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