Fix LDC, LDC_W, and INSTANCEOF opcodes, more debugging
[jamvm-avr32-jem.git] / src / thread.c
blob8f9bce569aadcd3ead84e746014f25657fa13026
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007
3 * Robert Lougher <rob@lougher.org.uk>.
5 * This file is part of JamVM.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <signal.h>
26 #include <sched.h>
28 #include "jam.h"
29 #include "thread.h"
30 #include "lock.h"
31 #include "hash.h"
33 #ifdef TRACETHREAD
34 #define TRACE(fmt, ...) jam_printf(fmt, ## __VA_ARGS__)
35 #else
36 #define TRACE(fmt, ...)
37 #endif
39 #define HASHTABSZE 1<<4
40 HashTable thread_id_map;
42 /* Size of Java stack to use if no size is given */
43 static int dflt_stack_size;
45 /* Thread create/destroy lock and condvar */
46 static pthread_mutex_t lock;
47 static pthread_cond_t cv;
49 /* lock and condvar used by main thread to wait for
50 * all non-daemon threads to die */
51 static pthread_mutex_t exit_lock;
52 static pthread_cond_t exit_cv;
54 /* Monitor for sleeping threads to do a timed-wait against */
55 static Monitor sleep_mon;
57 /* Thread specific key holding thread's Thread pntr */
58 static pthread_key_t threadKey;
60 /* Attributes for spawned threads */
61 static pthread_attr_t attributes;
63 /* The main thread info - head of the thread list */
64 static Thread main_thread;
66 /* Main thread ExecEnv */
67 static ExecEnv main_ee;
69 /* Various field offsets into java.lang.Thread &
70 java.lang.VMThread - cached at startup and used
71 in thread creation */
72 static int vmData_offset;
73 static int daemon_offset;
74 static int group_offset;
75 static int priority_offset;
76 static int name_offset;
77 static int vmthread_offset;
78 static int thread_offset;
79 static int threadId_offset;
81 /* Method table indexes of Thread.run method and
82 * ThreadGroup.removeThread - cached at startup */
83 static int run_mtbl_idx;
84 static int rmveThrd_mtbl_idx;
86 static MethodBlock *addThread_mb;
87 static MethodBlock *init_mb;
89 /* Cached java.lang.Thread class */
90 static Class *thread_class;
91 static Class *vmthread_class;
93 /* Count of non-daemon threads still running in VM */
94 static int non_daemon_thrds = 0;
96 /* Counts used in the ThreadMXBean management API. The
97 counts start from one to include the main thread */
98 static int threads_count = 1;
99 static int peak_threads_count = 1;
100 static long long total_started_threads_count = 1;
102 /* Guards against threads starting while the "world is stopped" */
103 static int all_threads_suspended = FALSE;
104 static int threads_waiting_to_start = 0;
106 static int main_exited = FALSE;
108 /* Bitmap - used for generating unique thread ID's */
109 #define MAP_INC 32
110 static unsigned int *tidBitmap = NULL;
111 static int tidBitmapSize = 0;
113 /* Mark a threadID value as no longer used */
114 #define freeThreadID(n) tidBitmap[(n-1)>>5] &= ~(1<<((n-1)&0x1f))
116 /* Generate a new thread ID - assumes the thread queue
117 * lock is held */
119 static int genThreadID() {
120 int i = 0;
122 retry:
123 for(; i < tidBitmapSize; i++) {
124 if(tidBitmap[i] != 0xffffffff) {
125 int n = ffs(~tidBitmap[i]);
126 tidBitmap[i] |= 1 << (n-1);
127 return (i<<5) + n;
131 tidBitmap = (unsigned int *)sysRealloc(tidBitmap,
132 (tidBitmapSize + MAP_INC) * sizeof(unsigned int));
133 memset(tidBitmap + tidBitmapSize, 0, MAP_INC * sizeof(unsigned int));
134 tidBitmapSize += MAP_INC;
135 goto retry;
138 int threadIsAlive(Thread *thread) {
139 return thread->state != 0;
142 int threadInterrupted(Thread *thread) {
143 int r = thread->interrupted;
144 thread->interrupted = FALSE;
145 return r;
148 int threadIsInterrupted(Thread *thread) {
149 return thread->interrupted;
152 void threadSleep(Thread *thread, long long ms, int ns) {
154 /* A sleep of zero should just yield, but a wait
155 of zero is "forever". Therefore wait for a tiny
156 amount -- this should yield and we also get the
157 interrupted checks. */
158 if(ms == 0 && ns == 0)
159 ns = 1;
161 monitorLock(&sleep_mon, thread);
162 monitorWait(&sleep_mon, thread, ms, ns);
163 monitorUnlock(&sleep_mon, thread);
166 void threadYield(Thread *thread) {
167 sched_yield();
170 void threadInterrupt(Thread *thread) {
171 Monitor *mon;
172 Thread *self = threadSelf();
174 /* monitorWait sets wait_mon _before_ checking interrupted status. Therefore,
175 if wait_mon is null, interrupted status will be noticed. This guards
176 against a race-condition leading to an interrupt being missed. The memory
177 barrier ensures correct ordering on SMP systems. */
178 thread->interrupted = TRUE;
179 MBARRIER();
181 if((mon = thread->wait_mon) != NULL && thread->wait_next != NULL) {
182 int locked;
183 thread->interrupting = TRUE;
185 /* Ensure the thread has actually entered the wait
186 (else the signal will be lost) */
188 while(!(locked = !pthread_mutex_trylock(&mon->lock)) && mon->owner == NULL)
189 sched_yield();
191 pthread_cond_signal(&thread->wait_cv);
193 if(locked)
194 pthread_mutex_unlock(&mon->lock);
197 /* Handle the case where the thread is blocked in a system call.
198 This will knock it out with an EINTR. The suspend signal
199 handler will just return (as in the user doing a kill), and do
200 nothing otherwise. */
202 /* Note, under Linuxthreads pthread_kill obtains a lock on the thread
203 being signalled. If another thread is suspending all threads,
204 and the interrupting thread is earlier in the thread list than the
205 thread being interrupted, it can be suspended holding the lock.
206 When the suspending thread tries to signal the interrupted thread
207 it will deadlock. To prevent this, disable suspension. */
209 fastDisableSuspend(self);
210 pthread_kill(thread->tid, SIGUSR1);
211 fastEnableSuspend(self);
214 void *getStackTop(Thread *thread) {
215 return thread->stack_top;
218 void *getStackBase(Thread *thread) {
219 return thread->stack_base;
222 Thread *threadSelf0(Object *vmThread) {
223 return (Thread*)(INST_DATA(vmThread)[vmData_offset]);
226 Thread *threadSelf() {
227 return (Thread*)pthread_getspecific(threadKey);
230 void setThreadSelf(Thread *thread) {
231 pthread_setspecific(threadKey, thread);
232 pthread_cond_init(&thread->wait_cv, NULL);
235 ExecEnv *getExecEnv() {
236 return threadSelf()->ee;
239 char *getThreadStateString(Thread *thread) {
240 switch(thread->state) {
241 case CREATING:
242 case STARTED:
243 return "NEW";
244 case RUNNING:
245 case SUSPENDED:
246 return "RUNNABLE";
247 case WAITING:
248 return "WAITING";
249 case TIMED_WAITING:
250 return "TIMED_WAITING";
251 case BLOCKED:
252 return "BLOCKED";
254 return "INVALID";
257 int getThreadsCount() {
258 return threads_count;
261 int getPeakThreadsCount() {
262 return peak_threads_count;
265 long long getTotalStartedThreadsCount() {
266 return total_started_threads_count;
269 void resetPeakThreadsCount() {
270 Thread *self = threadSelf();
272 /* Grab the thread lock to protect against
273 concurrent update by threads starting/dying */
274 disableSuspend(self);
275 pthread_mutex_lock(&lock);
276 peak_threads_count = threads_count;
277 pthread_mutex_unlock(&lock);
278 enableSuspend(self);
281 void initialiseJavaStack(ExecEnv *ee) {
282 int stack_size = ee->stack_size ?
283 (ee->stack_size > MIN_STACK ? ee->stack_size : MIN_STACK) : dflt_stack_size;
284 char *stack = sysMalloc(stack_size);
285 MethodBlock *mb = (MethodBlock *) stack;
286 Frame *top = (Frame *) (mb+1);
288 top->ostack = (uintptr_t*)(top+1);
289 #ifndef JEM
290 top->lvars = (uintptr_t*)top;
291 #else
292 /* We also need lvars_jem for frame-address calculation, even with no local variables. */
293 top->lvars_jem = (uintptr_t*)top;
294 #endif
295 mb->max_stack = 0;
296 top->prev = NULL;
297 top->mb = mb;
299 ee->stack = stack;
300 ee->last_frame = top;
301 ee->stack_size = stack_size;
302 ee->stack_end = stack + stack_size-STACK_RED_ZONE_SIZE;
305 long long javaThreadId(Thread *thread) {
306 return *(long long*)&(INST_DATA(thread->ee->thread)[threadId_offset]);
309 Thread *findHashedThread(Thread *thread, long long id) {
311 #define FOUND(ptr) ptr
312 #define DELETED ((void*)-1)
313 #define PREPARE(thread_id) thread
314 #define SCAVENGE(ptr) ptr == DELETED
315 #define HASH(thread_id) (int)thread_id
316 #define COMPARE(thread_id, ptr, hash1, hash2) ptr != DELETED && \
317 (hash1 == hash2 && thread_id == javaThreadId(ptr))
319 Thread *ptr;
321 /* Add if absent, scavenge, locked */
322 findHashEntry(thread_id_map, id, ptr, (thread != NULL), TRUE, TRUE);
324 return ptr;
327 void addThreadToHash(Thread *thread) {
328 findHashedThread(thread, javaThreadId(thread));
331 Thread *findThreadById(long long id) {
332 return findHashedThread(NULL, id);
335 void deleteThreadFromHash(Thread *thread) {
337 #undef HASH
338 #undef COMPARE
339 #define HASH(ptr) (int)javaThreadId(ptr)
340 #define COMPARE(ptr1, ptr2, hash1, hash2) ptr1 == ptr2
342 deleteHashEntry(thread_id_map, thread, TRUE);
345 static Object *initJavaThread(Thread *thread, char is_daemon, char *name) {
346 Object *vmthread, *jlthread, *thread_name = NULL;
348 /* Create the java.lang.Thread object and the VMThread */
349 if((vmthread = allocObject(vmthread_class)) == NULL ||
350 (jlthread = allocObject(thread_class)) == NULL)
351 return NULL;
353 thread->ee->thread = jlthread;
354 INST_DATA(vmthread)[vmData_offset] = (uintptr_t)thread;
355 #if JAM_ON_STACK
356 INST_DATA(vmthread)[thread_offset] = (uintptr_t)jlthread;
357 #else
358 INST_DATA(vmthread)[thread_offset] = (uintptr_t)INST_DATA(jlthread);
359 #endif
361 /* Create the string for the thread name. If null is specified
362 the initialiser method will generate a name of the form Thread-X */
363 if(name != NULL && (thread_name = Cstr2String(name)) == NULL)
364 return NULL;
366 /* Call the initialiser method -- this is for use by threads
367 created or attached by the VM "outside" of Java */
368 executeMethod(jlthread, init_mb, vmthread, thread_name, NORM_PRIORITY, is_daemon);
370 /* Add thread to thread ID map hash table. */
371 addThreadToHash(thread);
373 return jlthread;
376 static void initThread(Thread *thread, char is_daemon, void *stack_base) {
378 /* Create the thread stack and store the thread structure in
379 thread-specific memory */
380 initialiseJavaStack(thread->ee);
381 setThreadSelf(thread);
383 /* Record the thread's stack base */
384 thread->stack_base = stack_base;
386 /* Grab thread list lock. This also stops suspension */
387 pthread_mutex_lock(&lock);
389 /* If all threads are suspended (i.e. GC in progress) we cannot start
390 until the threads are resumed. Record we're waiting and wait until
391 the world is restarted... */
393 threads_waiting_to_start++;
395 while(all_threads_suspended)
396 pthread_cond_wait(&cv, &lock);
398 threads_waiting_to_start--;
400 /* add to thread list... After this point (once we release the lock)
401 we are suspendable */
402 if((thread->next = main_thread.next))
403 main_thread.next->prev = thread;
404 thread->prev = &main_thread;
405 main_thread.next = thread;
407 /* Keep track of threads counts */
408 if(++threads_count > peak_threads_count)
409 peak_threads_count = threads_count;
410 total_started_threads_count++;
412 /* If we're not a deamon thread the main thread must
413 wait until we exit */
414 if(!is_daemon)
415 non_daemon_thrds++;
417 /* Get a thread ID (used in thin locking) and
418 record we're now running */
419 thread->id = genThreadID();
420 thread->state = RUNNING;
422 pthread_cond_broadcast(&cv);
423 pthread_mutex_unlock(&lock);
426 static Thread *attachThread(char *name, char is_daemon, void *stack_base, Thread *thread, Object *group) {
427 Object *java_thread;
429 /* Create the ExecEnv for the thread */
430 ExecEnv *ee = sysMalloc(sizeof(ExecEnv));
431 memset(ee, 0, sizeof(ExecEnv));
433 thread->tid = pthread_self();
434 thread->ee = ee;
436 /* Complete initialisation of the thread structure, create the thread
437 stack and add the thread to the thread list */
438 initThread(thread, is_daemon, stack_base);
440 /* Initialise the Java-level thread objects representing this thread */
441 if((java_thread = initJavaThread(thread, is_daemon, name)) == NULL)
442 return NULL;
444 /* Initialiser doesn't handle the thread group */
445 #if JAM_ON_STACK
446 INST_DATA(java_thread)[group_offset] = (uintptr_t)group;
447 #else
448 INST_DATA(java_thread)[group_offset] = (uintptr_t)INST_DATA(group);
449 #endif
450 executeMethod(group, addThread_mb, java_thread);
452 /* We're now attached to the VM...*/
453 TRACE("Thread 0x%x id: %d attached\n", thread, thread->id);
454 return thread;
457 void detachThread(Thread *thread) {
458 Object *group, *excep;
459 ExecEnv *ee = thread->ee;
460 Object *jThread = ee->thread;
461 #if JAM_ON_STACK
462 Object *vmthread = (Object*)INST_DATA(jThread)[vmthread_offset];
463 #else
464 Object *vmthread = JAM_OBJECT((void *)INST_DATA(jThread)[vmthread_offset]);
465 #endif
467 /* Get the thread's group */
468 #if JAM_ON_STACK
469 group = (Object *)INST_DATA(jThread)[group_offset];
470 #else
471 group = JAM_OBJECT((void *)INST_DATA(jThread)[group_offset]);
472 #endif
474 /* If there's an uncaught exception, call uncaughtException on the thread's
475 exception handler, or the thread's group if this is unset */
476 if((excep = exceptionOccurred())) {
477 FieldBlock *fb = findField(thread_class, "exceptionHandler",
478 "Ljava/lang/Thread$UncaughtExceptionHandler;");
479 #if JAM_ON_STACK
480 Object *thread_handler = fb == NULL ? NULL : (Object *)INST_DATA(jThread)[fb->offset];
481 #else
482 Object *thread_handler = fb == NULL ? NULL : JAM_OBJECT((void *)INST_DATA(jThread)[fb->offset]);
483 #endif
484 Object *handler = thread_handler == NULL ? group : thread_handler;
486 MethodBlock *uncaught_exp = lookupMethod(handler->class, "uncaughtException",
487 "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
489 if(uncaught_exp) {
490 clearException();
491 executeMethod(handler, uncaught_exp, jThread, excep);
492 } else
493 printException();
496 /* remove thread from thread group */
497 executeMethod(group, (CLASS_CB(group->class))->method_table[rmveThrd_mtbl_idx], jThread);
499 /* set VMThread ref in Thread object to null - operations after this
500 point will result in an IllegalThreadStateException */
501 INST_DATA(jThread)[vmthread_offset] = 0;
503 /* Remove thread from the ID map hash table */
504 deleteThreadFromHash(thread);
506 /* Disable suspend to protect lock operation */
507 disableSuspend(thread);
509 /* Grab global lock, and update thread structures protected by
510 it (thread list, thread ID and number of daemon threads) */
511 pthread_mutex_lock(&lock);
513 /* remove from thread list... */
514 if((thread->prev->next = thread->next))
515 thread->next->prev = thread->prev;
517 /* One less live thread */
518 threads_count--;
520 /* Recycle the thread's thread ID */
521 freeThreadID(thread->id);
523 /* Handle daemon thread status */
524 if(!INST_DATA(jThread)[daemon_offset])
525 non_daemon_thrds--;
527 pthread_mutex_unlock(&lock);
529 /* notify any threads waiting on VMThread object -
530 these are joining this thread */
531 objectLock(vmthread);
532 objectNotifyAll(vmthread);
533 objectUnlock(vmthread);
535 /* It is safe to free the thread's ExecEnv and stack now as these are
536 only used within the thread. It is _not_ safe to free the native
537 thread structure as another thread may be concurrently accessing it.
538 However, they must have a reference to the VMThread -- therefore, it
539 is safe to free during GC when the VMThread is determined to be no
540 longer reachable. */
541 sysFree(ee->stack);
542 sysFree(ee);
544 /* If no more daemon threads notify the main thread (which
545 may be waiting to exit VM). Note, this is not protected
546 by lock, but main thread checks again */
548 if(non_daemon_thrds == 0) {
549 /* No need to bother with disabling suspension
550 * around lock, as we're no longer on thread list */
551 pthread_mutex_lock(&exit_lock);
552 pthread_cond_signal(&exit_cv);
553 pthread_mutex_unlock(&exit_lock);
556 TRACE("Thread 0x%x id: %d detached from VM\n", thread, thread->id);
559 void *threadStart(void *arg) {
560 Thread *thread = (Thread *)arg;
561 Object *jThread = thread->ee->thread;
563 /* Parent thread created thread with suspension disabled.
564 This is inherited so we need to enable */
565 enableSuspend(thread);
567 /* Complete initialisation of the thread structure, create the thread
568 stack and add the thread to the thread list */
569 initThread(thread, INST_DATA(jThread)[daemon_offset], &thread);
571 /* Add thread to thread ID map hash table. */
572 addThreadToHash(thread);
574 /* Execute the thread's run method */
575 executeMethod(jThread, CLASS_CB(jThread->class)->method_table[run_mtbl_idx]);
577 /* Run has completed. Detach the thread from the VM and exit */
578 detachThread(thread);
580 TRACE("Thread 0x%x id: %d exited\n", thread, thread->id);
581 return NULL;
584 void createJavaThread(Object *jThread, long long stack_size) {
585 ExecEnv *ee;
586 Thread *thread;
587 Thread *self = threadSelf();
588 Object *vmthread = allocObject(vmthread_class);
590 if(vmthread == NULL)
591 return;
593 disableSuspend(self);
595 pthread_mutex_lock(&lock);
596 if(INST_DATA(jThread)[vmthread_offset]) {
597 pthread_mutex_unlock(&lock);
598 enableSuspend(self);
599 signalException("java/lang/IllegalThreadStateException", "thread already started");
600 return;
603 ee = (ExecEnv*)sysMalloc(sizeof(ExecEnv));
604 thread = (Thread*)sysMalloc(sizeof(Thread));
605 memset(ee, 0, sizeof(ExecEnv));
606 memset(thread, 0, sizeof(Thread));
608 thread->ee = ee;
609 ee->thread = jThread;
610 ee->stack_size = stack_size;
612 INST_DATA(vmthread)[vmData_offset] = (uintptr_t)thread;
613 #if JAM_ON_STACK
614 INST_DATA(vmthread)[thread_offset] = (uintptr_t)jThread;
615 INST_DATA(jThread)[vmthread_offset] = (uintptr_t)vmthread;
616 #else
617 INST_DATA(vmthread)[thread_offset] = (uintptr_t)INST_DATA(jThread);
618 INST_DATA(jThread)[vmthread_offset] = (uintptr_t)INST_DATA(vmthread);
619 #endif
621 pthread_mutex_unlock(&lock);
623 if(pthread_create(&thread->tid, &attributes, threadStart, thread)) {
624 INST_DATA(jThread)[vmthread_offset] = 0;
625 sysFree(ee);
626 enableSuspend(self);
627 signalException("java/lang/OutOfMemoryError", "can't create thread");
628 return;
631 pthread_mutex_lock(&lock);
633 /* Wait for thread to start */
634 while(thread->state == 0)
635 pthread_cond_wait(&cv, &lock);
637 pthread_mutex_unlock(&lock);
638 enableSuspend(self);
641 static void initialiseSignals();
643 Thread *attachJNIThread(char *name, char is_daemon, Object *group) {
644 Thread *thread = sysMalloc(sizeof(Thread));
645 void *stack_base = nativeStackBase();
647 /* If no group is given add it to the main group */
648 if(group == NULL) {
649 #if JAM_ON_STACK
650 group = (Object*)INST_DATA(main_ee.thread)[group_offset];
651 #else
652 group = JAM_OBJECT((void *)INST_DATA(main_ee.thread)[group_offset]);
653 #endif
656 /* Initialise internal thread structure */
657 memset(thread, 0, sizeof(Thread));
659 /* Externally created threads will not inherit signal state */
660 initialiseSignals();
662 /* Initialise the thread and add it to the VM thread list */
663 return attachThread(name, is_daemon, stack_base, thread, group);
666 void detachJNIThread(Thread *thread) {
667 /* The JNI spec says we should release all locks held by this thread.
668 We don't do this (yet), and only remove the thread from the VM. */
669 detachThread(thread);
672 static void *shell(void *args) {
673 void *start = ((void**)args)[1];
674 Thread *self = ((Thread**)args)[2];
676 if(main_exited)
677 return NULL;
679 /* VM helper threads should be added to the system group, but this doesn't
680 exist. As the root group is main, we add it to that for now... */
681 #if JAM_ON_STACK
682 attachThread(((char**)args)[0], TRUE, &self, self,
683 (Object*)INST_DATA(main_ee.thread)[group_offset]);
684 #else
685 attachThread(((char**)args)[0], TRUE, &self, self,
686 JAM_OBJECT((void *)INST_DATA(main_ee.thread)[group_offset]));
687 #endif
689 sysFree(args);
690 (*(void(*)(Thread*))start)(self);
691 return NULL;
694 void createVMThread(char *name, void (*start)(Thread*)) {
695 Thread *thread = (Thread*)sysMalloc(sizeof(Thread));
696 void **args = sysMalloc(3 * sizeof(void*));
697 pthread_t tid;
699 args[0] = name;
700 args[1] = start;
701 args[2] = thread;
703 memset(thread, 0, sizeof(Thread));
704 pthread_create(&tid, &attributes, shell, args);
706 /* Wait for thread to start */
708 pthread_mutex_lock(&lock);
709 while(thread->state == 0)
710 pthread_cond_wait(&cv, &lock);
711 pthread_mutex_unlock(&lock);
714 void suspendThread(Thread *thread) {
715 thread->suspend = TRUE;
716 MBARRIER();
718 if(!thread->blocking) {
719 TRACE("Sending suspend signal to thread 0x%x id: %d\n", thread, thread->id);
720 pthread_kill(thread->tid, SIGUSR1);
723 while(thread->blocking != SUSP_BLOCKING && thread->state != SUSPENDED) {
724 TRACE("Waiting for thread 0x%x id: %d to suspend\n", thread, thread->id);
725 sched_yield();
729 void resumeThread(Thread *thread) {
730 thread->suspend = FALSE;
731 MBARRIER();
733 if(!thread->blocking) {
734 TRACE("Sending resume signal to thread 0x%x id: %d\n", thread, thread->id);
735 pthread_kill(thread->tid, SIGUSR1);
738 while(thread->state == SUSPENDED) {
739 TRACE("Waiting for thread 0x%x id: %d to resume\n", thread, thread->id);
740 sched_yield();
744 void suspendAllThreads(Thread *self) {
745 Thread *thread;
747 TRACE("Thread 0x%x id: %d is suspending all threads\n", self, self->id);
748 pthread_mutex_lock(&lock);
750 for(thread = &main_thread; thread != NULL; thread = thread->next) {
751 if(thread == self)
752 continue;
754 thread->suspend = TRUE;
755 MBARRIER();
757 if(!thread->blocking) {
758 TRACE("Sending suspend signal to thread 0x%x id: %d\n", thread, thread->id);
759 pthread_kill(thread->tid, SIGUSR1);
763 for(thread = &main_thread; thread != NULL; thread = thread->next) {
764 if(thread == self)
765 continue;
767 while(thread->blocking != SUSP_BLOCKING && thread->state != SUSPENDED) {
768 TRACE("Waiting for thread 0x%x id: %d to suspend\n", thread, thread->id);
769 sched_yield();
773 all_threads_suspended = TRUE;
775 TRACE("All threads suspended...\n");
776 pthread_mutex_unlock(&lock);
779 void resumeAllThreads(Thread *self) {
780 Thread *thread;
782 TRACE("Thread 0x%x id: %d is resuming all threads\n", self, self->id);
783 pthread_mutex_lock(&lock);
785 for(thread = &main_thread; thread != NULL; thread = thread->next) {
786 if(thread == self)
787 continue;
789 thread->suspend = FALSE;
790 MBARRIER();
792 if(!thread->blocking) {
793 TRACE("Sending resume signal to thread 0x%x id: %d\n", thread, thread->id);
794 pthread_kill(thread->tid, SIGUSR1);
798 for(thread = &main_thread; thread != NULL; thread = thread->next) {
799 while(thread->state == SUSPENDED) {
800 TRACE("Waiting for thread 0x%x id: %d to resume\n", thread, thread->id);
801 sched_yield();
805 all_threads_suspended = FALSE;
806 if(threads_waiting_to_start) {
807 TRACE("%d threads waiting to start...\n", threads_waiting_to_start);
808 pthread_cond_broadcast(&cv);
811 TRACE("All threads resumed...\n");
812 pthread_mutex_unlock(&lock);
815 static void suspendLoop(Thread *thread) {
816 char old_state = thread->state;
817 sigjmp_buf env;
818 sigset_t mask;
820 sigsetjmp(env, FALSE);
822 thread->stack_top = &env;
823 thread->state = SUSPENDED;
824 MBARRIER();
826 sigfillset(&mask);
827 sigdelset(&mask, SIGUSR1);
828 sigdelset(&mask, SIGTERM);
830 while(thread->suspend && !thread->blocking)
831 sigsuspend(&mask);
833 thread->state = old_state;
834 MBARRIER();
837 static void suspendHandler(int sig) {
838 Thread *thread = threadSelf();
839 suspendLoop(thread);
842 /* The "slow" disable. Normally used when a thread enters
843 a blocking code section, such as waiting on a lock. */
845 void disableSuspend0(Thread *thread, void *stack_top) {
846 sigset_t mask;
848 thread->stack_top = stack_top;
849 thread->blocking = SUSP_BLOCKING;
850 MBARRIER();
852 sigemptyset(&mask);
853 sigaddset(&mask, SIGUSR1);
854 pthread_sigmask(SIG_BLOCK, &mask, NULL);
857 void enableSuspend(Thread *thread) {
858 sigset_t mask;
860 thread->blocking = FALSE;
861 MBARRIER();
863 if(thread->suspend) {
864 TRACE("Thread 0x%x id: %d is self suspending\n", thread, thread->id);
865 suspendLoop(thread);
866 TRACE("Thread 0x%x id: %d resumed\n", thread, thread->id);
869 sigemptyset(&mask);
870 sigaddset(&mask, SIGUSR1);
871 pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
874 /* Fast disable/enable suspend doesn't modify the signal mask
875 or save the thread context. It's used in critical code
876 sections where the thread cannot be suspended (such as
877 modifying the loaded classes hash table). Thread supension
878 blocks until the thread self-suspends. */
880 void fastEnableSuspend(Thread *thread) {
882 thread->blocking = FALSE;
883 MBARRIER();
885 if(thread->suspend) {
886 sigset_t mask;
888 sigemptyset(&mask);
889 sigaddset(&mask, SIGUSR1);
890 pthread_sigmask(SIG_BLOCK, &mask, NULL);
892 TRACE("Thread 0x%x id: %d is fast self suspending\n", thread, thread->id);
893 suspendLoop(thread);
894 TRACE("Thread 0x%x id: %d resumed\n", thread, thread->id);
896 pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
900 void dumpThreadsLoop(Thread *self) {
901 char buffer[256];
902 Thread *thread;
903 sigset_t mask;
904 int sig;
906 sigemptyset(&mask);
907 sigaddset(&mask, SIGQUIT);
908 sigaddset(&mask, SIGINT);
910 disableSuspend0(self, &self);
911 for(;;) {
912 sigwait(&mask, &sig);
914 /* If it was an interrupt (e.g. Ctrl-C) terminate the VM */
915 if(sig == SIGINT)
916 exitVM(0);
918 /* It must be a SIGQUIT. Do a thread dump */
920 suspendAllThreads(self);
921 jam_printf("\n------ JamVM version %s Full Thread Dump -------\n", VERSION);
923 for(thread = &main_thread; thread != NULL; thread = thread->next) {
924 uintptr_t *thr_data = INST_DATA(thread->ee->thread);
925 int priority = thr_data[priority_offset];
926 int daemon = thr_data[daemon_offset];
927 Frame *last = thread->ee->last_frame;
929 /* Get thread name; we don't use String2Cstr(), as this mallocs memory
930 and may deadlock with a thread suspended in malloc/realloc/free */
931 String2Buff((Object*)thr_data[name_offset], buffer, sizeof(buffer));
933 jam_printf("\n\"%s\"%s %p priority: %d tid: %p id: %d state: %s (%d)\n",
934 buffer, daemon ? " (daemon)" : "", thread, priority, thread->tid,
935 thread->id, getThreadStateString(thread), thread->state);
937 while(last->prev != NULL) {
938 for(; last->mb != NULL; last = last->prev) {
939 MethodBlock *mb = last->mb;
940 ClassBlock *cb = CLASS_CB(mb->class);
942 /* Convert slashes in class name to dots. Similar to above,
943 we don't use slash2dots(), as this mallocs memory */
944 slash2dots2buff(cb->name, buffer, sizeof(buffer));
945 jam_printf("\tat %s.%s(", buffer, mb->name);
947 if(mb->access_flags & ACC_NATIVE)
948 jam_printf("Native method");
949 else
950 if(cb->source_file_name == NULL)
951 jam_printf("Unknown source");
952 else {
953 int line = mapPC2LineNo(mb, last->last_pc);
954 jam_printf("%s", cb->source_file_name);
955 if(line != -1)
956 jam_printf(":%d", line);
958 jam_printf(")\n");
960 last = last->prev;
963 resumeAllThreads(self);
967 static void initialiseSignals() {
968 struct sigaction act;
969 sigset_t mask;
971 act.sa_handler = suspendHandler;
972 sigemptyset(&act.sa_mask);
973 act.sa_flags = 0;
974 sigaction(SIGUSR1, &act, NULL);
976 sigemptyset(&mask);
977 sigaddset(&mask, SIGQUIT);
978 sigaddset(&mask, SIGINT);
979 sigaddset(&mask, SIGPIPE);
980 sigprocmask(SIG_BLOCK, &mask, NULL);
983 /* garbage collection support */
985 extern void scanThread(Thread *thread);
987 void scanThreads() {
988 Thread *thread;
990 pthread_mutex_lock(&lock);
991 for(thread = &main_thread; thread != NULL; thread = thread->next)
992 scanThread(thread);
993 pthread_mutex_unlock(&lock);
996 int systemIdle(Thread *self) {
997 Thread *thread;
999 for(thread = &main_thread; thread != NULL; thread = thread->next)
1000 if(thread != self && thread->state < WAITING)
1001 return FALSE;
1003 return TRUE;
1006 void exitVM(int status) {
1007 main_exited = TRUE;
1009 /* Execute System.exit() to run any registered shutdown hooks.
1010 In the unlikely event that System.exit() can't be found, or
1011 it returns, fall through and exit. */
1013 if(!VMInitialising()) {
1014 Class *system = findSystemClass("java/lang/System");
1015 if(system) {
1016 MethodBlock *exit = findMethod(system, "exit", "(I)V");
1017 if(exit)
1018 executeStaticMethod(system, exit, status);
1022 jamvm_exit(status);
1025 void mainThreadWaitToExitVM() {
1026 Thread *self = threadSelf();
1027 TRACE("Waiting for %d non-daemon threads to exit\n", non_daemon_thrds);
1029 disableSuspend(self);
1030 pthread_mutex_lock(&exit_lock);
1032 self->state = WAITING;
1033 while(non_daemon_thrds)
1034 pthread_cond_wait(&exit_cv, &exit_lock);
1036 pthread_mutex_unlock(&exit_lock);
1037 enableSuspend(self);
1040 void mainThreadSetContextClassLoader(Object *loader) {
1041 FieldBlock *fb = findField(thread_class, "contextClassLoader", "Ljava/lang/ClassLoader;");
1042 #if JAM_ON_STACK
1043 if(fb != NULL)
1044 INST_DATA(main_ee.thread)[fb->offset] = (uintptr_t)loader;
1045 #else
1046 if(fb != NULL)
1047 INST_DATA(main_ee.thread)[fb->offset] = (uintptr_t)INST_DATA(loader);
1048 #endif
1051 void initialiseMainThread(InitArgs *args) {
1052 size_t size;
1053 Object *java_thread;
1054 Class *thrdGrp_class;
1055 MethodBlock *run, *remove_thread;
1056 FieldBlock *group, *priority, *root, *threadId;
1057 FieldBlock *vmData, *vmThread, *thread, *daemon, *name;
1059 /* Set the default size of the Java stack for each _new_ thread */
1060 dflt_stack_size = args->java_stack;
1062 /* Initialise internal locks and pthread state */
1063 pthread_key_create(&threadKey, NULL);
1065 pthread_mutex_init(&lock, NULL);
1066 pthread_cond_init(&cv, NULL);
1068 pthread_mutex_init(&exit_lock, NULL);
1069 pthread_cond_init(&exit_cv, NULL);
1071 pthread_attr_init(&attributes);
1072 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
1074 /* Ensure the thread stacks are at least 1 megabyte in size */
1075 pthread_attr_getstacksize(&attributes, &size);
1076 if(size < 1*MB)
1077 pthread_attr_setstacksize(&attributes, 2*MB);
1079 monitorInit(&sleep_mon);
1080 initHashTable(thread_id_map, HASHTABSZE, TRUE);
1082 /* We need to cache field and method offsets to create and initialise
1083 threads. However, the class loading component requires a valid
1084 thread and ExecEnv. To get round this we initialise the main thread
1085 in two parts. First part is sufficient to _load_ classes, but it
1086 is still not fully setup so we don't allow initialisers to run */
1088 main_thread.stack_base = args->main_stack_base;
1089 main_thread.tid = pthread_self();
1090 main_thread.id = genThreadID();
1091 main_thread.state = RUNNING;
1092 main_thread.ee = &main_ee;
1094 initialiseJavaStack(&main_ee);
1095 setThreadSelf(&main_thread);
1097 /* As we're initialising, VM will abort if Thread can't be found */
1098 thread_class = findSystemClass0("java/lang/Thread");
1100 /* Register class reference for compaction threading */
1101 registerStaticClassRef(&thread_class);
1103 vmThread = findField(thread_class, "vmThread", "Ljava/lang/VMThread;");
1104 daemon = findField(thread_class, "daemon", "Z");
1105 name = findField(thread_class, "name", "Ljava/lang/String;");
1106 group = findField(thread_class, "group", "Ljava/lang/ThreadGroup;");
1107 priority = findField(thread_class, "priority", "I");
1108 threadId = findField(thread_class, "threadId", "J");
1110 init_mb = findMethod(thread_class, "<init>",
1111 "(Ljava/lang/VMThread;Ljava/lang/String;IZ)V");
1112 run = findMethod(thread_class, "run", "()V");
1114 vmthread_class = findSystemClass0("java/lang/VMThread");
1115 CLASS_CB(vmthread_class)->flags |= VMTHREAD;
1117 /* Register class reference for compaction threading */
1118 registerStaticClassRef(&vmthread_class);
1120 thread = findField(vmthread_class, "thread", "Ljava/lang/Thread;");
1121 vmData = findField(vmthread_class, "vmData", "I");
1123 /* findField and findMethod do not throw an exception... */
1124 if((init_mb == NULL) || (vmData == NULL) || (run == NULL) || (daemon == NULL) ||
1125 (name == NULL) || (group == NULL) || (priority == NULL) || (vmThread == NULL) ||
1126 (thread == NULL) || (threadId == NULL))
1127 goto error;
1129 vmthread_offset = vmThread->offset;
1130 thread_offset = thread->offset;
1131 vmData_offset = vmData->offset;
1132 daemon_offset = daemon->offset;
1133 group_offset = group->offset;
1134 priority_offset = priority->offset;
1135 threadId_offset = threadId->offset;
1136 name_offset = name->offset;
1137 run_mtbl_idx = run->method_table_index;
1139 /* Initialise the Java-level thread objects representing this thread */
1140 java_thread = initJavaThread(&main_thread, FALSE, "main");
1142 /* Main thread is now sufficiently setup to be able to run the thread group
1143 initialiser. This is essential to create the root thread group */
1144 thrdGrp_class = findSystemClass("java/lang/ThreadGroup");
1146 root = findField(thrdGrp_class, "root", "Ljava/lang/ThreadGroup;");
1147 addThread_mb = findMethod(thrdGrp_class, "addThread", "(Ljava/lang/Thread;)V");
1148 remove_thread = findMethod(thrdGrp_class, "removeThread", "(Ljava/lang/Thread;)V");
1150 /* findField and findMethod do not throw an exception... */
1151 if((root == NULL) || (addThread_mb == NULL) || (remove_thread == NULL))
1152 goto error;
1154 rmveThrd_mtbl_idx = remove_thread->method_table_index;
1156 /* Add the main thread to the root thread group */
1157 #if (JAM_ON_STACK)
1158 INST_DATA(java_thread)[group_offset] = root->static_value;
1159 #else
1160 INST_DATA(java_thread)[group_offset] = (uintptr_t)INST_DATA((Object *)root->static_value);
1161 #endif
1162 executeMethod(((Object*)root->static_value), addThread_mb, java_thread);
1164 /* Setup signal handling. This will be inherited by all
1165 threads created within Java */
1166 initialiseSignals();
1168 /* Create the signal handler thread. It is responsible for
1169 catching and handling SIGQUIT (thread dump) and SIGINT
1170 (user-termination of the VM, e.g. via Ctrl-C). Note it
1171 must be a valid Java-level thread as it needs to run the
1172 shutdown hooks in the event of user-termination */
1173 createVMThread("Signal Handler", dumpThreadsLoop);
1175 return;
1177 error:
1178 jam_fprintf(stderr, "Error initialising VM (initialiseMainThread)\nCheck "
1179 "the README for compatible versions of GNU Classpath\n");
1180 exitVM(1);