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