* src/threads/thread.cpp: Use a finalizer to remove dead threads.
[cacao.git] / src / threads / threadlist.cpp
1 /* src/threads/threadlist.cpp - thread list
2
3    Copyright (C) 2008, 2009
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 <algorithm>
31
32 #include "threads/mutex.hpp"
33 #include "threads/threadlist.hpp"
34 #include "threads/thread.hpp"
35
36 #include "toolbox/list.hpp"
37 #include "toolbox/logging.hpp"
38
39 #include "vm/jit/stacktrace.hpp"
40
41
42 /* class variables */
43
44 Mutex               ThreadList::_mutex;                // a mutex for all thread lists
45
46 List<threadobject*> ThreadList::_active_thread_list;   // list of active threads
47 List<threadobject*> ThreadList::_free_thread_list;     // list of free threads
48 List<int32_t>       ThreadList::_free_index_list;      // list of free thread indexes
49
50 int32_t             ThreadList::_number_of_started_java_threads;
51 int32_t             ThreadList::_number_of_active_java_threads;
52 int32_t             ThreadList::_peak_of_active_java_threads;
53 int32_t             ThreadList::_number_of_non_daemon_threads;
54
55
56 /**
57  * Dumps info for all threads running in the VM.  This function is
58  * called when SIGQUIT (<ctrl>-\) is sent to the VM.
59  */
60 void ThreadList::dump_threads()
61 {
62         // XXX we should stop the world here and remove explicit
63         //     thread suspension from the loop below.
64         // Lock the thread lists.
65         lock();
66
67         printf("Full thread dump CACAO "VERSION_FULL":\n");
68
69         // Iterate over all started threads.
70         threadobject* self = THREADOBJECT;
71         for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
72                 threadobject* t = *it;
73
74                 // Ignore threads which are in state NEW.
75                 if (t->state == THREAD_STATE_NEW)
76                         continue;
77
78                 /* Suspend the thread (and ignore return value). */
79
80                 if (t != self)
81                         (void) threads_suspend_thread(t, SUSPEND_REASON_DUMP);
82
83                 /* Print thread info. */
84
85                 printf("\n");
86                 thread_print_info(t);
87                 printf("\n");
88
89                 /* Print trace of thread. */
90
91                 stacktrace_print_of_thread(t);
92
93                 /* Resume the thread (and ignore return value). */
94
95                 if (t != self)
96                         (void) threads_resume_thread(t, SUSPEND_REASON_DUMP);
97         }
98
99         // Unlock the thread lists.
100         unlock();
101 }
102
103
104 /**
105  * Fills the passed list with all currently active threads. Creating a copy
106  * of the thread list here, is the only way to ensure we do not end up in a
107  * dead-lock when iterating over the list.
108  *
109  * @param list list class to be filled
110  */
111 void ThreadList::get_active_threads(List<threadobject*> &list)
112 {
113         // Lock the thread lists.
114         lock();
115
116         // Use the assignment operator to create a copy of the thread list.
117         list = _active_thread_list;
118
119         // Unlock the thread lists.
120         unlock();
121 }
122
123
124 /**
125  * Fills the passed list with all currently active threads which should be
126  * visible to Java. Creating a copy of the thread list here, is the only way
127  * to ensure we do not end up in a dead-lock when iterating over the list.
128  *
129  * @param list list class to be filled
130  */
131 void ThreadList::get_active_java_threads(List<threadobject*> &list)
132 {
133         // Lock the thread lists.
134         lock();
135
136         // Iterate over all active threads.
137         for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
138                 threadobject* t = *it;
139
140                 // We skip internal threads.
141                 if (t->flags & THREAD_FLAG_INTERNAL)
142                         continue;
143
144                 list.push_back(t);
145         }
146
147         // Unlock the thread lists.
148         unlock();
149 }
150
151
152 /**
153  * Return a free thread object.
154  *
155  * @return free thread object or NULL if none available
156  */
157 threadobject* ThreadList::get_free_thread()
158 {
159         threadobject* t = NULL;
160
161         lock();
162
163         // Do we have free threads in the free-list?
164         if (_free_thread_list.empty() == false) {
165                 // Yes, get the index and remove it from the free list.
166                 t = _free_thread_list.front();
167                 _free_thread_list.remove(t);
168         }
169
170         unlock();
171
172         return t;
173 }
174
175
176 /**
177  * Return a free thread index.
178  *
179  * @return free thread index
180  */
181 int32_t ThreadList::get_free_thread_index()
182 {
183         int32_t index;
184
185         lock();
186
187         // Do we have free indexes in the free-list?
188         if (_free_index_list.empty() == false) {
189                 // Yes, get the index and remove it from the free list.
190                 index = _free_index_list.front();
191                 _free_index_list.remove(index);
192         }
193         else {
194                 // Get a new the thread index.
195                 index = _active_thread_list.size() + 1;
196         }
197
198         unlock();
199
200         return index;
201 }
202
203
204 /**
205  * Return the number of daemon threads visible to Java.
206  *
207  * NOTE: This function does a linear-search over the threads list,
208  *       because it is only used by the management interface.
209  *
210  * @return number of daemon threads
211  */
212 int32_t ThreadList::get_number_of_daemon_java_threads(void)
213 {
214         int number = 0;
215
216         // Lock the thread lists.
217         lock();
218
219         // Iterate over all active threads.
220         for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
221                 threadobject* t = *it;
222
223                 // We skip internal threads.
224                 if (t->flags & THREAD_FLAG_INTERNAL)
225                         continue;
226
227                 if (thread_is_daemon(t))
228                         number++;
229         }
230
231         // Unlock the thread lists.
232         unlock();
233
234         return number;
235 }
236
237
238 /**
239  * Return the number of non-daemon threads.
240  *
241  * NOTE: This function does a linear-search over the threads list,
242  *       because it is only used for joining the threads.
243  *
244  * @return number of non daemon threads
245  */
246 int32_t ThreadList::get_number_of_non_daemon_threads(void)
247 {
248         int nondaemons = 0;
249
250         lock();
251
252         for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
253                 threadobject* t = *it;
254
255                 if (!thread_is_daemon(t))
256                         nondaemons++;
257         }
258
259         unlock();
260
261         return nondaemons;
262 }
263
264
265 /**
266  * Return the thread object with the given index.
267  *
268  * @return thread object
269  */
270 threadobject* ThreadList::get_thread_by_index(int32_t index)
271 {
272         lock();
273
274         List<threadobject*>::iterator it = find_if(_active_thread_list.begin(), _active_thread_list.end(), std::bind2nd(comparator(), index));
275
276         // No thread found.
277         if (it == _active_thread_list.end()) {
278                 unlock();
279                 return NULL;
280         }
281
282         threadobject* t = *it;
283
284         // The thread found is in state new.
285         if (t->state == THREAD_STATE_NEW) {
286                 unlock();
287                 return NULL;
288         }
289
290         unlock();
291         return t;
292 }
293
294
295 /**
296  * Return the Java thread object from the given thread object.
297  *
298  * @return Java thread object
299  */
300 threadobject* ThreadList::get_thread_from_java_object(java_handle_t* h)
301 {
302         List<threadobject*>::iterator it;
303         threadobject* t;
304         bool          equal;
305
306         lock();
307
308         for (it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
309                 t = *it;
310
311                 LLNI_equals(t->object, h, equal);
312
313                 if (equal == true) {
314                         unlock();
315                         return t;
316                 }
317         }
318
319         unlock();
320
321         return NULL;
322 }
323
324 void ThreadList::deactivate_thread(threadobject *t)
325 {
326         ThreadListLocker lock;
327         remove_from_active_thread_list(t);
328         threads_impl_clear_heap_pointers(t); // allow it to be garbage collected
329 }
330
331 /**
332  * Release the thread.
333  *
334  * @return free thread index
335  */
336 void ThreadList::release_thread(threadobject* t, bool needs_deactivate)
337 {
338         lock();
339
340         if (needs_deactivate)
341                 // Move thread from active thread list to free thread list.
342                 remove_from_active_thread_list(t);
343         else
344                 assert(!t->is_in_active_list);
345
346         add_to_free_thread_list(t);
347
348         // Add thread index to free index list.
349         add_to_free_index_list(t->index);
350
351         unlock();
352 }
353
354
355 /* C interface functions ******************************************************/
356
357 extern "C" {
358         void ThreadList_lock() { ThreadList::lock(); }
359         void ThreadList_unlock() { ThreadList::unlock(); }
360         void ThreadList_dump_threads() { ThreadList::dump_threads(); }
361         threadobject* ThreadList_get_free_thread() { return ThreadList::get_free_thread(); }
362         int32_t ThreadList_get_free_thread_index() { return ThreadList::get_free_thread_index(); }
363         void ThreadList_add_to_active_thread_list(threadobject* t) { ThreadList::add_to_active_thread_list(t); }
364         threadobject* ThreadList_get_thread_by_index(int32_t index) { return ThreadList::get_thread_by_index(index); }
365         threadobject* ThreadList_get_main_thread() { return ThreadList::get_main_thread(); }
366         threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h) { return ThreadList::get_thread_from_java_object(h); }
367
368         int32_t ThreadList_get_number_of_non_daemon_threads() { return ThreadList::get_number_of_non_daemon_threads(); }
369 }
370
371 /*
372  * These are local overrides for various environment variables in Emacs.
373  * Please do not remove this and leave it at the end of the file, where
374  * Emacs will automagically detect them.
375  * ---------------------------------------------------------------------
376  * Local variables:
377  * mode: c++
378  * indent-tabs-mode: t
379  * c-basic-offset: 4
380  * tab-width: 4
381  * End:
382  * vim:noexpandtab:sw=4:ts=4:
383  */