Merged with tip.
[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/mutex.h"
33 #include "threads/threadlist.h"
34 #include "threads/thread.h"
35
36 #include "toolbox/list.h"
37
38 #include "vmcore/options.h"
39
40
41 /* global variables ***********************************************************/
42
43 static mutex_t threadlist_mutex;          /* global mutex for the thread list */
44
45 static list_t *list_thread;                            /* global threads list */
46 static list_t *list_thread_free;                  /* global free threads list */
47 static list_t *list_thread_index_free;
48
49
50 typedef struct thread_index_t {
51         int32_t    index;
52         listnode_t linkage;
53 } thread_index_t;
54
55
56 /* threadlist_init *************************************************************
57
58    Initialize thread-lists.
59
60 *******************************************************************************/
61
62 void threadlist_init(void)
63 {
64         TRACESUBSYSTEMINITIALIZATION("threadlist_init");
65
66         /* Initialize the thread list mutex. */
67
68         mutex_init(&threadlist_mutex);
69
70         /* Initialize the thread lists. */
71
72         list_thread            = list_create(OFFSET(threadobject, linkage));
73         list_thread_free       = list_create(OFFSET(threadobject, linkage_free));
74         list_thread_index_free = list_create(OFFSET(thread_index_t, linkage));
75 }
76
77
78 /* threadlist_lock *************************************************************
79
80    Enter the thread list mutex.
81
82    NOTE: We need this function as we can't use an internal lock for
83          the threads lists because the thread's lock is initialized in
84          threads_table_add (when we have the thread index), but we
85          already need the lock at the entry of the function.
86
87 *******************************************************************************/
88
89 void threadlist_lock(void)
90 {
91         mutex_lock(&threadlist_mutex);
92 }
93
94
95 /* threadlist_unlock *********************************************************
96
97    Leave the thread list mutex.
98
99 *******************************************************************************/
100
101 void threadlist_unlock(void)
102 {
103         mutex_unlock(&threadlist_mutex);
104 }
105
106
107 /* threadlist_add **************************************************************
108
109    Add the given threadobject as last entry to the thread list.
110
111    IN:
112        t ... threadobject to be added
113
114 *******************************************************************************/
115
116 void threadlist_add(threadobject *t)
117 {
118         list_add_last(list_thread, t);
119 }
120
121
122 /* threadlist_remove ***********************************************************
123
124    Remove the given threadobject from the thread list.
125
126    IN:
127        t ... threadobject to be removed
128
129 *******************************************************************************/
130
131 void threadlist_remove(threadobject *t)
132 {
133         list_remove(list_thread, t);
134 }
135
136
137 /* threadlist_first ************************************************************
138
139    Return the first entry in the thread list.
140
141    RETURN:
142        threadobject of the first entry
143
144 *******************************************************************************/
145
146 threadobject *threadlist_first(void)
147 {
148         threadobject *t;
149
150         t = list_first(list_thread);
151
152         return t;
153 }
154
155
156 /* threadlist_next *************************************************************
157
158    Return the next entry in the thread list.
159
160    IN:
161        t ... threadobject to get next thread of
162
163    RETURN:
164        threadobject of the next entry
165
166 *******************************************************************************/
167
168 threadobject *threadlist_next(threadobject *t)
169 {
170         threadobject *next;
171
172         next = list_next(list_thread, t);
173
174         return next;
175 }
176
177
178 /* threadlist_free_add *********************************************************
179
180    Add the given threadobject as last entry to the free thread list.
181
182    IN:
183        t ... threadobject to be added
184
185 *******************************************************************************/
186
187 void threadlist_free_add(threadobject *t)
188 {
189         list_add_last(list_thread_free, t);
190 }
191
192
193 /* threadlist_free_remove ******************************************************
194
195    Remove the given entry from the free thread list.
196
197    IN:
198        t ... threadobject to be removed
199
200 *******************************************************************************/
201
202 void threadlist_free_remove(threadobject *t)
203 {
204         list_remove(list_thread_free, t);
205 }
206
207
208 /* threadlist_free_first *******************************************************
209
210    Return the first entry in the free thread list.
211
212    RETURN:
213        threadobject of the first free entry
214
215 *******************************************************************************/
216
217 threadobject *threadlist_free_first(void)
218 {
219         threadobject *t;
220
221         t = list_first(list_thread_free);
222
223         return t;
224 }
225
226
227 /* threadlist_get_non_daemons **************************************************
228
229    Return the number of non-daemon threads.
230
231    NOTE: This function does a linear-search over the threads list,
232          because it's only used for joining the threads.
233
234 *******************************************************************************/
235
236 int threadlist_get_non_daemons(void)
237 {
238         threadobject *t;
239         int           nondaemons;
240
241         /* Lock the thread lists. */
242
243         threadlist_lock();
244
245         nondaemons = 0;
246
247         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
248                 if (!thread_is_daemon(t))
249                         nondaemons++;
250         }
251
252         /* Unlock the thread lists. */
253
254         threadlist_unlock();
255
256         return nondaemons;
257 }
258
259
260 /* threadlist_index_first ******************************************************
261
262    Return the first entry in the thread-index list.
263
264    RETURN VALUE:
265        thread-index structure
266
267 *******************************************************************************/
268
269 static inline thread_index_t *threadlist_index_first(void)
270 {
271         thread_index_t *ti;
272
273         ti = list_first(list_thread_index_free);
274
275         return ti;
276 }
277
278
279 /* threadlist_index_add ********************************************************
280
281    Add the given thread-index to the thread-index free list.
282
283    IN:
284        i ... thread index
285
286 *******************************************************************************/
287
288 void threadlist_index_add(int index)
289 {
290         thread_index_t *ti;
291
292         ti = NEW(thread_index_t);
293
294 #if defined(ENABLE_STATISTICS)
295         if (opt_stat)
296                 size_thread_index_t += sizeof(thread_index_t);
297 #endif
298
299         /* Set the index in the structure. */
300
301         ti->index = index;
302
303         list_add_last(list_thread_index_free, ti);
304 }
305
306
307 /* threadlist_index_remove *****************************************************
308
309    Remove the given thread-index from the thread-index list and free
310    the thread-index structure.
311
312    IN:
313        ti ... thread-index structure
314
315 *******************************************************************************/
316
317 static inline void threadlist_index_remove(thread_index_t *ti)
318 {
319         list_remove(list_thread_index_free, ti);
320
321         FREE(ti, thread_index_t);
322
323 #if defined(ENABLE_STATISTICS)
324         if (opt_stat)
325                 size_thread_index_t -= sizeof(thread_index_t);
326 #endif
327 }
328
329
330 /* threadlist_get_free_index ***************************************************
331
332    Return a free thread index.
333
334    RETURN VALUE:
335        free thread index
336
337 *******************************************************************************/
338
339 int threadlist_get_free_index(void)
340 {
341         thread_index_t *ti;
342         int             index;
343
344         /* Try to get a thread index from the free-list. */
345
346         ti = threadlist_index_first();
347
348         /* Is a free thread index available? */
349
350         if (ti != NULL) {
351                 /* Yes, get the index and remove it from the free list. */
352
353                 index = ti->index;
354
355                 threadlist_index_remove(ti);
356         }
357         else {
358                 /* Get a new the thread index. */
359
360                 index = list_thread->size + 1;
361         }
362
363         return index;
364 }
365
366
367 /*
368  * These are local overrides for various environment variables in Emacs.
369  * Please do not remove this and leave it at the end of the file, where
370  * Emacs will automagically detect them.
371  * ---------------------------------------------------------------------
372  * Local variables:
373  * mode: c
374  * indent-tabs-mode: t
375  * c-basic-offset: 4
376  * tab-width: 4
377  * End:
378  * vim:noexpandtab:sw=4:ts=4:
379  */