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