* src/vm/utf8.h, src/vm/utf8.c: The Big utf_* Renaming.
[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 4879 2006-05-05 17:34:49Z 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                         nlr->waiter = wlr; /* XXX is it ok to overwrite the nlr->waiter field like that? */
1371                         STORE_ORDER_BARRIER();
1372                 }
1373                 else {
1374                         threads_wake_waiters(wlr);
1375                 }
1376                 lr->waiter = NULL;
1377         }
1378
1379         /* unlock and throw away this lock record */
1380         freeLockRecord(lr);
1381         recycleLockRecord(t, lr);
1382         return true;
1383 }
1384
1385 /* threads_remove_waiter *******************************************************
1386
1387    Remove a waiter lock record from the waiter list of the given lock record
1388
1389    IN:
1390       lr...........the lock record holding the waiter list
1391           toremove.....the record to remove from the list
1392
1393 *******************************************************************************/
1394
1395 static void threads_remove_waiter(monitorLockRecord *lr,
1396                                                                   monitorLockRecord *toremove)
1397 {
1398         do {
1399                 if (lr->waiter == toremove) {
1400                         lr->waiter = toremove->waiter;
1401                         break;
1402                 }
1403                 lr = lr->waiter;
1404         } while (lr); /* XXX need to break cycle? */
1405 }
1406
1407 /* threads_timespec_earlier ****************************************************
1408
1409    Return true if timespec tv1 is earlier than timespec tv2.
1410
1411    IN:
1412       tv1..........first timespec
1413           tv2..........second timespec
1414
1415    RETURN VALUE:
1416       true, if the first timespec is earlier
1417
1418 *******************************************************************************/
1419
1420 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1421                                                                                         const struct timespec *tv2)
1422 {
1423         return (tv1->tv_sec < tv2->tv_sec)
1424                                 ||
1425                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1426 }
1427
1428 /* threads_current_time_is_earlier_than ****************************************
1429
1430    Check if the current time is earlier than the given timespec.
1431
1432    IN:
1433       tv...........the timespec to compare against
1434
1435    RETURN VALUE:
1436       true, if the current time is earlier
1437
1438 *******************************************************************************/
1439
1440 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1441 {
1442         struct timeval tvnow;
1443         struct timespec tsnow;
1444
1445         /* get current time */
1446
1447         if (gettimeofday(&tvnow, NULL) != 0) {
1448                 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1449                                 errno, strerror(errno));
1450                 abort();
1451         }
1452
1453         /* convert it to a timespec */
1454
1455         tsnow.tv_sec = tvnow.tv_sec;
1456         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1457
1458         /* compare current time with the given timespec */
1459
1460         return threads_timespec_earlier(&tsnow, tv);
1461 }
1462
1463
1464 /* threads_wait_with_timeout ***************************************************
1465
1466    Wait for the given maximum amount of time on a monitor until either
1467    we are notified, we are interrupted, or the time is up.
1468
1469    IN:
1470       t............the current thread
1471           wakeupTime...absolute (latest) wakeup time
1472                            If both tv_sec and tv_nsec are zero, this function
1473                                            waits for an unlimited amount of time.
1474
1475    RETURN VALUE:
1476       true.........if the wait has been interrupted,
1477           false........if the wait was ended by notification or timeout
1478
1479 *******************************************************************************/
1480
1481 static bool threads_wait_with_timeout(threadobject *t,
1482                                                                           struct timespec *wakeupTime)
1483 {
1484         bool wasinterrupted;
1485
1486         /* acquire the waitLock */
1487
1488         pthread_mutex_lock(&t->waitLock);
1489
1490         /* mark us as sleeping */
1491
1492         t->isSleeping = true;
1493
1494         /* wait on waitCond */
1495
1496         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1497                 /* with timeout */
1498                 while (!t->interrupted && !t->signaled
1499                            && threads_current_time_is_earlier_than(wakeupTime))
1500                 {
1501                         pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1502                 }
1503         }
1504         else {
1505                 /* no timeout */
1506                 while (!t->interrupted && !t->signaled)
1507                         pthread_cond_wait(&t->waitCond, &t->waitLock);
1508         }
1509
1510         /* check if we were interrupted */
1511
1512         wasinterrupted = t->interrupted;
1513
1514         /* reset all flags */
1515
1516         t->interrupted = false;
1517         t->signaled = false;
1518         t->isSleeping = false;
1519
1520         /* release the waitLock */
1521
1522         pthread_mutex_unlock(&t->waitLock);
1523
1524         return wasinterrupted;
1525 }
1526
1527
1528 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1529 {
1530         if (millis || nanos) {
1531                 struct timeval tv;
1532                 long nsec;
1533                 gettimeofday(&tv, NULL);
1534                 tv.tv_sec += millis / 1000;
1535                 millis %= 1000;
1536                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1537                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1538                 tm->tv_nsec = nsec % 1000000000;
1539         }
1540         else {
1541                 tm->tv_sec = 0;
1542                 tm->tv_nsec = 0;
1543         }
1544 }
1545
1546 /* monitorWait *****************************************************************
1547
1548    Wait on an object for a given (maximum) amount of time.
1549
1550    IN:
1551       t............the current thread
1552           o............the object
1553           millis.......milliseconds of timeout
1554           nanos........nanoseconds of timeout
1555
1556    PRE-CONDITION:
1557       The current thread must be the owner of the object's monitor.
1558    
1559 *******************************************************************************/
1560
1561 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1562 {
1563         bool wasinterrupted;
1564         struct timespec wakeupTime;
1565         monitorLockRecord *newlr;
1566         monitorLockRecord *lr;
1567
1568         lr = o->monitorPtr;
1569         GRAB_LR(lr, t);
1570         CHECK_MONITORSTATE(lr, t, o, return);
1571
1572         /* { the thread t owns the lock record lr on the object o } */
1573
1574         /* calculate the the (latest) wakeup time */
1575
1576         calcAbsoluteTime(&wakeupTime, millis, nanos);
1577
1578         /* wake threads waiting on this record XXX why? */
1579
1580         if (lr->waiter)
1581                 threads_wake_waiters(lr->waiter);
1582
1583         /* mark the lock record as "waiting on object o" */
1584
1585         lr->waiting = o;
1586         STORE_ORDER_BARRIER();
1587
1588         /* unlock this record */
1589
1590         freeLockRecord(lr);
1591
1592         /* wait until notified/interrupted/timed out */
1593
1594         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1595
1596         /* re-enter the monitor */
1597
1598         newlr = monitorEnter(t, o);
1599
1600         /* we are no longer waiting */
1601
1602         threads_remove_waiter(newlr, lr);
1603         newlr->lockCount = lr->lockCount;
1604
1605         /* recylce the old lock record */
1606
1607         lr->lockCount = 1;
1608         lr->waiting = NULL;
1609         lr->waiter = NULL;
1610         recycleLockRecord(t, lr);
1611
1612         /* if we have been interrupted, throw the appropriate exception */
1613
1614         if (wasinterrupted)
1615                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1616 }
1617
1618 /* notifyOneOrAll **************************************************************
1619
1620    Notify one thread or all threads waiting on the given object.
1621
1622    IN:
1623       t............the current thread
1624           o............the object
1625           one..........if true, only notify one thread
1626
1627    PRE-CONDITION:
1628       The current thread must be the owner of the object's monitor.
1629    
1630 *******************************************************************************/
1631
1632 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1633 {
1634         monitorLockRecord *lr;
1635         monitorLockRecord *wlr;
1636         threadobject *wthread;
1637
1638         lr = o->monitorPtr;
1639         GRAB_LR(lr, t);
1640         CHECK_MONITORSTATE(lr, t, o, return);
1641
1642         /* { the thread t owns the lock record lr on the object o } */
1643
1644         /* for each waiter: */
1645
1646         for (wlr = lr->waiter; wlr; wlr = wlr->waiter) {
1647
1648                 /* signal the waiting thread */
1649
1650                 wthread = wlr->ownerThread;
1651                 pthread_mutex_lock(&wthread->waitLock);
1652                 if (wthread->isSleeping)
1653                         pthread_cond_signal(&wthread->waitCond);
1654                 wthread->signaled = true;
1655                 pthread_mutex_unlock(&wthread->waitLock);
1656
1657                 /* if we should only wake one, we are done */
1658
1659                 if (one)
1660                         break;
1661         }
1662 }
1663
1664 /* threadHoldsLock *************************************************************
1665
1666    Return true if the given thread owns the monitor of the given object.
1667
1668    IN:
1669       t............the thread
1670           o............the object
1671    
1672    RETURN VALUE:
1673       true, if the thread is locking the object
1674
1675 *******************************************************************************/
1676
1677 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1678 {
1679         monitorLockRecord *lr;
1680
1681         lr = o->monitorPtr;
1682         GRAB_LR(lr, t);
1683
1684         return (lr->o == o) && (lr->ownerThread == t);
1685 }
1686
1687 /* interruptThread *************************************************************
1688
1689    Interrupt the given thread.
1690
1691    The thread gets the "waitCond" signal and 
1692    its interrupted flag is set to true.
1693
1694    IN:
1695       thread............the thread to interrupt
1696
1697 *******************************************************************************/
1698
1699 void interruptThread(java_lang_VMThread *thread)
1700 {
1701         threadobject *t = (threadobject*) thread;
1702
1703         /* signal the thread a "waitCond" and tell it that it has been */
1704         /* interrupted                                                 */
1705
1706         pthread_mutex_lock(&t->waitLock);
1707         if (t->isSleeping)
1708                 pthread_cond_signal(&t->waitCond);
1709         t->interrupted = true;
1710         pthread_mutex_unlock(&t->waitLock);
1711 }
1712
1713 /* interruptedThread ***********************************************************
1714
1715    Check if the current thread has been interrupted and reset the
1716    interruption flag.
1717
1718    RETURN VALUE:
1719       true, if the current thread had been interrupted
1720
1721 *******************************************************************************/
1722
1723 bool interruptedThread()
1724 {
1725         threadobject *t;
1726         bool intr;
1727
1728         t = (threadobject*) THREADOBJECT;
1729
1730         intr = t->interrupted;
1731
1732         t->interrupted = false;
1733
1734         return intr;
1735 }
1736
1737 /* isInterruptedThread *********************************************************
1738
1739    Check if the given thread has been interrupted
1740
1741    IN:
1742       t............the thread to check
1743
1744    RETURN VALUE:
1745       true, if the given thread had been interrupted
1746
1747 *******************************************************************************/
1748
1749 bool isInterruptedThread(java_lang_VMThread *thread)
1750 {
1751         threadobject *t;
1752
1753         t = (threadobject*) thread;
1754
1755         return t->interrupted;
1756 }
1757
1758 /* thread_sleep ****************************************************************
1759
1760    Sleep the current thread for the specified amount of time.
1761
1762 *******************************************************************************/
1763
1764 void thread_sleep(s8 millis, s4 nanos)
1765 {
1766         threadobject       *t;
1767         struct timespec    wakeupTime;
1768         bool               wasinterrupted;
1769
1770         t = (threadobject *) THREADOBJECT;
1771
1772         calcAbsoluteTime(&wakeupTime, millis, nanos);
1773
1774         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1775
1776         if (wasinterrupted)
1777                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1778 }
1779
1780 void yieldThread()
1781 {
1782         sched_yield();
1783 }
1784
1785 void setPriorityThread(thread *t, s4 priority)
1786 {
1787         nativethread *info = &((threadobject*) t->vmThread)->info;
1788         threads_set_thread_priority(info->tid, priority);
1789 }
1790
1791 void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
1792 {
1793         threadobject *t = (threadobject*) THREADOBJECT;
1794         monitorWait(t, o, millis, nanos);
1795 }
1796
1797 void signal_cond_for_object(java_objectheader *o)
1798 {
1799         threadobject *t = (threadobject*) THREADOBJECT;
1800         notifyOneOrAll(t, o, true);
1801 }
1802
1803 void broadcast_cond_for_object(java_objectheader *o)
1804 {
1805         threadobject *t = (threadobject*) THREADOBJECT;
1806         notifyOneOrAll(t, o, false);
1807 }
1808
1809
1810 /* threads_dump ****************************************************************
1811
1812    Dumps info for all threads running in the JVM. This function is
1813    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1814
1815 *******************************************************************************/
1816
1817 void threads_dump(void)
1818 {
1819         threadobject       *tobj;
1820         java_lang_VMThread *vmt;
1821         nativethread       *nt;
1822         java_lang_Thread   *t;
1823         utf                *name;
1824
1825         tobj = mainthreadobj;
1826
1827         printf("Full thread dump CACAO "VERSION":\n");
1828
1829         /* iterate over all started threads */
1830
1831         do {
1832                 /* get thread objects */
1833
1834                 vmt = &tobj->o;
1835                 nt  = &tobj->info;
1836                 t   = vmt->thread;
1837
1838                 /* the thread may be currently in initalization, don't print it */
1839
1840                 if (t) {
1841                         /* get thread name */
1842
1843                         name = javastring_toutf(t->name, false);
1844
1845                         printf("\n\"");
1846                         utf_display_printable_ascii(name);
1847                         printf("\" ");
1848
1849                         if (t->daemon)
1850                                 printf("daemon ");
1851
1852 #if SIZEOF_VOID_P == 8
1853                         printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1854 #else
1855                         printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1856 #endif
1857
1858                         /* send SIGUSR1 to thread to print stacktrace */
1859
1860                         pthread_kill(nt->tid, SIGUSR1);
1861
1862                         /* sleep this thread a bit, so the signal can reach the thread */
1863
1864                         thread_sleep(10, 0);
1865                 }
1866
1867                 tobj = tobj->info.next;
1868         } while (tobj && (tobj != mainthreadobj));
1869 }
1870
1871
1872 /*
1873  * These are local overrides for various environment variables in Emacs.
1874  * Please do not remove this and leave it at the end of the file, where
1875  * Emacs will automagically detect them.
1876  * ---------------------------------------------------------------------
1877  * Local variables:
1878  * mode: c
1879  * indent-tabs-mode: t
1880  * c-basic-offset: 4
1881  * tab-width: 4
1882  * End:
1883  * vim:noexpandtab:sw=4:ts=4:
1884  */