Merging 7971:887db7d64bc9 with 7970:21b063622472.
[cacao.git] / src / threads / threadlist.c
1 /* src/threads/threadlist.c - different thread-lists
2
3    Copyright (C) 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29
30 #include "mm/memory.h"
31
32 #include "threads/threadlist.h"
33 #include "threads/threads-common.h"
34
35 #include "toolbox/list.h"
36
37 #include "vmcore/options.h"
38
39
40 /* global variables ***********************************************************/
41
42 static list_t *list_thread;                            /* global threads list */
43 static list_t *list_thread_free;                  /* global free threads list */
44 static list_t *list_thread_index_free;
45
46
47 typedef struct thread_index_t {
48         int32_t    index;
49         listnode_t linkage;
50 } thread_index_t;
51
52
53 /* threadlist_init *************************************************************
54
55    Initialize thread-lists.
56
57 *******************************************************************************/
58
59 void threadlist_init(void)
60 {
61         TRACESUBSYSTEMINITIALIZATION("threadlist_init");
62
63         /* Initialize the thread lists. */
64
65         list_thread            = list_create(OFFSET(threadobject, linkage));
66         list_thread_free       = list_create(OFFSET(threadobject, linkage_free));
67         list_thread_index_free = list_create(OFFSET(thread_index_t, linkage));
68
69         /* Initialize the implementation specific parts. */
70
71         threadlist_impl_init();
72 }
73
74
75 /* threadlist_add **************************************************************
76
77    Add the given threadobject as last entry to the thread list.
78
79    IN:
80        t ... threadobject to be added
81
82 *******************************************************************************/
83
84 void threadlist_add(threadobject *t)
85 {
86         list_add_last_unsynced(list_thread, t);
87 }
88
89
90 /* threadlist_remove ***********************************************************
91
92    Remove the given threadobject from the thread list.
93
94    IN:
95        t ... threadobject to be removed
96
97 *******************************************************************************/
98
99 void threadlist_remove(threadobject *t)
100 {
101         list_remove_unsynced(list_thread, t);
102 }
103
104
105 /* threadlist_first ************************************************************
106
107    Return the first entry in the thread list.
108
109    RETURN:
110        threadobject of the first entry
111
112 *******************************************************************************/
113
114 threadobject *threadlist_first(void)
115 {
116         threadobject *t;
117
118         t = list_first_unsynced(list_thread);
119
120         return t;
121 }
122
123
124 /* threadlist_next *************************************************************
125
126    Return the next entry in the thread list.
127
128    IN:
129        t ... threadobject to get next thread of
130
131    RETURN:
132        threadobject of the next entry
133
134 *******************************************************************************/
135
136 threadobject *threadlist_next(threadobject *t)
137 {
138         threadobject *next;
139
140         next = list_next_unsynced(list_thread, t);
141
142         return next;
143 }
144
145
146 /* threadlist_free_add *********************************************************
147
148    Add the given threadobject as last entry to the free thread list.
149
150    IN:
151        t ... threadobject to be added
152
153 *******************************************************************************/
154
155 void threadlist_free_add(threadobject *t)
156 {
157         list_add_last_unsynced(list_thread_free, t);
158 }
159
160
161 /* threadlist_free_remove ******************************************************
162
163    Remove the given entry from the free thread list.
164
165    IN:
166        t ... threadobject to be removed
167
168 *******************************************************************************/
169
170 void threadlist_free_remove(threadobject *t)
171 {
172         list_remove_unsynced(list_thread_free, t);
173 }
174
175
176 /* threadlist_free_first *******************************************************
177
178    Return the first entry in the free thread list.
179
180    RETURN:
181        threadobject of the first free entry
182
183 *******************************************************************************/
184
185 threadobject *threadlist_free_first(void)
186 {
187         threadobject *t;
188
189         t = list_first_unsynced(list_thread_free);
190
191         return t;
192 }
193
194
195 /* threadlist_get_non_daemons **************************************************
196
197    Return the number of non-daemon threads.
198
199    NOTE: This function does a linear-search over the threads list,
200          because it's only used for joining the threads.
201
202 *******************************************************************************/
203
204 int threadlist_get_non_daemons(void)
205 {
206         threadobject *t;
207         int           nondaemons;
208
209         /* Lock the thread lists. */
210
211         threadlist_lock();
212
213         nondaemons = 0;
214
215         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
216                 if (!(t->flags & THREAD_FLAG_DAEMON))
217                         nondaemons++;
218         }
219
220         /* Unlock the thread lists. */
221
222         threadlist_unlock();
223
224         return nondaemons;
225 }
226
227
228 /* threadlist_index_first ******************************************************
229
230    Return the first entry in the thread-index list.
231
232    RETURN VALUE:
233        thread-index structure
234
235 *******************************************************************************/
236
237 static inline thread_index_t *threadlist_index_first(void)
238 {
239         thread_index_t *ti;
240
241         ti = list_first_unsynced(list_thread_index_free);
242
243         return ti;
244 }
245
246
247 /* threadlist_index_add ********************************************************
248
249    Add the given thread-index to the thread-index free list.
250
251    IN:
252        i ... thread index
253
254 *******************************************************************************/
255
256 void threadlist_index_add(int index)
257 {
258         thread_index_t *ti;
259
260         ti = NEW(thread_index_t);
261
262 #if defined(ENABLE_STATISTICS)
263         if (opt_stat)
264                 size_thread_index_t += sizeof(thread_index_t);
265 #endif
266
267         /* Set the index in the structure. */
268
269         ti->index = index;
270
271         list_add_last_unsynced(list_thread_index_free, ti);
272 }
273
274
275 /* threadlist_index_remove *****************************************************
276
277    Remove the given thread-index from the thread-index list and free
278    the thread-index structure.
279
280    IN:
281        ti ... thread-index structure
282
283 *******************************************************************************/
284
285 static inline void threadlist_index_remove(thread_index_t *ti)
286 {
287         list_remove_unsynced(list_thread_index_free, ti);
288
289         FREE(ti, thread_index_t);
290
291 #if defined(ENABLE_STATISTICS)
292         if (opt_stat)
293                 size_thread_index_t -= sizeof(thread_index_t);
294 #endif
295 }
296
297
298 /* threadlist_get_free_index ***************************************************
299
300    Return a free thread index.
301
302    RETURN VALUE:
303        free thread index
304
305 *******************************************************************************/
306
307 int threadlist_get_free_index(void)
308 {
309         thread_index_t *ti;
310         int             index;
311
312         /* Try to get a thread index from the free-list. */
313
314         ti = threadlist_index_first();
315
316         /* Is a free thread index available? */
317
318         if (ti != NULL) {
319                 /* Yes, get the index and remove it from the free list. */
320
321                 index = ti->index;
322
323                 threadlist_index_remove(ti);
324         }
325         else {
326                 /* Get a new the thread index. */
327
328                 index = list_thread->size + 1;
329         }
330
331         return index;
332 }
333
334
335 /*
336  * These are local overrides for various environment variables in Emacs.
337  * Please do not remove this and leave it at the end of the file, where
338  * Emacs will automagically detect them.
339  * ---------------------------------------------------------------------
340  * Local variables:
341  * mode: c
342  * indent-tabs-mode: t
343  * c-basic-offset: 4
344  * tab-width: 4
345  * End:
346  * vim:noexpandtab:sw=4:ts=4:
347  */