ab69fce052721a22186563dfab23d383d8f069f3
[cacao.git] / src / threads / critical.c
1 /* src/threads/critical.c - restartable critical sections
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: threads.c 4903 2006-05-11 12:48:43Z edwin $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stddef.h>
33
34 #include "vm/types.h"
35
36 #include "threads/critical.h"
37
38 #include "toolbox/avl.h"
39
40 #include "vm/jit/asmpart.h"
41
42
43 /* the AVL tree containing the critical sections */
44
45 static avl_tree *criticaltree;
46
47
48 /* prototypes *****************************************************************/
49
50 static s4 critical_compare(const void *pa, const void *pb);
51 static void critical_register_asm_critical_sections(void);
52
53
54 /* critical_init ***************************************************************
55
56    Init global data structures.
57
58 *******************************************************************************/
59
60 void critical_init(void)
61 {
62     criticaltree = avl_create(&critical_compare);
63
64         critical_register_asm_critical_sections();
65 }
66
67
68 /* critical_compare ************************************************************
69
70    Comparison function for AVL tree of critical section.
71
72    IN:
73        pa...............first node
74            pb...............second node
75
76    RETURN VALUE:
77        -1, 0, +1 for (pa <, ==, > pb)
78
79 *******************************************************************************/
80
81 static s4 critical_compare(const void *pa, const void *pb)
82 {
83         const critical_section_node_t *na = pa;
84         const critical_section_node_t *nb = pb;
85
86         if (na->mcodebegin < nb->mcodebegin)
87                 return -1;
88         if (na->mcodebegin > nb->mcodebegin)
89                 return 1;
90         return 0;
91 }
92
93
94 /* critical_find ***************************************************************
95  
96    Find the critical region the given pc is in.
97
98    IN:
99        mcodeptr.........PC
100
101    OUT:
102        pointer to critical region node, or
103            NULL if critical region was not found.
104    
105 *******************************************************************************/
106
107 static const critical_section_node_t *critical_find(u1 *mcodeptr)
108 {
109     avl_node *n;
110     const critical_section_node_t *m;
111
112     n = criticaltree->root;
113         m = NULL;
114
115     if (!n)
116         return NULL;
117
118     for (;;) {
119         const critical_section_node_t *d = n->data;
120
121         if (mcodeptr == d->mcodebegin)
122             return d;
123
124         if (mcodeptr < d->mcodebegin) {
125             if (n->childs[0]) {
126                 n = n->childs[0];
127                         }
128             else {
129                 return m;
130                         }
131         }
132                 else {
133             if (n->childs[1]) {
134                 m = n->data;
135                 n = n->childs[1];
136             }
137                         else {
138                 return n->data;
139                         }
140         }
141     }
142 }
143
144
145 /* critical_register_critical_section ******************************************
146  
147    Register a critical section.
148
149    IN:
150        n................node for the critical section
151
152 *******************************************************************************/
153
154 void critical_register_critical_section(critical_section_node_t *n)
155 {
156         (void) avl_insert(criticaltree, n);
157 }
158
159
160 /* critical_find_restart_point *************************************************
161
162    Find a restart point for the given PC, in case it is in a critical section.
163
164    IN:
165        mcodeptr.........PC
166
167    OUT:
168        PC of the restart point, or
169            NULL if the given mcodeptr is not in a critical section
170
171 *******************************************************************************/
172
173 u1 *critical_find_restart_point(u1 *mcodeptr)
174 {
175         const critical_section_node_t *n = critical_find(mcodeptr);
176
177         /* XXX should we check >= n->mcodebegin */
178         return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
179 }
180
181
182 /* critical_register_asm_critical_sections *************************************
183
184    Register critical sections defined in the array asm_criticalsections.
185
186 *******************************************************************************/
187
188 static void critical_register_asm_critical_sections(void)
189 {
190         /* XXX TWISTI: this is just a quick hack */
191 #if defined(ENABLE_JIT) && defined(ENABLE_THREADS)
192         critical_section_node_t *n = &asm_criticalsections;
193
194         while (n->mcodebegin)
195                 critical_register_critical_section(n++);
196 #endif
197 }
198
199
200 /*
201  * These are local overrides for various environment variables in Emacs.
202  * Please do not remove this and leave it at the end of the file, where
203  * Emacs will automagically detect them.
204  * ---------------------------------------------------------------------
205  * Local variables:
206  * mode: c
207  * indent-tabs-mode: t
208  * c-basic-offset: 4
209  * tab-width: 4
210  * End:
211  * vim:noexpandtab:sw=4:ts=4:
212  */