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