* src/threads/threads-common.c (threads_create_thread): Renamed to
[cacao.git] / src / threads / threads-common.c
1 /* src/threads/threads-common.c - machine independent thread functions
2
3    Copyright (C) 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-common.c 7811 2007-04-25 18:33:30Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "native/jni.h"
37
38 #include "native/include/java_lang_Object.h"
39 #include "native/include/java_lang_String.h"
40 #include "native/include/java_lang_Thread.h"
41
42 #if defined(WITH_CLASSPATH_GNU)
43 # include "native/include/java_lang_VMThread.h"
44 #endif
45
46 #include "threads/threads-common.h"
47
48 #include "threads/native/threads.h"
49
50 #include "vm/builtin.h"
51 #include "vm/stringlocal.h"
52 #include "vm/vm.h"
53
54 #include "vm/jit/stacktrace.h"
55
56 #include "vmcore/class.h"
57
58 #if defined(ENABLE_STATISTICS)
59 # include "vmcore/options.h"
60 # include "vmcore/statistics.h"
61 #endif
62
63 #include "vmcore/utf8.h"
64
65
66 /* threads_create_thread *******************************************************
67
68    Creates and initializes an internal thread data-structure.
69
70 *******************************************************************************/
71
72 threadobject *threads_create_thread(void)
73 {
74         threadobject *thread;
75
76         /* allocate internal thread data-structure */
77
78 #if defined(ENABLE_GC_BOEHM)
79         thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
80 #else
81         thread = NEW(threadobject);
82 #endif
83
84 #if defined(ENABLE_STATISTICS)
85         if (opt_stat)
86                 size_threadobject += sizeof(threadobject);
87 #endif
88
89         /* initialize thread data structure */
90
91         threads_init_threadobject(thread);
92         lock_init_execution_env(thread);
93
94         return thread;
95 }
96
97
98 /* threads_thread_create_internal **********************************************
99
100    Creates an internal thread data-structure with the given name, plus
101    necessary Java objects for the VM (e.g. finalizer-thread,
102    signal-thread, ...).
103
104 *******************************************************************************/
105
106 threadobject *threads_thread_create_internal(utf *name)
107 {
108         threadobject       *thread;
109         java_lang_Thread   *t;
110 #if defined(WITH_CLASSPATH_GNU)
111         java_lang_VMThread *vmt;
112 #endif
113
114         /* create internal thread data-structure */
115
116         thread = threads_create_thread();
117
118         /* create the java thread object */
119
120         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
121
122         if (t == NULL)
123                 return NULL;
124
125 #if defined(WITH_CLASSPATH_GNU)
126         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
127
128         if (vmt == NULL)
129                 return NULL;
130
131         vmt->thread = t;
132         vmt->vmdata = (java_lang_Object *) thread;
133
134         t->vmThread = vmt;
135 #elif defined(WITH_CLASSPATH_CLDC1_1)
136         t->vm_thread = (java_lang_Object *) thread;
137 #endif
138
139         thread->object     = t;
140         thread->flags      = THREAD_FLAG_DAEMON;
141
142         /* set java.lang.Thread fields */
143
144         t->name     = (java_lang_String *) javastring_new(name);
145 #if defined(ENABLE_JAVASE)
146         t->daemon   = true;
147 #endif
148         t->priority = NORM_PRIORITY;
149
150         /* return the thread data-structure */
151
152         return thread;
153 }
154
155
156 /* threads_start_javathread ****************************************************
157
158    Start a thread in the JVM. Only the java thread object exists so far.
159
160    IN:
161       object.....the java thread object java.lang.Thread
162
163 *******************************************************************************/
164
165 void threads_start_javathread(java_lang_Thread *object)
166 {
167         threadobject *thread;
168
169         /* create internal thread data-structure */
170
171         thread = threads_create_thread();
172
173         /* link the two objects together */
174
175         thread->object = object;
176
177 #if defined(ENABLE_JAVASE)
178         /* is this a daemon thread? */
179
180         if (object->daemon == true)
181                 thread->flags |= THREAD_FLAG_DAEMON;
182 #endif
183
184 #if defined(WITH_CLASSPATH_GNU)
185         assert(object->vmThread);
186         assert(object->vmThread->vmdata == NULL);
187
188         object->vmThread->vmdata = (java_lang_Object *) thread;
189 #elif defined(WITH_CLASSPATH_CLDC1_1)
190         object->vm_thread = (java_lang_Object *) thread;
191 #endif
192
193         /* Actually start the thread.  Don't pass a function pointer
194            (NULL) since we want Thread.run()V here. */
195
196         threads_start_thread(thread, NULL);
197 }
198
199
200 /* threads_get_current_tid *****************************************************
201
202    Return the tid of the current thread.
203    
204    RETURN VALUE:
205        the current tid
206
207 *******************************************************************************/
208
209 ptrint threads_get_current_tid(void)
210 {
211         threadobject *thread;
212
213         thread = THREADOBJECT;
214
215         /* this may happen during bootstrap */
216
217         if (thread == NULL)
218                 return 0;
219
220         return (ptrint) thread->tid;
221 }
222
223
224 /* threads_thread_get_state ****************************************************
225
226    Returns the current state of the given thread.
227
228 *******************************************************************************/
229
230 utf *threads_thread_get_state(threadobject *thread)
231 {
232         utf *u;
233
234         switch (thread->state) {
235         case THREAD_STATE_NEW:
236                 u = utf_new_char("NEW");
237                 break;
238         case THREAD_STATE_RUNNABLE:
239                 u = utf_new_char("RUNNABLE");
240                 break;
241         case THREAD_STATE_BLOCKED:
242                 u = utf_new_char("BLOCKED");
243                 break;
244         case THREAD_STATE_WAITING:
245                 u = utf_new_char("WAITING");
246                 break;
247         case THREAD_STATE_TIMED_WAITING:
248                 u = utf_new_char("TIMED_WAITING");
249                 break;
250         case THREAD_STATE_TERMINATED:
251                 u = utf_new_char("TERMINATED");
252                 break;
253         default:
254                 vm_abort("threads_get_state: unknown thread state %d", thread->state);
255         }
256
257         return u;
258 }
259
260
261 /* threads_thread_is_alive *****************************************************
262
263    Returns if the give thread is alive.
264
265 *******************************************************************************/
266
267 bool threads_thread_is_alive(threadobject *thread)
268 {
269         bool result;
270
271         switch (thread->state) {
272         case THREAD_STATE_NEW:
273         case THREAD_STATE_TERMINATED:
274                 result = false;
275                 break;
276
277         case THREAD_STATE_RUNNABLE:
278         case THREAD_STATE_BLOCKED:
279         case THREAD_STATE_WAITING:
280         case THREAD_STATE_TIMED_WAITING:
281                 result = true;
282                 break;
283
284         default:
285                 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
286         }
287
288         return result;
289 }
290
291
292 /* threads_dump ****************************************************************
293
294    Dumps info for all threads running in the JVM.  This function is
295    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
296
297 *******************************************************************************/
298
299 void threads_dump(void)
300 {
301         threadobject     *thread;
302         java_lang_Thread *t;
303         utf              *name;
304
305         /* XXX we should stop the world here */
306
307         printf("Full thread dump CACAO "VERSION":\n");
308
309         /* iterate over all started threads */
310
311         thread = mainthreadobj;
312
313         do {
314                 /* get thread object */
315
316                 t = thread->object;
317
318                 /* the thread may be currently in initalization, don't print it */
319
320                 if (t != NULL) {
321                         /* get thread name */
322
323 #if defined(ENABLE_JAVASE)
324                         name = javastring_toutf((java_objectheader *) t->name, false);
325 #elif defined(ENABLE_JAVAME_CLDC1_1)
326                         name = t->name;
327 #endif
328
329                         printf("\n\"");
330                         utf_display_printable_ascii(name);
331                         printf("\"");
332
333                         if (thread->flags & THREAD_FLAG_DAEMON)
334                                 printf(" daemon");
335
336                         printf(" prio=%d", t->priority);
337
338 #if SIZEOF_VOID_P == 8
339                         printf(" tid=0x%016lx (%ld)",
340                                    (ptrint) thread->tid, (ptrint) thread->tid);
341 #else
342                         printf(" tid=0x%08lx (%ld)",
343                                    (ptrint) thread->tid, (ptrint) thread->tid);
344 #endif
345
346                         /* print thread state */
347
348                         switch (thread->state) {
349                         case THREAD_STATE_NEW:
350                                 printf(" new");
351                                 break;
352                         case THREAD_STATE_RUNNABLE:
353                                 printf(" runnable");
354                                 break;
355                         case THREAD_STATE_BLOCKED:
356                                 printf(" blocked");
357                                 break;
358                         case THREAD_STATE_WAITING:
359                                 printf(" waiting");
360                                 break;
361                         case THREAD_STATE_TIMED_WAITING:
362                                 printf(" waiting on condition");
363                                 break;
364                         case THREAD_STATE_TERMINATED:
365                                 printf(" terminated");
366                                 break;
367                         default:
368                                 vm_abort("threads_dump: unknown thread state %d",
369                                                  thread->state);
370                         }
371
372                         printf("\n");
373
374                         /* print trace of thread */
375
376                         threads_thread_print_stacktrace(thread);
377                 }
378
379                 thread = thread->next;
380         } while ((thread != NULL) && (thread != mainthreadobj));
381 }
382
383
384 /* threads_thread_print_stacktrace *********************************************
385
386    Print the current stacktrace of the current thread.
387
388 *******************************************************************************/
389
390 void threads_thread_print_stacktrace(threadobject *thread)
391 {
392         stackframeinfo   *sfi;
393         stacktracebuffer *stb;
394         s4                dumpsize;
395
396         /* mark start of dump memory area */
397
398         dumpsize = dump_size();
399
400         /* create a stacktrace for the passed thread */
401
402         sfi = thread->_stackframeinfo;
403
404         stb = stacktrace_create(sfi);
405
406         /* print stacktrace */
407
408         if (stb != NULL)
409                 stacktrace_print_trace_from_buffer(stb);
410         else {
411                 puts("\t<<No stacktrace available>>");
412                 fflush(stdout);
413         }
414
415         dump_release(dumpsize);
416 }
417
418
419 /* threads_print_stacktrace ****************************************************
420
421    Print the current stacktrace of the current thread.
422
423 *******************************************************************************/
424
425 void threads_print_stacktrace(void)
426 {
427         threadobject *thread;
428
429         thread = THREADOBJECT;
430
431         threads_thread_print_stacktrace(thread);
432 }
433
434
435 /*
436  * These are local overrides for various environment variables in Emacs.
437  * Please do not remove this and leave it at the end of the file, where
438  * Emacs will automagically detect them.
439  * ---------------------------------------------------------------------
440  * Local variables:
441  * mode: c
442  * indent-tabs-mode: t
443  * c-basic-offset: 4
444  * tab-width: 4
445  * End:
446  * vim:noexpandtab:sw=4:ts=4:
447  */