* src/threads/native/threads.c (monitorExit): Added an assert to
[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 4903 2006-05-11 12:48:43Z edwin $
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 /******************************************************************************/
98 /* Recursive Mutex Implementation for Darwin                                  */
99 /******************************************************************************/
100
101 #ifdef MUTEXSIM
102
103 /* We need this for older MacOSX (10.1.x) */
104
105 typedef struct {
106         pthread_mutex_t mutex;
107         pthread_t owner;
108         int count;
109 } pthread_mutex_rec_t;
110
111 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
112 {
113         pthread_mutex_init(&m->mutex, NULL);
114         m->count = 0;
115 }
116
117 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
118 {
119         pthread_mutex_destroy(&m->mutex);
120 }
121
122 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
123 {
124         for (;;) {
125                 if (!m->count)
126                 {
127                         pthread_mutex_lock(&m->mutex);
128                         m->owner = pthread_self();
129                         m->count++;
130                         break;
131                 }
132                 else {
133                         if (m->owner != pthread_self()) {
134                                 pthread_mutex_lock(&m->mutex);
135                         }
136                         else {
137                                 m->count++;
138                                 break;
139                         }
140                 }
141         }
142 }
143
144 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
145 {
146         if (!--m->count)
147                 pthread_mutex_unlock(&m->mutex);
148 }
149
150 #else /* MUTEXSIM */
151
152 #define pthread_mutex_lock_rec pthread_mutex_lock
153 #define pthread_mutex_unlock_rec pthread_mutex_unlock
154 #define pthread_mutex_rec_t pthread_mutex_t
155
156 #endif /* MUTEXSIM */
157
158 /* threads_sem_init ************************************************************
159  
160    Initialize a semaphore. Checks against errors and interruptions.
161
162    IN:
163        sem..............the semaphore to initialize
164            shared...........true if this semaphore will be shared between processes
165            value............the initial value for the semaphore
166    
167 *******************************************************************************/
168
169 void threads_sem_init(sem_t *sem, bool shared, int value)
170 {
171         int r;
172
173         assert(sem);
174
175         do {
176                 r = sem_init(sem, shared, value);
177                 if (r == 0)
178                         return;
179         } while (errno == EINTR);
180
181         fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
182                         errno, strerror(errno));
183         abort();
184 }
185
186 /* threads_sem_wait ************************************************************
187  
188    Wait for a semaphore, non-interruptible.
189
190    IMPORTANT: Always use this function instead of `sem_wait` directly, as
191               `sem_wait` may be interrupted by signals!
192   
193    IN:
194        sem..............the semaphore to wait on
195    
196 *******************************************************************************/
197
198 void threads_sem_wait(sem_t *sem)
199 {
200         int r;
201
202         assert(sem);
203
204         do {
205                 r = sem_wait(sem);
206                 if (r == 0)
207                         return;
208         } while (errno == EINTR);
209
210         fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
211                         errno, strerror(errno));
212         abort();
213 }
214
215 /* threads_sem_post ************************************************************
216  
217    Increase the count of a semaphore. Checks for errors.
218
219    IN:
220        sem..............the semaphore to increase the count of
221    
222 *******************************************************************************/
223
224 void threads_sem_post(sem_t *sem)
225 {
226         int r;
227
228         assert(sem);
229
230         /* unlike sem_wait, sem_post is not interruptible */
231
232         r = sem_post(sem);
233         if (r == 0)
234                 return;
235
236         fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
237                         errno, strerror(errno));
238         abort();
239 }
240
241 /* threads_set_thread_priority *************************************************
242
243    Set the priority of the given thread.
244
245    IN:
246       tid..........thread id
247           priority.....priority to set
248
249 ******************************************************************************/
250
251 static void threads_set_thread_priority(pthread_t tid, int priority)
252 {
253         struct sched_param schedp;
254         int policy;
255
256         pthread_getschedparam(tid, &policy, &schedp);
257         schedp.sched_priority = priority;
258         pthread_setschedparam(tid, policy, &schedp);
259 }
260
261
262 static avl_tree *criticaltree;
263 threadobject *mainthreadobj;
264
265 #ifndef HAVE___THREAD
266 pthread_key_t tkey_threadinfo;
267 #else
268 __thread threadobject *threadobj;
269 #endif
270
271 static pthread_mutex_rec_t compiler_mutex;
272
273 void compiler_lock()
274 {
275         pthread_mutex_lock_rec(&compiler_mutex);
276 }
277
278 void compiler_unlock()
279 {
280         pthread_mutex_unlock_rec(&compiler_mutex);
281 }
282
283 static s4 criticalcompare(const void *pa, const void *pb)
284 {
285         const threadcritnode *na = pa;
286         const threadcritnode *nb = pb;
287
288         if (na->mcodebegin < nb->mcodebegin)
289                 return -1;
290         if (na->mcodebegin > nb->mcodebegin)
291                 return 1;
292         return 0;
293 }
294
295
296 static const threadcritnode *findcritical(u1 *mcodeptr)
297 {
298     avl_node *n;
299     const threadcritnode *m;
300
301     n = criticaltree->root;
302         m = NULL;
303
304     if (!n)
305         return NULL;
306
307     for (;;) {
308         const threadcritnode *d = n->data;
309
310         if (mcodeptr == d->mcodebegin)
311             return d;
312
313         if (mcodeptr < d->mcodebegin) {
314             if (n->childs[0]) {
315                 n = n->childs[0];
316                         }
317             else {
318                 return m;
319                         }
320         }
321                 else {
322             if (n->childs[1]) {
323                 m = n->data;
324                 n = n->childs[1];
325             }
326                         else {
327                 return n->data;
328                         }
329         }
330     }
331 }
332
333
334 void thread_registercritical(threadcritnode *n)
335 {
336         avl_insert(criticaltree, n);
337 }
338
339 u1 *thread_checkcritical(u1 *mcodeptr)
340 {
341         const threadcritnode *n = findcritical(mcodeptr);
342         return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
343 }
344
345 static void thread_addstaticcritical()
346 {
347         /* XXX TWISTI: this is just a quick hack */
348 #if defined(ENABLE_JIT)
349         threadcritnode *n = &asm_criticalsections;
350
351         while (n->mcodebegin)
352                 thread_registercritical(n++);
353 #endif
354 }
355
356 static pthread_mutex_t threadlistlock;
357
358 static pthread_mutex_t stopworldlock;
359 volatile int stopworldwhere;
360
361 static sem_t suspend_ack;
362 #if defined(__MIPS__)
363 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
364 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
365 #endif
366
367 /*
368  * where - 1 from within GC
369            2 class numbering
370  */
371 void lock_stopworld(int where)
372 {
373         pthread_mutex_lock(&stopworldlock);
374         stopworldwhere = where;
375 }
376
377 void unlock_stopworld()
378 {
379         stopworldwhere = 0;
380         pthread_mutex_unlock(&stopworldlock);
381 }
382
383 #if !defined(__DARWIN__)
384 /* Caller must hold threadlistlock */
385 static int cast_sendsignals(int sig, int count)
386 {
387         /* Count threads */
388         threadobject *tobj = mainthreadobj;
389         nativethread *infoself = THREADINFO;
390
391         if (count == 0) {
392                 do {
393                         count++;
394                         tobj = tobj->info.next;
395                 } while (tobj != mainthreadobj);
396         }
397
398         do {
399                 nativethread *info = &tobj->info;
400                 if (info != infoself)
401                         pthread_kill(info->tid, sig);
402                 tobj = tobj->info.next;
403         } while (tobj != mainthreadobj);
404
405         return count-1;
406 }
407
408 #else
409
410 static void cast_darwinstop()
411 {
412         threadobject *tobj = mainthreadobj;
413         nativethread *infoself = THREADINFO;
414
415         do {
416                 nativethread *info = &tobj->info;
417                 if (info != infoself)
418                 {
419                         thread_state_flavor_t flavor = PPC_THREAD_STATE;
420                         mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
421                         ppc_thread_state_t thread_state;
422                         mach_port_t thread = info->mach_thread;
423                         kern_return_t r;
424
425                         r = thread_suspend(thread);
426                         if (r != KERN_SUCCESS) {
427                                 log_text("thread_suspend failed");
428                                 assert(0);
429                         }
430
431                         r = thread_get_state(thread, flavor,
432                                 (natural_t*)&thread_state, &thread_state_count);
433                         if (r != KERN_SUCCESS) {
434                                 log_text("thread_get_state failed");
435                                 assert(0);
436                         }
437
438                         thread_restartcriticalsection(&thread_state);
439
440                         r = thread_set_state(thread, flavor,
441                                 (natural_t*)&thread_state, thread_state_count);
442                         if (r != KERN_SUCCESS) {
443                                 log_text("thread_set_state failed");
444                                 assert(0);
445                         }
446                 }
447                 tobj = tobj->info.next;
448         } while (tobj != mainthreadobj);
449 }
450
451 static void cast_darwinresume()
452 {
453         threadobject *tobj = mainthreadobj;
454         nativethread *infoself = THREADINFO;
455
456         do {
457                 nativethread *info = &tobj->info;
458                 if (info != infoself)
459                 {
460                         mach_port_t thread = info->mach_thread;
461                         kern_return_t r;
462
463                         r = thread_resume(thread);
464                         if (r != KERN_SUCCESS) {
465                                 log_text("thread_resume failed");
466                                 assert(0);
467                         }
468                 }
469                 tobj = tobj->info.next;
470         } while (tobj != mainthreadobj);
471 }
472
473 #endif
474
475 #if defined(__MIPS__)
476 static void cast_irixresume()
477 {
478         pthread_mutex_lock(&suspend_ack_lock);
479         pthread_cond_broadcast(&suspend_cond);
480         pthread_mutex_unlock(&suspend_ack_lock);
481 }
482 #endif
483
484 void cast_stopworld()
485 {
486         int count, i;
487         lock_stopworld(2);
488         pthread_mutex_lock(&threadlistlock);
489 #if defined(__DARWIN__)
490         cast_darwinstop();
491 #else
492         count = cast_sendsignals(GC_signum1(), 0);
493         for (i=0; i<count; i++)
494                 threads_sem_wait(&suspend_ack);
495 #endif
496         pthread_mutex_unlock(&threadlistlock);
497 }
498
499 void cast_startworld()
500 {
501         pthread_mutex_lock(&threadlistlock);
502 #if defined(__DARWIN__)
503         cast_darwinresume();
504 #elif defined(__MIPS__)
505         cast_irixresume();
506 #else
507         cast_sendsignals(GC_signum2(), -1);
508 #endif
509         pthread_mutex_unlock(&threadlistlock);
510         unlock_stopworld();
511 }
512
513 #if !defined(__DARWIN__)
514 static void sigsuspend_handler(ucontext_t *ctx)
515 {
516         int sig;
517         sigset_t sigs;
518
519         /* XXX TWISTI: this is just a quick hack */
520 #if defined(ENABLE_JIT)
521         thread_restartcriticalsection(ctx);
522 #endif
523
524         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
525            (not POSIX async-safe). */
526 #if defined(__IRIX__)
527         pthread_mutex_lock(&suspend_ack_lock);
528         threads_sem_post(&suspend_ack);
529         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
530         pthread_mutex_unlock(&suspend_ack_lock);
531 #else
532         threads_sem_post(&suspend_ack);
533
534         sig = GC_signum2();
535         sigfillset(&sigs);
536         sigdelset(&sigs, sig);
537         sigsuspend(&sigs);
538 #endif
539 }
540
541 int cacao_suspendhandler(ucontext_t *ctx)
542 {
543         if (stopworldwhere != 2)
544                 return 0;
545
546         sigsuspend_handler(ctx);
547         return 1;
548 }
549 #endif
550
551 #if !defined(ENABLE_JVMTI)
552 static void setthreadobject(threadobject *thread)
553 #else
554 void setthreadobject(threadobject *thread)
555 #endif
556 {
557 #if !defined(HAVE___THREAD)
558         pthread_setspecific(tkey_threadinfo, thread);
559 #else
560         threadobj = thread;
561 #endif
562 }
563
564
565 /* thread_setself **************************************************************
566
567    Return the threadobject of the current thread.
568    
569    XXX The return value type should be changed to a typed pointer.
570
571 *******************************************************************************/
572
573 void *thread_getself(void)
574 {
575         return THREADOBJECT;
576 }
577
578 /* unlocked dummy record - avoids NULL checks */
579 static monitorLockRecord *dummyLR;
580
581 static void initPools();
582
583
584 /* thread_preinit **************************************************************
585
586    Do some early initialization of stuff required.
587
588 *******************************************************************************/
589
590 void threads_preinit(void)
591 {
592 #ifndef MUTEXSIM
593         pthread_mutexattr_t mutexattr;
594         pthread_mutexattr_init(&mutexattr);
595         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
596         pthread_mutex_init(&compiler_mutex, &mutexattr);
597         pthread_mutexattr_destroy(&mutexattr);
598 #else
599         pthread_mutex_init_rec(&compiler_mutex);
600 #endif
601
602         pthread_mutex_init(&threadlistlock, NULL);
603         pthread_mutex_init(&stopworldlock, NULL);
604
605         /* Allocate something so the garbage collector's signal handlers
606            are installed. */
607         heap_allocate(1, false, NULL);
608
609         mainthreadobj = NEW(threadobject);
610         mainthreadobj->info.tid = pthread_self();
611 #if !defined(HAVE___THREAD)
612         pthread_key_create(&tkey_threadinfo, NULL);
613 #endif
614         setthreadobject(mainthreadobj);
615         initPools();
616
617         /* Every newly created object's monitorPtr points here so we save
618            a check against NULL */
619
620         dummyLR = NEW(monitorLockRecord);
621         dummyLR->o = NULL;
622         dummyLR->ownerThread = NULL;
623         dummyLR->waiting = NULL;
624         dummyLR->incharge = dummyLR;
625
626         /* we need a working dummyLR before initializing the critical
627            section tree */
628
629     criticaltree = avl_create(&criticalcompare);
630
631         thread_addstaticcritical();
632         threads_sem_init(&suspend_ack, 0, 0);
633 }
634
635
636 static pthread_attr_t threadattr;
637
638 static void freeLockRecordPools(lockRecordPool *);
639
640
641 /* threads_init ****************************************************************
642
643    Initializes the threads required by the JVM: main, finalizer.
644
645 *******************************************************************************/
646
647 bool threads_init(u1 *stackbottom)
648 {
649         java_lang_String      *threadname;
650         java_lang_Thread      *mainthread;
651         java_lang_ThreadGroup *threadgroup;
652         threadobject          *tempthread;
653         methodinfo            *method;
654
655         tempthread = mainthreadobj;
656
657         freeLockRecordPools(mainthreadobj->ee.lrpool);
658
659         /* This is kinda tricky, we grow the java.lang.Thread object so we
660            can keep the execution environment there. No Thread object must
661            have been created at an earlier time. */
662
663         class_java_lang_VMThread->instancesize = sizeof(threadobject);
664
665         /* create a VMThread */
666
667         mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
668
669         if (!mainthreadobj)
670                 return false;
671
672         FREE(tempthread, threadobject);
673
674         initThread(&mainthreadobj->o);
675
676         setthreadobject(mainthreadobj);
677
678         initLocks();
679
680         mainthreadobj->info.next = mainthreadobj;
681         mainthreadobj->info.prev = mainthreadobj;
682
683 #if defined(ENABLE_INTRP)
684         /* create interpreter stack */
685
686         if (opt_intrp) {
687                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
688                 mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
689         }
690 #endif
691
692         threadname = javastring_new(utf_new_char("main"));
693
694         /* allocate and init ThreadGroup */
695
696         threadgroup = (java_lang_ThreadGroup *)
697                 native_new_and_init(class_java_lang_ThreadGroup);
698
699         if (!threadgroup)
700                 throw_exception_exit();
701
702         /* create a Thread */
703
704         mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
705
706         if (!mainthread)
707                 throw_exception_exit();
708
709         mainthreadobj->o.thread = mainthread;
710
711         /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
712
713         method = class_resolveclassmethod(class_java_lang_Thread,
714                                                                           utf_init,
715                                                                           utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
716                                                                           class_java_lang_Thread,
717                                                                           true);
718
719         if (!method)
720                 return false;
721
722         (void) vm_call_method(method, (java_objectheader *) mainthread,
723                                                   mainthreadobj, threadname, 5, false);
724
725         if (*exceptionptr)
726                 return false;
727
728         mainthread->group = threadgroup;
729
730         /* add mainthread to ThreadGroup */
731
732         method = class_resolveclassmethod(class_java_lang_ThreadGroup,
733                                                                           utf_new_char("addThread"),
734                                                                           utf_new_char("(Ljava/lang/Thread;)V"),
735                                                                           class_java_lang_ThreadGroup,
736                                                                           true);
737
738         if (!method)
739                 return false;
740
741         (void) vm_call_method(method, (java_objectheader *) threadgroup,
742                                                   mainthread);
743
744         if (*exceptionptr)
745                 return false;
746
747         threads_set_thread_priority(pthread_self(), 5);
748
749         pthread_attr_init(&threadattr);
750         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
751
752         /* everything's ok */
753
754         return true;
755 }
756
757
758 void initThread(java_lang_VMThread *t)
759 {
760         threadobject *thread = (threadobject*) t;
761         nativethread *info = &thread->info;
762         info->tid = pthread_self();
763         /* TODO destroy all those things */
764         pthread_mutex_init(&info->joinMutex, NULL);
765         pthread_cond_init(&info->joinCond, NULL);
766
767         pthread_mutex_init(&thread->waitLock, NULL);
768         pthread_cond_init(&thread->waitCond, NULL);
769         thread->interrupted = false;
770         thread->signaled = false;
771         thread->isSleeping = false;
772 }
773
774 static void initThreadLocks(threadobject *);
775
776
777 /* startupinfo *****************************************************************
778
779    Struct used to pass info from threads_start_thread to 
780    threads_startup_thread.
781
782 ******************************************************************************/
783
784 typedef struct {
785         threadobject *thread;      /* threadobject for this thread             */
786         functionptr   function;    /* function to run in the new thread        */
787         sem_t        *psem;        /* signals when thread has been entered     */
788                                    /* in the thread list                       */
789         sem_t        *psem_first;  /* signals when pthread_create has returned */
790 } startupinfo;
791
792
793 /* threads_startup_thread ******************************************************
794
795    Thread startup function called by pthread_create.
796
797    NOTE: This function is not called directly by pthread_create. The Boehm GC
798          inserts its own GC_start_routine in between, which then calls
799                  threads_startup.
800
801    IN:
802       t............the argument passed to pthread_create, ie. a pointer to
803                        a startupinfo struct. CAUTION: When the `psem` semaphore
804                                    is posted, the startupinfo struct becomes invalid! (It
805                                    is allocated on the stack of threads_start_thread.)
806
807 ******************************************************************************/
808
809 static void *threads_startup_thread(void *t)
810 {
811         startupinfo  *startup;
812         threadobject *thread;
813         sem_t        *psem;
814         nativethread *info;
815         threadobject *tnext;
816         methodinfo   *method;
817         functionptr   function;
818
819 #if defined(ENABLE_INTRP)
820         u1 *intrp_thread_stack;
821
822         /* create interpreter stack */
823
824         if (opt_intrp) {
825                 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
826                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
827         } else {
828                 intrp_thread_stack = NULL;
829         }
830 #endif
831
832         /* get passed startupinfo structure and the values in there */
833
834         startup = t;
835         t = NULL; /* make sure it's not used wrongly */
836
837         thread   = startup->thread;
838         function = startup->function;
839         psem     = startup->psem;
840
841         info = &thread->info;
842
843         /* Seems like we've encountered a situation where info->tid was not set by
844          * pthread_create. We alleviate this problem by waiting for pthread_create
845          * to return. */
846         threads_sem_wait(startup->psem_first);
847
848         /* set the thread object */
849
850 #if defined(__DARWIN__)
851         info->mach_thread = mach_thread_self();
852 #endif
853         setthreadobject(thread);
854
855         /* insert the thread into the threadlist */
856
857         pthread_mutex_lock(&threadlistlock);
858
859         info->prev = mainthreadobj;
860         info->next = tnext = mainthreadobj->info.next;
861         mainthreadobj->info.next = thread;
862         tnext->info.prev = thread;
863
864         pthread_mutex_unlock(&threadlistlock);
865
866         /* init data structures of this thread */
867
868         initThreadLocks(thread);
869
870         /* tell threads_startup_thread that we registered ourselves */
871         /* CAUTION: *startup becomes invalid with this!             */
872
873         startup = NULL;
874         threads_sem_post(psem);
875
876         /* set our priority */
877
878         threads_set_thread_priority(info->tid, thread->o.thread->priority);
879
880 #if defined(ENABLE_INTRP)
881         /* set interpreter stack */
882
883         if (opt_intrp)
884                 THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
885 #endif
886
887         /* find and run the Thread.run()V method if no other function was passed */
888
889         if (function == NULL) {
890                 method = class_resolveclassmethod(thread->o.header.vftbl->class,
891                                                                                   utf_run,
892                                                                                   utf_void__void,
893                                                                                   thread->o.header.vftbl->class,
894                                                                                   true);
895
896                 if (!method)
897                         throw_exception();
898
899                 (void) vm_call_method(method, (java_objectheader *) thread);
900
901         }
902         else {
903                 /* call passed function, e.g. finalizer_thread */
904
905                 (function)();
906         }
907
908         /* Allow lock record pools to be used by other threads. They
909            cannot be deleted so we'd better not waste them. */
910
911         freeLockRecordPools(thread->ee.lrpool);
912
913         /* remove thread from thread list, do this inside a lock */
914
915         pthread_mutex_lock(&threadlistlock);
916         info->next->info.prev = info->prev;
917         info->prev->info.next = info->next;
918         pthread_mutex_unlock(&threadlistlock);
919
920         /* reset thread id (lock on joinMutex? TWISTI) */
921
922         pthread_mutex_lock(&info->joinMutex);
923         info->tid = 0;
924         pthread_mutex_unlock(&info->joinMutex);
925
926         /* tell everyone that a thread has finished */
927
928         pthread_cond_broadcast(&info->joinCond);
929
930         return NULL;
931 }
932
933
934 /* threads_start_thread ********************************************************
935
936    Start a thread in the JVM.
937
938    IN:
939       t............the java.lang.Thread object
940           function.....function to run in the new thread. NULL means that the
941                        "run" method of the object `t` should be called
942
943 ******************************************************************************/
944
945 void threads_start_thread(thread *t, functionptr function)
946 {
947         nativethread *info;
948         sem_t         sem;
949         sem_t         sem_first;
950         startupinfo   startup;
951
952         info = &((threadobject *) t->vmThread)->info;
953
954         /* fill startupinfo structure passed by pthread_create to
955          * threads_startup_thread */
956
957         startup.thread     = (threadobject*) t->vmThread;
958         startup.function   = function;       /* maybe we don't call Thread.run()V */
959         startup.psem       = &sem;
960         startup.psem_first = &sem_first;
961
962         threads_sem_init(&sem, 0, 0);
963         threads_sem_init(&sem_first, 0, 0);
964
965         /* create the thread */
966
967         if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
968                                            &startup)) {
969                 log_text("pthread_create failed");
970                 assert(0);
971         }
972
973         /* signal that pthread_create has returned, so info->tid is valid */
974
975         threads_sem_post(&sem_first);
976
977         /* wait here until the thread has entered itself into the thread list */
978
979         threads_sem_wait(&sem);
980
981         /* cleanup */
982
983         sem_destroy(&sem);
984         sem_destroy(&sem_first);
985 }
986
987
988 /* At the end of the program, we wait for all running non-daemon threads to die
989  */
990
991 static threadobject *findNonDaemon(threadobject *thread)
992 {
993         while (thread != mainthreadobj) {
994                 if (!thread->o.thread->daemon)
995                         return thread;
996                 thread = thread->info.prev;
997         }
998
999         return NULL;
1000 }
1001
1002 void joinAllThreads()
1003 {
1004         threadobject *thread;
1005         pthread_mutex_lock(&threadlistlock);
1006         while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
1007                 nativethread *info = &thread->info;
1008                 pthread_mutex_lock(&info->joinMutex);
1009                 pthread_mutex_unlock(&threadlistlock);
1010                 while (info->tid)
1011                         pthread_cond_wait(&info->joinCond, &info->joinMutex);
1012                 pthread_mutex_unlock(&info->joinMutex);
1013                 pthread_mutex_lock(&threadlistlock);
1014         }
1015         pthread_mutex_unlock(&threadlistlock);
1016 }
1017
1018 static void initLockRecord(monitorLockRecord *r, threadobject *t)
1019 {
1020         r->lockCount = 1;
1021         r->ownerThread = t;
1022         r->queuers = 0;
1023         r->o = NULL;
1024         r->waiter = NULL;
1025         r->incharge = (monitorLockRecord *) &dummyLR;
1026         r->waiting = NULL;
1027         threads_sem_init(&r->queueSem, 0, 0);
1028         pthread_mutex_init(&r->resolveLock, NULL);
1029         pthread_cond_init(&r->resolveWait, NULL);
1030 }
1031
1032 void initLocks()
1033 {
1034         initThreadLocks(mainthreadobj);
1035 }
1036
1037 static void initThreadLocks(threadobject *thread)
1038 {
1039         thread->ee.firstLR = NULL;
1040         thread->ee.lrpool = NULL;
1041         thread->ee.numlr = 0;
1042 }
1043
1044 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
1045 {
1046         lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
1047         int i;
1048
1049         p->header.size = size;
1050         for (i=0; i<size; i++) {
1051                 initLockRecord(&p->lr[i], thread);
1052                 p->lr[i].nextFree = &p->lr[i+1];
1053         }
1054         p->lr[i-1].nextFree = NULL;
1055         return p;
1056 }
1057
1058 #define INITIALLOCKRECORDS 8
1059
1060 pthread_mutex_t pool_lock;
1061 lockRecordPool *global_pool;
1062
1063 static void initPools()
1064 {
1065         pthread_mutex_init(&pool_lock, NULL);
1066 }
1067
1068 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
1069 {
1070         pthread_mutex_lock(&pool_lock);
1071         if (global_pool) {
1072                 int i;
1073                 lockRecordPool *pool = global_pool;
1074                 global_pool = pool->header.next;
1075                 pthread_mutex_unlock(&pool_lock);
1076
1077                 for (i=0; i < pool->header.size; i++) {
1078                         pool->lr[i].ownerThread = t;
1079                         pool->lr[i].nextFree = &pool->lr[i+1];
1080                 }
1081                 pool->lr[i-1].nextFree = NULL;
1082
1083                 return pool;
1084         }
1085         pthread_mutex_unlock(&pool_lock);
1086
1087         return allocNewLockRecordPool(t, size);
1088 }
1089
1090 static void freeLockRecordPools(lockRecordPool *pool)
1091 {
1092         lockRecordPoolHeader *last;
1093         pthread_mutex_lock(&pool_lock);
1094         last = &pool->header;
1095         while (last->next)
1096                 last = &last->next->header;
1097         last->next = global_pool;
1098         global_pool = pool;
1099         pthread_mutex_unlock(&pool_lock);
1100 }
1101
1102 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
1103 {
1104         monitorLockRecord *r;
1105
1106         assert(t);
1107         r = t->ee.firstLR;
1108
1109         if (!r) {
1110                 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
1111                 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
1112                 pool->header.next = t->ee.lrpool;
1113                 t->ee.lrpool = pool;
1114                 r = &pool->lr[0];
1115                 t->ee.numlr += pool->header.size;
1116         }
1117
1118         t->ee.firstLR = r->nextFree;
1119 #ifndef NDEBUG
1120         r->nextFree = NULL; /* in order to find invalid uses of nextFree */
1121 #endif
1122         return r;
1123 }
1124
1125 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
1126 {
1127         assert(t);
1128         assert(r);
1129         assert(r->ownerThread == t);
1130         assert(r->nextFree == NULL);
1131
1132         r->nextFree = t->ee.firstLR;
1133         t->ee.firstLR = r;
1134 }
1135
1136 /* initObjectLock **************************************************************
1137
1138    Initialize the monitor pointer of the given object. The monitor gets
1139    initialized to an unlocked state.
1140
1141 *******************************************************************************/
1142
1143 void initObjectLock(java_objectheader *o)
1144 {
1145         assert(o);
1146
1147         o->monitorPtr = dummyLR;
1148 }
1149
1150
1151 /* get_dummyLR *****************************************************************
1152
1153    Returns the global dummy monitor lock record. The pointer is
1154    required in the code generator to set up a virtual
1155    java_objectheader for code patch locking.
1156
1157 *******************************************************************************/
1158
1159 monitorLockRecord *get_dummyLR(void)
1160 {
1161         return dummyLR;
1162 }
1163
1164
1165 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
1166 {
1167         atomic_add(&lr->queuers, 1);
1168         MEMORY_BARRIER_AFTER_ATOMIC();
1169
1170         if (lr->o == o)
1171                 threads_sem_wait(&lr->queueSem);
1172
1173         atomic_add(&lr->queuers, -1);
1174 }
1175
1176 static void freeLockRecord(monitorLockRecord *lr)
1177 {
1178         int q;
1179         lr->o = NULL;
1180         MEMORY_BARRIER();
1181         q = lr->queuers;
1182         while (q--)
1183                 threads_sem_post(&lr->queueSem);
1184 }
1185
1186 static inline void handleWaiter(monitorLockRecord *newlr,
1187                                                                 monitorLockRecord *curlr,
1188                                                                 java_objectheader *o)
1189 {
1190         /* if the current lock record is used for waiting on the object */
1191         /* `o`, then record it as a waiter in the new lock record       */
1192
1193         if (curlr->waiting == o)
1194                 newlr->waiter = curlr;
1195 }
1196
1197 /* monitorEnter ****************************************************************
1198
1199    Acquire the monitor of the given object. If the current thread already
1200    owns the monitor, the lock counter is simply increased.
1201
1202    This function blocks until it can acquire the monitor.
1203
1204    IN:
1205       t............the current thread
1206           o............the object of which to enter the monitor
1207
1208    RETURN VALUE:
1209       the new lock record of the object when it has been entered
1210
1211 *******************************************************************************/
1212
1213 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
1214 {
1215         for (;;) {
1216                 monitorLockRecord *lr = o->monitorPtr;
1217                 if (lr->o != o) {
1218                         /* the lock record does not lock this object */
1219                         monitorLockRecord *nlr;
1220                         monitorLockRecord *mlr;
1221                    
1222                         /* allocate a new lock record for this object */
1223                         mlr     = allocLockRecordSimple(t);
1224                         mlr->o = o;
1225
1226                         /* check if it is the same record the object refered to earlier */
1227                         if (mlr == lr) {
1228                                 MEMORY_BARRIER();
1229                                 nlr = o->monitorPtr;
1230                                 if (nlr == lr) {
1231                                         /* the object still refers to the same lock record */
1232                                         /* got it! */
1233                                         handleWaiter(mlr, lr, o);
1234                                         return mlr;
1235                                 }
1236                         } 
1237                         else {
1238                                 /* no, it's another lock record */
1239                                 /* if we don't own the old record, set incharge XXX */
1240                                 if (lr->ownerThread != t)
1241                                         mlr->incharge = lr;
1242
1243                                 /* if the object still refers to lr, replace it by the new mlr */
1244                                 MEMORY_BARRIER_BEFORE_ATOMIC();
1245                                 nlr = (monitorLockRecord *) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
1246                         }
1247
1248                         if (nlr == lr) {
1249                                 /* we swapped the new record in successfully */
1250                                 if (mlr == lr || lr->o != o) {
1251                                         /* the old lock record is the same as the new one, or */
1252                                         /* it locks another object.                           */
1253                                         /* got it! */
1254                                         handleWaiter(mlr, lr, o);
1255                                         return mlr;
1256                                 }
1257                                 /* lr locks the object, we have to wait */
1258                                 while (lr->o == o)
1259                                         queueOnLockRecord(lr, o);
1260
1261                                 /* got it! */
1262                                 handleWaiter(mlr, lr, o);
1263                                 return mlr;
1264                         }
1265
1266                         /* forget this mlr lock record, wait on nlr and try again */
1267                         freeLockRecord(mlr);
1268                         recycleLockRecord(t, mlr);
1269                         queueOnLockRecord(nlr, o);
1270                 } 
1271                 else {
1272                         /* the lock record is for the object we want */
1273
1274                         if (lr->ownerThread == t) {
1275                                 /* we own it already, just recurse */
1276                                 lr->lockCount++;
1277                                 return lr;
1278                         }
1279
1280                         /* it's locked. we wait and then try again */
1281                         queueOnLockRecord(lr, o);
1282                 }
1283         }
1284 }
1285
1286 /* threads_wake_waiters ********************************************************
1287
1288    For each lock record in the given waiter list, post the queueSem
1289    once for each queuer of the lock record.
1290
1291    IN:
1292       lr...........the head of the waiter list
1293
1294 *******************************************************************************/
1295
1296 static void threads_wake_waiters(monitorLockRecord *lr)
1297 {
1298         monitorLockRecord *tmplr;
1299         s4 q;
1300
1301         /* move it to a local variable (Stefan commented this especially.
1302          * Might be important somehow...) */
1303
1304         tmplr = lr;
1305
1306         do {
1307                 q = tmplr->queuers;
1308
1309                 while (q--)
1310                         threads_sem_post(&tmplr->queueSem);
1311
1312                 tmplr = tmplr->waiter;
1313         } while (tmplr != NULL && tmplr != lr); /* this breaks cycles to lr */
1314 }
1315
1316 #define GRAB_LR(lr,t) \
1317     if (lr->ownerThread != t) { \
1318                 lr = lr->incharge; \
1319         }
1320
1321 #define CHECK_MONITORSTATE(lr,t,mo,a) \
1322     if (lr->o != mo || lr->ownerThread != t) { \
1323                 *exceptionptr = new_illegalmonitorstateexception(); \
1324                 a; \
1325         }
1326
1327 /* monitorExit *****************************************************************
1328
1329    Decrement the counter of a (currently owned) monitor. If the counter
1330    reaches zero, release the monitor.
1331
1332    If the current thread is not the owner of the monitor, an 
1333    IllegalMonitorState exception is thrown.
1334
1335    IN:
1336       t............the current thread
1337           o............the object of which to exit the monitor
1338
1339    RETURN VALUE:
1340       true.........everything ok,
1341           false........an exception has been thrown
1342
1343 *******************************************************************************/
1344
1345 bool monitorExit(threadobject *t, java_objectheader *o)
1346 {
1347         monitorLockRecord *lr;
1348
1349         lr = o->monitorPtr;
1350         GRAB_LR(lr, t);
1351         CHECK_MONITORSTATE(lr, t, o, return false);
1352
1353         /* { the current thread `t` owns the lock record `lr` on object `o` } */
1354
1355         if (lr->lockCount > 1) {
1356                 /* we had locked this one recursively. just decrement, it will */
1357                 /* still be locked. */
1358                 lr->lockCount--;
1359                 return true;
1360         }
1361
1362         /* we are going to unlock and recycle this lock record */
1363
1364         if (lr->waiter) {
1365                 monitorLockRecord *wlr = lr->waiter;
1366                 if (o->monitorPtr != lr ||
1367                         (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
1368                 {
1369                         monitorLockRecord *nlr = o->monitorPtr;
1370                         assert(nlr->waiter == NULL);
1371                         nlr->waiter = wlr; /* XXX is it ok to overwrite the nlr->waiter field like that? */
1372                         STORE_ORDER_BARRIER();
1373                 }
1374                 else {
1375                         threads_wake_waiters(wlr);
1376                 }
1377                 lr->waiter = NULL;
1378         }
1379
1380         /* unlock and throw away this lock record */
1381         freeLockRecord(lr);
1382         recycleLockRecord(t, lr);
1383         return true;
1384 }
1385
1386 /* threads_remove_waiter *******************************************************
1387
1388    Remove a waiter lock record from the waiter list of the given lock record
1389
1390    IN:
1391       lr...........the lock record holding the waiter list
1392           toremove.....the record to remove from the list
1393
1394 *******************************************************************************/
1395
1396 static void threads_remove_waiter(monitorLockRecord *lr,
1397                                                                   monitorLockRecord *toremove)
1398 {
1399         do {
1400                 if (lr->waiter == toremove) {
1401                         lr->waiter = toremove->waiter;
1402                         break;
1403                 }
1404                 lr = lr->waiter;
1405         } while (lr); /* XXX need to break cycle? */
1406 }
1407
1408 /* threads_timespec_earlier ****************************************************
1409
1410    Return true if timespec tv1 is earlier than timespec tv2.
1411
1412    IN:
1413       tv1..........first timespec
1414           tv2..........second timespec
1415
1416    RETURN VALUE:
1417       true, if the first timespec is earlier
1418
1419 *******************************************************************************/
1420
1421 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1422                                                                                         const struct timespec *tv2)
1423 {
1424         return (tv1->tv_sec < tv2->tv_sec)
1425                                 ||
1426                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1427 }
1428
1429 /* threads_current_time_is_earlier_than ****************************************
1430
1431    Check if the current time is earlier than the given timespec.
1432
1433    IN:
1434       tv...........the timespec to compare against
1435
1436    RETURN VALUE:
1437       true, if the current time is earlier
1438
1439 *******************************************************************************/
1440
1441 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1442 {
1443         struct timeval tvnow;
1444         struct timespec tsnow;
1445
1446         /* get current time */
1447
1448         if (gettimeofday(&tvnow, NULL) != 0) {
1449                 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1450                                 errno, strerror(errno));
1451                 abort();
1452         }
1453
1454         /* convert it to a timespec */
1455
1456         tsnow.tv_sec = tvnow.tv_sec;
1457         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1458
1459         /* compare current time with the given timespec */
1460
1461         return threads_timespec_earlier(&tsnow, tv);
1462 }
1463
1464
1465 /* threads_wait_with_timeout ***************************************************
1466
1467    Wait for the given maximum amount of time on a monitor until either
1468    we are notified, we are interrupted, or the time is up.
1469
1470    IN:
1471       t............the current thread
1472           wakeupTime...absolute (latest) wakeup time
1473                            If both tv_sec and tv_nsec are zero, this function
1474                                            waits for an unlimited amount of time.
1475
1476    RETURN VALUE:
1477       true.........if the wait has been interrupted,
1478           false........if the wait was ended by notification or timeout
1479
1480 *******************************************************************************/
1481
1482 static bool threads_wait_with_timeout(threadobject *t,
1483                                                                           struct timespec *wakeupTime)
1484 {
1485         bool wasinterrupted;
1486
1487         /* acquire the waitLock */
1488
1489         pthread_mutex_lock(&t->waitLock);
1490
1491         /* mark us as sleeping */
1492
1493         t->isSleeping = true;
1494
1495         /* wait on waitCond */
1496
1497         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1498                 /* with timeout */
1499                 while (!t->interrupted && !t->signaled
1500                            && threads_current_time_is_earlier_than(wakeupTime))
1501                 {
1502                         pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1503                 }
1504         }
1505         else {
1506                 /* no timeout */
1507                 while (!t->interrupted && !t->signaled)
1508                         pthread_cond_wait(&t->waitCond, &t->waitLock);
1509         }
1510
1511         /* check if we were interrupted */
1512
1513         wasinterrupted = t->interrupted;
1514
1515         /* reset all flags */
1516
1517         t->interrupted = false;
1518         t->signaled = false;
1519         t->isSleeping = false;
1520
1521         /* release the waitLock */
1522
1523         pthread_mutex_unlock(&t->waitLock);
1524
1525         return wasinterrupted;
1526 }
1527
1528
1529 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1530 {
1531         if (millis || nanos) {
1532                 struct timeval tv;
1533                 long nsec;
1534                 gettimeofday(&tv, NULL);
1535                 tv.tv_sec += millis / 1000;
1536                 millis %= 1000;
1537                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1538                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1539                 tm->tv_nsec = nsec % 1000000000;
1540         }
1541         else {
1542                 tm->tv_sec = 0;
1543                 tm->tv_nsec = 0;
1544         }
1545 }
1546
1547 /* monitorWait *****************************************************************
1548
1549    Wait on an object for a given (maximum) amount of time.
1550
1551    IN:
1552       t............the current thread
1553           o............the object
1554           millis.......milliseconds of timeout
1555           nanos........nanoseconds of timeout
1556
1557    PRE-CONDITION:
1558       The current thread must be the owner of the object's monitor.
1559    
1560 *******************************************************************************/
1561
1562 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1563 {
1564         bool wasinterrupted;
1565         struct timespec wakeupTime;
1566         monitorLockRecord *newlr;
1567         monitorLockRecord *lr;
1568
1569         lr = o->monitorPtr;
1570         GRAB_LR(lr, t);
1571         CHECK_MONITORSTATE(lr, t, o, return);
1572
1573         /* { the thread t owns the lock record lr on the object o } */
1574
1575         /* calculate the the (latest) wakeup time */
1576
1577         calcAbsoluteTime(&wakeupTime, millis, nanos);
1578
1579         /* wake threads waiting on this record XXX why? */
1580
1581         if (lr->waiter)
1582                 threads_wake_waiters(lr->waiter);
1583
1584         /* mark the lock record as "waiting on object o" */
1585
1586         lr->waiting = o;
1587         STORE_ORDER_BARRIER();
1588
1589         /* unlock this record */
1590
1591         freeLockRecord(lr);
1592
1593         /* wait until notified/interrupted/timed out */
1594
1595         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1596
1597         /* re-enter the monitor */
1598
1599         newlr = monitorEnter(t, o);
1600
1601         /* we are no longer waiting */
1602
1603         threads_remove_waiter(newlr, lr);
1604         newlr->lockCount = lr->lockCount;
1605
1606         /* recylce the old lock record */
1607
1608         lr->lockCount = 1;
1609         lr->waiting = NULL;
1610         lr->waiter = NULL;
1611         recycleLockRecord(t, lr);
1612
1613         /* if we have been interrupted, throw the appropriate exception */
1614
1615         if (wasinterrupted)
1616                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1617 }
1618
1619 /* notifyOneOrAll **************************************************************
1620
1621    Notify one thread or all threads waiting on the given object.
1622
1623    IN:
1624       t............the current thread
1625           o............the object
1626           one..........if true, only notify one thread
1627
1628    PRE-CONDITION:
1629       The current thread must be the owner of the object's monitor.
1630    
1631 *******************************************************************************/
1632
1633 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1634 {
1635         monitorLockRecord *lr;
1636         monitorLockRecord *wlr;
1637         threadobject *wthread;
1638
1639         lr = o->monitorPtr;
1640         GRAB_LR(lr, t);
1641         CHECK_MONITORSTATE(lr, t, o, return);
1642
1643         /* { the thread t owns the lock record lr on the object o } */
1644
1645         /* for each waiter: */
1646
1647         for (wlr = lr->waiter; wlr; wlr = wlr->waiter) {
1648
1649                 /* signal the waiting thread */
1650
1651                 wthread = wlr->ownerThread;
1652                 pthread_mutex_lock(&wthread->waitLock);
1653                 if (wthread->isSleeping)
1654                         pthread_cond_signal(&wthread->waitCond);
1655                 wthread->signaled = true;
1656                 pthread_mutex_unlock(&wthread->waitLock);
1657
1658                 /* if we should only wake one, we are done */
1659
1660                 if (one)
1661                         break;
1662         }
1663 }
1664
1665 /* threadHoldsLock *************************************************************
1666
1667    Return true if the given thread owns the monitor of the given object.
1668
1669    IN:
1670       t............the thread
1671           o............the object
1672    
1673    RETURN VALUE:
1674       true, if the thread is locking the object
1675
1676 *******************************************************************************/
1677
1678 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1679 {
1680         monitorLockRecord *lr;
1681
1682         lr = o->monitorPtr;
1683         GRAB_LR(lr, t);
1684
1685         return (lr->o == o) && (lr->ownerThread == t);
1686 }
1687
1688 /* interruptThread *************************************************************
1689
1690    Interrupt the given thread.
1691
1692    The thread gets the "waitCond" signal and 
1693    its interrupted flag is set to true.
1694
1695    IN:
1696       thread............the thread to interrupt
1697
1698 *******************************************************************************/
1699
1700 void interruptThread(java_lang_VMThread *thread)
1701 {
1702         threadobject *t = (threadobject*) thread;
1703
1704         /* signal the thread a "waitCond" and tell it that it has been */
1705         /* interrupted                                                 */
1706
1707         pthread_mutex_lock(&t->waitLock);
1708         if (t->isSleeping)
1709                 pthread_cond_signal(&t->waitCond);
1710         t->interrupted = true;
1711         pthread_mutex_unlock(&t->waitLock);
1712 }
1713
1714 /* interruptedThread ***********************************************************
1715
1716    Check if the current thread has been interrupted and reset the
1717    interruption flag.
1718
1719    RETURN VALUE:
1720       true, if the current thread had been interrupted
1721
1722 *******************************************************************************/
1723
1724 bool interruptedThread()
1725 {
1726         threadobject *t;
1727         bool intr;
1728
1729         t = (threadobject*) THREADOBJECT;
1730
1731         intr = t->interrupted;
1732
1733         t->interrupted = false;
1734
1735         return intr;
1736 }
1737
1738 /* isInterruptedThread *********************************************************
1739
1740    Check if the given thread has been interrupted
1741
1742    IN:
1743       t............the thread to check
1744
1745    RETURN VALUE:
1746       true, if the given thread had been interrupted
1747
1748 *******************************************************************************/
1749
1750 bool isInterruptedThread(java_lang_VMThread *thread)
1751 {
1752         threadobject *t;
1753
1754         t = (threadobject*) thread;
1755
1756         return t->interrupted;
1757 }
1758
1759 /* thread_sleep ****************************************************************
1760
1761    Sleep the current thread for the specified amount of time.
1762
1763 *******************************************************************************/
1764
1765 void thread_sleep(s8 millis, s4 nanos)
1766 {
1767         threadobject       *t;
1768         struct timespec    wakeupTime;
1769         bool               wasinterrupted;
1770
1771         t = (threadobject *) THREADOBJECT;
1772
1773         calcAbsoluteTime(&wakeupTime, millis, nanos);
1774
1775         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1776
1777         if (wasinterrupted)
1778                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1779 }
1780
1781 void yieldThread()
1782 {
1783         sched_yield();
1784 }
1785
1786 void setPriorityThread(thread *t, s4 priority)
1787 {
1788         nativethread *info = &((threadobject*) t->vmThread)->info;
1789         threads_set_thread_priority(info->tid, priority);
1790 }
1791
1792 void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
1793 {
1794         threadobject *t = (threadobject*) THREADOBJECT;
1795         monitorWait(t, o, millis, nanos);
1796 }
1797
1798 void signal_cond_for_object(java_objectheader *o)
1799 {
1800         threadobject *t = (threadobject*) THREADOBJECT;
1801         notifyOneOrAll(t, o, true);
1802 }
1803
1804 void broadcast_cond_for_object(java_objectheader *o)
1805 {
1806         threadobject *t = (threadobject*) THREADOBJECT;
1807         notifyOneOrAll(t, o, false);
1808 }
1809
1810
1811 /* threads_dump ****************************************************************
1812
1813    Dumps info for all threads running in the JVM. This function is
1814    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1815
1816 *******************************************************************************/
1817
1818 void threads_dump(void)
1819 {
1820         threadobject       *tobj;
1821         java_lang_VMThread *vmt;
1822         nativethread       *nt;
1823         java_lang_Thread   *t;
1824         utf                *name;
1825
1826         tobj = mainthreadobj;
1827
1828         printf("Full thread dump CACAO "VERSION":\n");
1829
1830         /* iterate over all started threads */
1831
1832         do {
1833                 /* get thread objects */
1834
1835                 vmt = &tobj->o;
1836                 nt  = &tobj->info;
1837                 t   = vmt->thread;
1838
1839                 /* the thread may be currently in initalization, don't print it */
1840
1841                 if (t) {
1842                         /* get thread name */
1843
1844                         name = javastring_toutf(t->name, false);
1845
1846                         printf("\n\"");
1847                         utf_display_printable_ascii(name);
1848                         printf("\" ");
1849
1850                         if (t->daemon)
1851                                 printf("daemon ");
1852
1853 #if SIZEOF_VOID_P == 8
1854                         printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1855 #else
1856                         printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1857 #endif
1858
1859                         /* send SIGUSR1 to thread to print stacktrace */
1860
1861                         pthread_kill(nt->tid, SIGUSR1);
1862
1863                         /* sleep this thread a bit, so the signal can reach the thread */
1864
1865                         thread_sleep(10, 0);
1866                 }
1867
1868                 tobj = tobj->info.next;
1869         } while (tobj && (tobj != mainthreadobj));
1870 }
1871
1872
1873 /*
1874  * These are local overrides for various environment variables in Emacs.
1875  * Please do not remove this and leave it at the end of the file, where
1876  * Emacs will automagically detect them.
1877  * ---------------------------------------------------------------------
1878  * Local variables:
1879  * mode: c
1880  * indent-tabs-mode: t
1881  * c-basic-offset: 4
1882  * tab-width: 4
1883  * End:
1884  * vim:noexpandtab:sw=4:ts=4:
1885  */