* src/vm/global.h (jni_callblock): Removed.
[cacao.git] / src / threads / native / threads.c
1 /* src/threads/native/threads.c - native threads support
2
3    Copyright (C) 1996-2005, 2006 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    Contact: cacao@cacaojvm.org
26
27    Authors: Stefan Ring
28
29    Changes: Christian Thalinger
30                         Edwin Steiner
31
32    $Id: threads.c 4552 2006-03-04 17:15:44Z twisti $
33
34 */
35
36
37 #include "config.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44 #include <signal.h>
45 #include <sys/time.h>
46 #include <time.h>
47 #include <errno.h>
48
49 #include <pthread.h>
50 #include <semaphore.h>
51
52 #include "vm/types.h"
53
54 #include "arch.h"
55
56 #ifndef USE_MD_THREAD_STUFF
57 #include "machine-instr.h"
58 #else
59 #include "threads/native/generic-primitives.h"
60 #endif
61
62 #include "mm/boehm.h"
63 #include "mm/memory.h"
64 #include "native/native.h"
65 #include "native/include/java_lang_Object.h"
66 #include "native/include/java_lang_Throwable.h"
67 #include "native/include/java_lang_Thread.h"
68 #include "native/include/java_lang_ThreadGroup.h"
69 #include "native/include/java_lang_VMThread.h"
70 #include "threads/native/threads.h"
71 #include "toolbox/avl.h"
72 #include "toolbox/logging.h"
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/loader.h"
77 #include "vm/options.h"
78 #include "vm/stringlocal.h"
79 #include "vm/vm.h"
80 #include "vm/jit/asmpart.h"
81
82 #if !defined(__DARWIN__)
83 #if defined(__LINUX__)
84 #define GC_LINUX_THREADS
85 #elif defined(__MIPS__)
86 #define GC_IRIX_THREADS
87 #endif
88 #include "boehm-gc/include/gc.h"
89 #endif
90
91 #ifdef USE_MD_THREAD_STUFF
92 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
93 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
94 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
95 #endif
96
97 #ifdef MUTEXSIM
98
99 /* We need this for older MacOSX (10.1.x) */
100
101 typedef struct {
102         pthread_mutex_t mutex;
103         pthread_t owner;
104         int count;
105 } pthread_mutex_rec_t;
106
107 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
108 {
109         pthread_mutex_init(&m->mutex, NULL);
110         m->count = 0;
111 }
112
113 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
114 {
115         pthread_mutex_destroy(&m->mutex);
116 }
117
118 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
119 {
120         for (;;) {
121                 if (!m->count)
122                 {
123                         pthread_mutex_lock(&m->mutex);
124                         m->owner = pthread_self();
125                         m->count++;
126                         break;
127                 } 
128                 else {
129                         if (m->owner != pthread_self()) {
130                                 pthread_mutex_lock(&m->mutex);
131                         }
132                         else {
133                                 m->count++;
134                                 break;
135                         }
136                 }
137         }
138 }
139
140 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
141 {
142         if (!--m->count)
143                 pthread_mutex_unlock(&m->mutex);
144 }
145
146 #else /* MUTEXSIM */
147
148 #define pthread_mutex_lock_rec pthread_mutex_lock
149 #define pthread_mutex_unlock_rec pthread_mutex_unlock
150 #define pthread_mutex_rec_t pthread_mutex_t
151
152 #endif /* MUTEXSIM */
153
154 static void setPriority(pthread_t tid, int priority)
155 {
156         struct sched_param schedp;
157         int policy;
158
159         pthread_getschedparam(tid, &policy, &schedp);
160         schedp.sched_priority = priority;
161         pthread_setschedparam(tid, policy, &schedp);
162 }
163
164
165 static avl_tree *criticaltree;
166 threadobject *mainthreadobj;
167
168 #ifndef HAVE___THREAD
169 pthread_key_t tkey_threadinfo;
170 #else
171 __thread threadobject *threadobj;
172 #endif
173
174 static pthread_mutex_rec_t compiler_mutex;
175 static pthread_mutex_rec_t tablelock;
176
177 void compiler_lock()
178 {
179         pthread_mutex_lock_rec(&compiler_mutex);
180 }
181
182 void compiler_unlock()
183 {
184         pthread_mutex_unlock_rec(&compiler_mutex);
185 }
186
187 void tables_lock()
188 {
189     pthread_mutex_lock_rec(&tablelock);
190 }
191
192 void tables_unlock()
193 {
194     pthread_mutex_unlock_rec(&tablelock);
195 }
196
197
198 static s4 criticalcompare(const void *pa, const void *pb)
199 {
200         const threadcritnode *na = pa;
201         const threadcritnode *nb = pb;
202
203         if (na->mcodebegin < nb->mcodebegin)
204                 return -1;
205         if (na->mcodebegin > nb->mcodebegin)
206                 return 1;
207         return 0;
208 }
209
210
211 static const threadcritnode *findcritical(u1 *mcodeptr)
212 {
213     avl_node *n;
214     const threadcritnode *m;
215
216     n = criticaltree->root;
217         m = NULL;
218
219     if (!n)
220         return NULL;
221
222     for (;;) {
223         const threadcritnode *d = n->data;
224
225         if (mcodeptr == d->mcodebegin)
226             return d;
227
228         if (mcodeptr < d->mcodebegin) {
229             if (n->childs[0]) {
230                 n = n->childs[0];
231                         }
232             else {
233                 return m;
234                         }
235         } 
236                 else {
237             if (n->childs[1]) {
238                 m = n->data;
239                 n = n->childs[1];
240             } 
241                         else {
242                 return n->data;
243                         }
244         }
245     }
246 }
247
248
249 void thread_registercritical(threadcritnode *n)
250 {
251         avl_insert(criticaltree, n);
252 }
253
254 u1 *thread_checkcritical(u1 *mcodeptr)
255 {
256         const threadcritnode *n = findcritical(mcodeptr);
257         return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
258 }
259
260 static void thread_addstaticcritical()
261 {
262         /* XXX TWISTI: this is just a quick hack */
263 #if defined(ENABLE_JIT)
264         threadcritnode *n = &asm_criticalsections;
265
266         while (n->mcodebegin)
267                 thread_registercritical(n++);
268 #endif
269 }
270
271 static pthread_mutex_t threadlistlock;
272
273 static pthread_mutex_t stopworldlock;
274 volatile int stopworldwhere;
275
276 static sem_t suspend_ack;
277 #if defined(__MIPS__)
278 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
279 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
280 #endif
281
282 /*
283  * where - 1 from within GC
284            2 class numbering
285  */
286 void lock_stopworld(int where)
287 {
288         pthread_mutex_lock(&stopworldlock);
289         stopworldwhere = where;
290 }
291
292 void unlock_stopworld()
293 {
294         stopworldwhere = 0;
295         pthread_mutex_unlock(&stopworldlock);
296 }
297
298 #if !defined(__DARWIN__)
299 /* Caller must hold threadlistlock */
300 static int cast_sendsignals(int sig, int count)
301 {
302         /* Count threads */
303         threadobject *tobj = mainthreadobj;
304         nativethread *infoself = THREADINFO;
305
306         if (count == 0) {
307                 do {
308                         count++;
309                         tobj = tobj->info.next;
310                 } while (tobj != mainthreadobj);
311         }
312         
313         do {
314                 nativethread *info = &tobj->info;
315                 if (info != infoself)
316                         pthread_kill(info->tid, sig);
317                 tobj = tobj->info.next;
318         } while (tobj != mainthreadobj);
319
320         return count-1;
321 }
322
323 #else
324
325 static void cast_darwinstop()
326 {
327         threadobject *tobj = mainthreadobj;
328         nativethread *infoself = THREADINFO;
329
330         do {
331                 nativethread *info = &tobj->info;
332                 if (info != infoself)
333                 {
334                         thread_state_flavor_t flavor = PPC_THREAD_STATE;
335                         mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
336                         ppc_thread_state_t thread_state;
337                         mach_port_t thread = info->mach_thread;
338                         kern_return_t r;
339
340                         r = thread_suspend(thread);
341                         if (r != KERN_SUCCESS) {
342                                 log_text("thread_suspend failed");
343                                 assert(0);
344                         }
345
346                         r = thread_get_state(thread, flavor,
347                                 (natural_t*)&thread_state, &thread_state_count);
348                         if (r != KERN_SUCCESS) {
349                                 log_text("thread_get_state failed");
350                                 assert(0);
351                         }
352
353                         thread_restartcriticalsection(&thread_state);
354
355                         r = thread_set_state(thread, flavor,
356                                 (natural_t*)&thread_state, thread_state_count);
357                         if (r != KERN_SUCCESS) {
358                                 log_text("thread_set_state failed");
359                                 assert(0);
360                         }
361                 }
362                 tobj = tobj->info.next;
363         } while (tobj != mainthreadobj);
364 }
365
366 static void cast_darwinresume()
367 {
368         threadobject *tobj = mainthreadobj;
369         nativethread *infoself = THREADINFO;
370
371         do {
372                 nativethread *info = &tobj->info;
373                 if (info != infoself)
374                 {
375                         mach_port_t thread = info->mach_thread;
376                         kern_return_t r;
377
378                         r = thread_resume(thread);
379                         if (r != KERN_SUCCESS) {
380                                 log_text("thread_resume failed");
381                                 assert(0);
382                         }
383                 }
384                 tobj = tobj->info.next;
385         } while (tobj != mainthreadobj);
386 }
387
388 #endif
389
390 #if defined(__MIPS__)
391 static void cast_irixresume()
392 {
393         pthread_mutex_lock(&suspend_ack_lock);
394         pthread_cond_broadcast(&suspend_cond);
395         pthread_mutex_unlock(&suspend_ack_lock);
396 }
397 #endif
398
399 void cast_stopworld()
400 {
401         int count, i;
402         lock_stopworld(2);
403         pthread_mutex_lock(&threadlistlock);
404 #if defined(__DARWIN__)
405         cast_darwinstop();
406 #else
407         count = cast_sendsignals(GC_signum1(), 0);
408         for (i=0; i<count; i++)
409                 sem_wait(&suspend_ack);
410 #endif
411         pthread_mutex_unlock(&threadlistlock);
412 }
413
414 void cast_startworld()
415 {
416         pthread_mutex_lock(&threadlistlock);
417 #if defined(__DARWIN__)
418         cast_darwinresume();
419 #elif defined(__MIPS__)
420         cast_irixresume();
421 #else
422         cast_sendsignals(GC_signum2(), -1);
423 #endif
424         pthread_mutex_unlock(&threadlistlock);
425         unlock_stopworld();
426 }
427
428 #if !defined(__DARWIN__)
429 static void sigsuspend_handler(ucontext_t *ctx)
430 {
431         int sig;
432         sigset_t sigs;
433         
434         /* XXX TWISTI: this is just a quick hack */
435 #if defined(ENABLE_JIT)
436         thread_restartcriticalsection(ctx);
437 #endif
438
439         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
440            (not POSIX async-safe). */
441 #if defined(__IRIX__)
442         pthread_mutex_lock(&suspend_ack_lock);
443         sem_post(&suspend_ack);
444         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
445         pthread_mutex_unlock(&suspend_ack_lock);
446 #else
447         sem_post(&suspend_ack);
448
449         sig = GC_signum2();
450         sigfillset(&sigs);
451         sigdelset(&sigs, sig);
452         sigsuspend(&sigs);
453 #endif
454 }
455
456 int cacao_suspendhandler(ucontext_t *ctx)
457 {
458         if (stopworldwhere != 2)
459                 return 0;
460
461         sigsuspend_handler(ctx);
462         return 1;
463 }
464 #endif
465
466 static void setthreadobject(threadobject *thread)
467 {
468 #if !defined(HAVE___THREAD)
469         pthread_setspecific(tkey_threadinfo, thread);
470 #else
471         threadobj = thread;
472 #endif
473 }
474
475
476 /* thread_setself **************************************************************
477
478    XXX
479
480 *******************************************************************************/
481
482 void *thread_getself(void)
483 {
484         return THREADOBJECT;
485 }
486
487
488 static monitorLockRecord *dummyLR;
489
490 static void initPools();
491
492
493 /* thread_preinit **************************************************************
494
495    Do some early initialization of stuff required.
496
497 *******************************************************************************/
498
499 void threads_preinit(void)
500 {
501 #ifndef MUTEXSIM
502         pthread_mutexattr_t mutexattr;
503         pthread_mutexattr_init(&mutexattr);
504         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
505         pthread_mutex_init(&compiler_mutex, &mutexattr);
506         pthread_mutex_init(&tablelock, &mutexattr);
507         pthread_mutexattr_destroy(&mutexattr);
508 #else
509         pthread_mutex_init_rec(&compiler_mutex);
510         pthread_mutex_init_rec(&tablelock);
511 #endif
512
513         pthread_mutex_init(&threadlistlock, NULL);
514         pthread_mutex_init(&stopworldlock, NULL);
515
516         /* Allocate something so the garbage collector's signal handlers
517            are installed. */
518         heap_allocate(1, false, NULL);
519
520         mainthreadobj = NEW(threadobject);
521         mainthreadobj->info.tid = pthread_self();
522 #if !defined(HAVE___THREAD)
523         pthread_key_create(&tkey_threadinfo, NULL);
524 #endif
525         setthreadobject(mainthreadobj);
526         initPools();
527
528         /* Every newly created object's monitorPtr points here so we save
529            a check against NULL */
530
531         dummyLR = NEW(monitorLockRecord);
532         dummyLR->o = NULL;
533         dummyLR->ownerThread = NULL;
534         dummyLR->waiting = NULL;
535         dummyLR->incharge = dummyLR;
536
537         /* we need a working dummyLR before initializing the critical
538            section tree */
539
540     criticaltree = avl_create(&criticalcompare);
541
542         thread_addstaticcritical();
543         sem_init(&suspend_ack, 0, 0);
544 }
545
546
547 static pthread_attr_t threadattr;
548
549 static void freeLockRecordPools(lockRecordPool *);
550
551
552 /* threads_init ****************************************************************
553
554    Initializes the threads required by the JVM: main, finalizer.
555
556 *******************************************************************************/
557
558 bool threads_init(u1 *stackbottom)
559 {
560         java_lang_String      *threadname;
561         java_lang_Thread      *mainthread;
562         java_lang_ThreadGroup *threadgroup;
563         threadobject          *tempthread;
564         methodinfo            *method;
565
566         tempthread = mainthreadobj;
567
568         freeLockRecordPools(mainthreadobj->ee.lrpool);
569
570         /* This is kinda tricky, we grow the java.lang.Thread object so we
571            can keep the execution environment there. No Thread object must
572            have been created at an earlier time. */
573
574         class_java_lang_VMThread->instancesize = sizeof(threadobject);
575
576         /* create a VMThread */
577
578         mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
579
580         if (!mainthreadobj)
581                 return false;
582
583         FREE(tempthread, threadobject);
584
585         initThread(&mainthreadobj->o);
586
587         setthreadobject(mainthreadobj);
588
589         initLocks();
590
591         mainthreadobj->info.next = mainthreadobj;
592         mainthreadobj->info.prev = mainthreadobj;
593
594 #if defined(ENABLE_INTRP)
595         /* create interpreter stack */
596
597         if (opt_intrp) {
598                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
599                 mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
600         }
601 #endif
602
603         threadname = javastring_new(utf_new_char("main"));
604
605         /* allocate and init ThreadGroup */
606
607         threadgroup = (java_lang_ThreadGroup *)
608                 native_new_and_init(class_java_lang_ThreadGroup);
609
610         if (!threadgroup)
611                 throw_exception_exit();
612
613         /* create a Thread */
614
615         mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
616
617         if (!mainthread)
618                 throw_exception_exit();
619
620         mainthreadobj->o.thread = mainthread;
621
622         /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
623
624         method = class_resolveclassmethod(class_java_lang_Thread,
625                                                                           utf_init,
626                                                                           utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
627                                                                           class_java_lang_Thread,
628                                                                           true);
629
630         if (!method)
631                 return false;
632
633         (void) vm_call_method_intern(method, mainthread, mainthreadobj, threadname,
634                                                                  (void *) 5);
635
636         if (*exceptionptr)
637                 return false;
638
639         mainthread->group = threadgroup;
640         /* XXX This is a hack because the fourth argument was omitted */
641         mainthread->daemon = false;
642
643         /* add mainthread to ThreadGroup */
644
645         method = class_resolveclassmethod(class_java_lang_ThreadGroup,
646                                                                           utf_new_char("addThread"),
647                                                                           utf_new_char("(Ljava/lang/Thread;)V"),
648                                                                           class_java_lang_ThreadGroup,
649                                                                           true);
650
651         if (!method)
652                 return false;
653
654         (void) vm_call_method_intern(method, threadgroup, mainthread, NULL, NULL);
655
656         if (*exceptionptr)
657                 return false;
658
659         setPriority(pthread_self(), 5);
660
661         pthread_attr_init(&threadattr);
662         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
663
664         /* everything's ok */
665
666         return true;
667 }
668
669
670 void initThread(java_lang_VMThread *t)
671 {
672         threadobject *thread = (threadobject*) t;
673         nativethread *info = &thread->info;
674         info->tid = pthread_self();
675         /* TODO destroy all those things */
676         pthread_mutex_init(&info->joinMutex, NULL);
677         pthread_cond_init(&info->joinCond, NULL);
678
679         pthread_mutex_init(&thread->waitLock, NULL);
680         pthread_cond_init(&thread->waitCond, NULL);
681         thread->interrupted = false;
682         thread->signaled = false;
683         thread->isSleeping = false;
684 }
685
686 static void initThreadLocks(threadobject *);
687
688
689 typedef struct {
690         threadobject *thread;
691         functionptr   function;
692         sem_t        *psem;
693         sem_t        *psem_first;
694 } startupinfo;
695
696
697 /* threads_startup *************************************************************
698
699    Thread startup function called by pthread_create.
700
701 ******************************************************************************/
702
703 static void *threads_startup_thread(void *t)
704 {
705         startupinfo  *startup;
706         threadobject *thread;
707         sem_t        *psem;
708         nativethread *info;
709         threadobject *tnext;
710         methodinfo   *method;
711         functionptr   function;
712
713 #if defined(ENABLE_INTRP)
714         u1 *intrp_thread_stack;
715
716         /* create interpreter stack */
717
718         if (opt_intrp) {
719                 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
720                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
721         } else {
722                 intrp_thread_stack = NULL;
723         }
724 #endif
725
726         /* get passed startupinfo structure and the values in there */
727
728         startup = t;
729
730         thread   = startup->thread;
731         function = startup->function;
732         psem     = startup->psem;
733
734         info = &thread->info;
735
736         /* Seems like we've encountered a situation where info->tid was not set by
737          * pthread_create. We alleviate this problem by waiting for pthread_create
738          * to return. */
739         sem_wait(startup->psem_first);
740
741         t = NULL;
742 #if defined(__DARWIN__)
743         info->mach_thread = mach_thread_self();
744 #endif
745         setthreadobject(thread);
746
747         /* insert the thread into the threadlist */
748
749         pthread_mutex_lock(&threadlistlock);
750
751         info->prev = mainthreadobj;
752         info->next = tnext = mainthreadobj->info.next;
753         mainthreadobj->info.next = thread;
754         tnext->info.prev = thread;
755
756         pthread_mutex_unlock(&threadlistlock);
757
758         initThreadLocks(thread);
759
760         startup = NULL;
761         sem_post(psem);
762
763         setPriority(info->tid, thread->o.thread->priority);
764
765 #if defined(ENABLE_INTRP)
766         /* set interpreter stack */
767
768         if (opt_intrp)
769                 THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
770 #endif
771
772         /* find and run the Thread.run()V method if no other function was passed */
773
774         if (function == NULL) {
775                 method = class_resolveclassmethod(thread->o.header.vftbl->class,
776                                                                                   utf_run,
777                                                                                   utf_void__void,
778                                                                                   thread->o.header.vftbl->class,
779                                                                                   true);
780
781                 if (!method)
782                         throw_exception();
783
784                 (void) vm_call_method_intern(method, thread, NULL, NULL, NULL);
785
786         } 
787         else {
788                 /* call passed function, e.g. finalizer_thread */
789
790                 (function)();
791         }
792
793         /* Allow lock record pools to be used by other threads. They
794            cannot be deleted so we'd better not waste them. */
795
796         freeLockRecordPools(thread->ee.lrpool);
797
798         /* remove thread from thread list, do this inside a lock */
799
800         pthread_mutex_lock(&threadlistlock);
801         info->next->info.prev = info->prev;
802         info->prev->info.next = info->next;
803         pthread_mutex_unlock(&threadlistlock);
804
805         /* reset thread id (lock on joinMutex? TWISTI) */
806
807         pthread_mutex_lock(&info->joinMutex);
808         info->tid = 0;
809         pthread_mutex_unlock(&info->joinMutex);
810
811         pthread_cond_broadcast(&info->joinCond);
812
813         return NULL;
814 }
815
816
817 /* threads_start_thread ********************************************************
818
819    Start a thread in the JVM.
820
821 ******************************************************************************/
822
823 void threads_start_thread(thread *t, functionptr function)
824 {
825         nativethread *info;
826         sem_t         sem;
827         sem_t         sem_first;
828         startupinfo   startup;
829
830         info = &((threadobject *) t->vmThread)->info;
831
832         /* fill startupinfo structure passed by pthread_create to XXX */
833
834         startup.thread     = (threadobject*) t->vmThread;
835         startup.function   = function;       /* maybe we don't call Thread.run()V */
836         startup.psem       = &sem;
837         startup.psem_first = &sem_first;
838
839         sem_init(&sem, 0, 0);
840         sem_init(&sem_first, 0, 0);
841         
842         if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
843                                            &startup)) {
844                 log_text("pthread_create failed");
845                 assert(0);
846         }
847
848         sem_post(&sem_first);
849
850         /* wait here until the thread has entered itself into the thread list */
851
852         sem_wait(&sem);
853         sem_destroy(&sem);
854         sem_destroy(&sem_first);
855 }
856
857
858 /* At the end of the program, we wait for all running non-daemon threads to die
859  */
860
861 static threadobject *findNonDaemon(threadobject *thread)
862 {
863         while (thread != mainthreadobj) {
864                 if (!thread->o.thread->daemon)
865                         return thread;
866                 thread = thread->info.prev;
867         }
868
869         return NULL;
870 }
871
872 void joinAllThreads()
873 {
874         threadobject *thread;
875         pthread_mutex_lock(&threadlistlock);
876         while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
877                 nativethread *info = &thread->info;
878                 pthread_mutex_lock(&info->joinMutex);
879                 pthread_mutex_unlock(&threadlistlock);
880                 while (info->tid)
881                         pthread_cond_wait(&info->joinCond, &info->joinMutex);
882                 pthread_mutex_unlock(&info->joinMutex);
883                 pthread_mutex_lock(&threadlistlock);
884         }
885         pthread_mutex_unlock(&threadlistlock);
886 }
887
888 static void initLockRecord(monitorLockRecord *r, threadobject *t)
889 {
890         r->lockCount = 1;
891         r->ownerThread = t;
892         r->queuers = 0;
893         r->o = NULL;
894         r->waiter = NULL;
895         r->incharge = (monitorLockRecord *) &dummyLR;
896         r->waiting = NULL;
897         sem_init(&r->queueSem, 0, 0);
898         pthread_mutex_init(&r->resolveLock, NULL);
899         pthread_cond_init(&r->resolveWait, NULL);
900 }
901
902 /* No lock record must ever be destroyed because there may still be references
903  * to it.
904
905 static void destroyLockRecord(monitorLockRecord *r)
906 {
907         sem_destroy(&r->queueSem);
908         pthread_mutex_destroy(&r->resolveLock);
909         pthread_cond_destroy(&r->resolveWait);
910 }
911 */
912
913 void initLocks()
914 {
915         initThreadLocks(mainthreadobj);
916 }
917
918 static void initThreadLocks(threadobject *thread)
919 {
920         thread->ee.firstLR = NULL;
921         thread->ee.lrpool = NULL;
922         thread->ee.numlr = 0;
923 }
924
925 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
926 {
927         lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
928         int i;
929
930         p->header.size = size;
931         for (i=0; i<size; i++) {
932                 initLockRecord(&p->lr[i], thread);
933                 p->lr[i].nextFree = &p->lr[i+1];
934         }
935         p->lr[i-1].nextFree = NULL;
936         return p;
937 }
938
939 #define INITIALLOCKRECORDS 8
940
941 pthread_mutex_t pool_lock;
942 lockRecordPool *global_pool;
943
944 static void initPools()
945 {
946         pthread_mutex_init(&pool_lock, NULL);
947 }
948
949 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
950 {
951         pthread_mutex_lock(&pool_lock);
952         if (global_pool) {
953                 int i;
954                 lockRecordPool *pool = global_pool;
955                 global_pool = pool->header.next;
956                 pthread_mutex_unlock(&pool_lock);
957
958                 for (i=0; i < pool->header.size; i++) {
959                         pool->lr[i].ownerThread = t;
960                         pool->lr[i].nextFree = &pool->lr[i+1];
961                 }
962                 pool->lr[i-1].nextFree = NULL;
963                 
964                 return pool;
965         }
966         pthread_mutex_unlock(&pool_lock);
967
968         return allocNewLockRecordPool(t, size);
969 }
970
971 static void freeLockRecordPools(lockRecordPool *pool)
972 {
973         lockRecordPoolHeader *last;
974         pthread_mutex_lock(&pool_lock);
975         last = &pool->header;
976         while (last->next)
977                 last = &last->next->header;
978         last->next = global_pool;
979         global_pool = pool;
980         pthread_mutex_unlock(&pool_lock);
981 }
982
983 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
984 {
985         monitorLockRecord *r;
986
987         assert(t);
988         r = t->ee.firstLR;
989
990         if (!r) {
991                 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
992                 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
993                 pool->header.next = t->ee.lrpool;
994                 t->ee.lrpool = pool;
995                 r = &pool->lr[0];
996                 t->ee.numlr += pool->header.size;
997         }
998         
999         t->ee.firstLR = r->nextFree;
1000 #ifndef NDEBUG
1001         r->nextFree = NULL; /* in order to find invalid uses of nextFree */
1002 #endif
1003         return r;
1004 }
1005
1006 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
1007 {
1008         assert(t);
1009         assert(r);
1010         assert(r->ownerThread == t);
1011         assert(r->nextFree == NULL);
1012         
1013         r->nextFree = t->ee.firstLR;
1014         t->ee.firstLR = r;
1015 }
1016
1017 void initObjectLock(java_objectheader *o)
1018 {
1019         assert(o);
1020
1021         o->monitorPtr = dummyLR;
1022 }
1023
1024
1025 /* get_dummyLR *****************************************************************
1026
1027    Returns the global dummy monitor lock record. The pointer is
1028    required in the code generator to set up a virtual
1029    java_objectheader for code patch locking.
1030
1031 *******************************************************************************/
1032
1033 monitorLockRecord *get_dummyLR(void)
1034 {
1035         return dummyLR;
1036 }
1037
1038
1039 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
1040 {
1041         atomic_add(&lr->queuers, 1);
1042
1043         MEMORY_BARRIER_AFTER_ATOMIC();
1044
1045         if (lr->o == o)
1046                 sem_wait(&lr->queueSem);
1047
1048         atomic_add(&lr->queuers, -1);
1049 }
1050
1051 static void freeLockRecord(monitorLockRecord *lr)
1052 {
1053         int q;
1054         lr->o = NULL;
1055         MEMORY_BARRIER();
1056         q = lr->queuers;
1057         while (q--)
1058                 sem_post(&lr->queueSem);
1059 }
1060
1061 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr, java_objectheader *o)
1062 {
1063         if (lr->waiting == o)
1064                 mlr->waiter = lr;
1065 }
1066
1067 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
1068 {
1069         for (;;) {
1070                 monitorLockRecord *lr = o->monitorPtr;
1071                 if (lr->o != o) {
1072                         /* the lock record does not lock this object */
1073                         monitorLockRecord *nlr;
1074                         monitorLockRecord *mlr;
1075                    
1076                         /* allocate a new lock record for this object */
1077                         mlr     = allocLockRecordSimple(t);
1078                         mlr->o = o;
1079
1080                         /* check if it is the same record the object refered to earlier */
1081                         if (mlr == lr) {
1082                                 MEMORY_BARRIER();
1083                                 nlr = o->monitorPtr;
1084                                 if (nlr == lr) {
1085                                         /* the object still refers to the same lock record */
1086                                         /* got it! */
1087                                         handleWaiter(mlr, lr, o);
1088                                         return mlr;
1089                                 }
1090                         } 
1091                         else {
1092                                 /* no, it's another lock record */
1093                                 /* if we don't own the old record, set incharge XXX */
1094                                 if (lr->ownerThread != t)
1095                                         mlr->incharge = lr;
1096
1097                                 /* if the object still refers to lr, replace it by the new mlr */
1098                                 MEMORY_BARRIER_BEFORE_ATOMIC();
1099                                 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
1100                         }
1101
1102                         if (nlr == lr) {
1103                                 /* we swapped the new record in successfully */
1104                                 if (mlr == lr || lr->o != o) {
1105                                         /* the old lock record is the same as the new one, or */
1106                                         /* it locks another object.                           */
1107                                         /* got it! */
1108                                         handleWaiter(mlr, lr, o);
1109                                         return mlr;
1110                                 }
1111                                 /* lr locks the object, we have to wait */
1112                                 while (lr->o == o)
1113                                         queueOnLockRecord(lr, o);
1114
1115                                 /* got it! */
1116                                 handleWaiter(mlr, lr, o);
1117                                 return mlr;
1118                         }
1119
1120                         /* forget this mlr lock record, wait on nlr and try again */
1121                         freeLockRecord(mlr);
1122                         recycleLockRecord(t, mlr);
1123                         queueOnLockRecord(nlr, o);
1124                 } 
1125                 else {
1126                         /* the lock record is for the object we want */
1127
1128                         if (lr->ownerThread == t) {
1129                                 /* we own it already, just recurse */
1130                                 lr->lockCount++;
1131                                 return lr;
1132                         }
1133
1134                         /* it's locked. we wait and then try again */
1135                         queueOnLockRecord(lr, o);
1136                 }
1137         }
1138 }
1139
1140 static void wakeWaiters(monitorLockRecord *lr)
1141 {
1142         monitorLockRecord *tmplr;
1143         s4 q;
1144
1145         /* assign lock record to a temporary variable */
1146
1147         tmplr = lr;
1148
1149         do {
1150                 q = tmplr->queuers;
1151
1152                 while (q--)
1153                         sem_post(&tmplr->queueSem);
1154
1155                 tmplr = tmplr->waiter;
1156         } while (tmplr != NULL && tmplr != lr);
1157 }
1158
1159 #define GRAB_LR(lr,t) \
1160     if (lr->ownerThread != t) { \
1161                 lr = lr->incharge; \
1162         }
1163
1164 #define CHECK_MONITORSTATE(lr,t,mo,a) \
1165     if (lr->o != mo || lr->ownerThread != t) { \
1166                 *exceptionptr = new_illegalmonitorstateexception(); \
1167                 a; \
1168         }
1169
1170 bool monitorExit(threadobject *t, java_objectheader *o)
1171 {
1172         monitorLockRecord *lr = o->monitorPtr;
1173         GRAB_LR(lr, t);
1174         CHECK_MONITORSTATE(lr, t, o, return false);
1175
1176         if (lr->lockCount > 1) {
1177                 /* we had locked this one recursively. just decrement, it will */
1178                 /* still be locked. */
1179                 lr->lockCount--;
1180                 return true;
1181         }
1182         
1183         if (lr->waiter) {
1184                 monitorLockRecord *wlr = lr->waiter;
1185                 if (o->monitorPtr != lr ||
1186                         (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
1187                 {
1188                         monitorLockRecord *nlr = o->monitorPtr;
1189                         nlr->waiter = wlr;
1190                         STORE_ORDER_BARRIER();
1191                 } 
1192                 else {
1193                         wakeWaiters(wlr);
1194                 }
1195                 lr->waiter = NULL;
1196         }
1197
1198         /* unlock and throw away this lock record */
1199         freeLockRecord(lr);
1200         recycleLockRecord(t, lr);
1201         return true;
1202 }
1203
1204 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
1205 {
1206         do {
1207                 if (lr->waiter == wlr) {
1208                         lr->waiter = wlr->waiter;
1209                         break;
1210                 }
1211                 lr = lr->waiter;
1212         } while (lr); /* XXX need to break cycle? */
1213 }
1214
1215 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
1216 {
1217         return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1218 }
1219
1220 static bool timeIsEarlier(const struct timespec *tv)
1221 {
1222         struct timeval tvnow;
1223         struct timespec tsnow;
1224         gettimeofday(&tvnow, NULL);
1225         tsnow.tv_sec = tvnow.tv_sec;
1226         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1227         return timespec_less(&tsnow, tv);
1228 }
1229
1230
1231 /* waitWithTimeout *************************************************************
1232
1233    XXX
1234
1235 *******************************************************************************/
1236
1237 static bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
1238 {
1239         bool wasinterrupted;
1240
1241         pthread_mutex_lock(&t->waitLock);
1242
1243         t->isSleeping = true;
1244
1245         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1246                 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
1247                         pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1248         }
1249         else {
1250                 while (!t->interrupted && !t->signaled)
1251                         pthread_cond_wait(&t->waitCond, &t->waitLock);
1252         }
1253
1254         wasinterrupted = t->interrupted;
1255         t->interrupted = false;
1256         t->signaled = false;
1257         t->isSleeping = false;
1258
1259         pthread_mutex_unlock(&t->waitLock);
1260
1261         return wasinterrupted;
1262 }
1263
1264
1265 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1266 {
1267         if (millis || nanos) {
1268                 struct timeval tv;
1269                 long nsec;
1270                 gettimeofday(&tv, NULL);
1271                 tv.tv_sec += millis / 1000;
1272                 millis %= 1000;
1273                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1274                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1275                 tm->tv_nsec = nsec % 1000000000;
1276         } 
1277         else {
1278                 tm->tv_sec = 0;
1279                 tm->tv_nsec = 0;
1280         }
1281 }
1282
1283 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1284 {
1285         bool wasinterrupted;
1286         struct timespec wakeupTime;
1287         monitorLockRecord *mlr, *lr = o->monitorPtr;
1288         GRAB_LR(lr, t);
1289         CHECK_MONITORSTATE(lr, t, o, return);
1290
1291         calcAbsoluteTime(&wakeupTime, millis, nanos);
1292         
1293         if (lr->waiter)
1294                 wakeWaiters(lr->waiter);
1295         lr->waiting = o;
1296         STORE_ORDER_BARRIER();
1297         freeLockRecord(lr);
1298         wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1299         mlr = monitorEnter(t, o);
1300         removeFromWaiters(mlr, lr);
1301         mlr->lockCount = lr->lockCount;
1302         lr->lockCount = 1;
1303         lr->waiting = NULL;
1304         lr->waiter = NULL;
1305         recycleLockRecord(t, lr);
1306
1307         if (wasinterrupted)
1308                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1309 }
1310
1311 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1312 {
1313         monitorLockRecord *lr = o->monitorPtr;
1314         GRAB_LR(lr, t);
1315         CHECK_MONITORSTATE(lr, t, o, return);
1316         do {
1317                 threadobject *wthread;
1318                 monitorLockRecord *wlr = lr->waiter;
1319                 if (!wlr)
1320                         break;
1321                 wthread = wlr->ownerThread;
1322                 pthread_mutex_lock(&wthread->waitLock);
1323                 if (wthread->isSleeping)
1324                         pthread_cond_signal(&wthread->waitCond);
1325                 wthread->signaled = true;
1326                 pthread_mutex_unlock(&wthread->waitLock);
1327                 lr = wlr;
1328         } while (!one);
1329 }
1330
1331 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1332 {
1333         monitorLockRecord *lr = o->monitorPtr;
1334         GRAB_LR(lr, t);
1335         /* The reason why we have to check against NULL is that
1336          * dummyLR->incharge == NULL */
1337         return lr->o == o && lr->ownerThread == t;
1338 }
1339
1340 void interruptThread(java_lang_VMThread *thread)
1341 {
1342         threadobject *t = (threadobject*) thread;
1343
1344         pthread_mutex_lock(&t->waitLock);
1345         if (t->isSleeping)
1346                 pthread_cond_signal(&t->waitCond);
1347         t->interrupted = true;
1348         pthread_mutex_unlock(&t->waitLock);
1349 }
1350
1351 bool interruptedThread()
1352 {
1353         threadobject *t = (threadobject*) THREADOBJECT;
1354         bool intr = t->interrupted;
1355         t->interrupted = false;
1356         return intr;
1357 }
1358
1359 bool isInterruptedThread(java_lang_VMThread *thread)
1360 {
1361         threadobject *t = (threadobject*) thread;
1362         return t->interrupted;
1363 }
1364
1365
1366 /* thread_sleep ****************************************************************
1367
1368    Sleep the current thread for the specified amount of time.
1369
1370 *******************************************************************************/
1371
1372 void thread_sleep(s8 millis, s4 nanos)
1373 {
1374         threadobject       *t;
1375         struct timespec    wakeupTime;
1376         monitorLockRecord *lr;
1377         bool               wasinterrupted;
1378
1379         t = (threadobject *) THREADOBJECT;
1380
1381         calcAbsoluteTime(&wakeupTime, millis, nanos);
1382
1383         lr = allocLockRecordSimple(t);
1384
1385         wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1386
1387         recycleLockRecord(t, lr);
1388
1389         if (wasinterrupted)
1390                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1391 }
1392
1393 void yieldThread()
1394 {
1395         sched_yield();
1396 }
1397
1398 void setPriorityThread(thread *t, s4 priority)
1399 {
1400         nativethread *info = &((threadobject*) t->vmThread)->info;
1401         setPriority(info->tid, priority);
1402 }
1403
1404 void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
1405 {
1406         threadobject *t = (threadobject*) THREADOBJECT;
1407         monitorWait(t, o, millis, nanos);
1408 }
1409
1410 void signal_cond_for_object(java_objectheader *o)
1411 {
1412         threadobject *t = (threadobject*) THREADOBJECT;
1413         notifyOneOrAll(t, o, true);
1414 }
1415
1416 void broadcast_cond_for_object(java_objectheader *o)
1417 {
1418         threadobject *t = (threadobject*) THREADOBJECT;
1419         notifyOneOrAll(t, o, false);
1420 }
1421
1422
1423 /* threads_dump ****************************************************************
1424
1425    Dumps info for all threads running in the JVM. This function is
1426    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1427
1428 *******************************************************************************/
1429
1430 void threads_dump(void)
1431 {
1432         threadobject       *tobj;
1433         java_lang_VMThread *vmt;
1434         nativethread       *nt;
1435         java_lang_Thread   *t;
1436         utf                *name;
1437
1438         tobj = mainthreadobj;
1439
1440         printf("Full thread dump CACAO "VERSION":\n");
1441
1442         /* iterate over all started threads */
1443
1444         do {
1445                 /* get thread objects */
1446
1447                 vmt = &tobj->o;
1448                 nt  = &tobj->info;
1449                 t   = vmt->thread;
1450
1451                 /* the thread may be currently in initalization, don't print it */
1452
1453                 if (t) {
1454                         /* get thread name */
1455
1456                         name = javastring_toutf(t->name, false);
1457
1458                         printf("\n\"");
1459                         utf_display(name);
1460                         printf("\" ");
1461
1462                         if (t->daemon)
1463                                 printf("daemon ");
1464
1465 #if SIZEOF_VOID_P == 8
1466                         printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1467 #else
1468                         printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1469 #endif
1470
1471                         /* send SIGUSR1 to thread to print stacktrace */
1472
1473                         pthread_kill(nt->tid, SIGUSR1);
1474
1475                         /* sleep this thread a bit, so the signal can reach the thread */
1476
1477                         thread_sleep(10, 0);
1478                 }
1479
1480                 tobj = tobj->info.next;
1481         } while (tobj && (tobj != mainthreadobj));
1482 }
1483
1484
1485 /*
1486  * These are local overrides for various environment variables in Emacs.
1487  * Please do not remove this and leave it at the end of the file, where
1488  * Emacs will automagically detect them.
1489  * ---------------------------------------------------------------------
1490  * Local variables:
1491  * mode: c
1492  * indent-tabs-mode: t
1493  * c-basic-offset: 4
1494  * tab-width: 4
1495  * End:
1496  * vim:noexpandtab:sw=4:ts=4:
1497  */