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