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