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