cb10f505b1f7b34261479e6128ef8786db201c55
[cacao.git] / src / threads / native / threads.c
1 #include "global.h"
2
3 #if defined(NATIVE_THREADS)
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <assert.h>
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <signal.h>
11 #include <sys/time.h>
12 #include <time.h>
13 #include <errno.h>
14
15 #include "config.h"
16 #include "thread.h"
17 #include "codegen.h"
18 #include "locks.h"
19 #include "tables.h"
20 #include "native.h"
21 #include "loader.h"
22 #include "builtin.h"
23 #include "asmpart.h"
24 #include "exceptions.h"
25 #include "toolbox/logging.h"
26 #include "toolbox/memory.h"
27 #include "toolbox/avl.h"
28 #include "mm/boehm.h"
29
30 #include "nat/java_lang_Object.h"
31 #include "nat/java_lang_Throwable.h"
32 #include "nat/java_lang_Thread.h"
33 #include "nat/java_lang_ThreadGroup.h"
34 #include "nat/java_lang_VMThread.h"
35
36 #include <pthread.h>
37 #include <semaphore.h>
38
39 #if !defined(__DARWIN__)
40 #if defined(__LINUX__)
41 #define GC_LINUX_THREADS
42 #elif defined(__MIPS__)
43 #define GC_IRIX_THREADS
44 #endif
45 #include "../mm/boehm-gc/include/gc.h"
46 #endif
47
48 #ifdef MUTEXSIM
49
50 /* We need this for older MacOSX (10.1.x) */
51
52 typedef struct {
53         pthread_mutex_t mutex;
54         pthread_t owner;
55         int count;
56 } pthread_mutex_rec_t;
57
58 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
59 {
60         pthread_mutex_init(&m->mutex, NULL);
61         m->count = 0;
62 }
63
64 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
65 {
66         pthread_mutex_destroy(&m->mutex);
67 }
68
69 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
70 {
71         for (;;)
72                 if (!m->count)
73                 {
74                         pthread_mutex_lock(&m->mutex);
75                         m->owner = pthread_self();
76                         m->count++;
77                         break;
78                 } else {
79                         if (m->owner != pthread_self())
80                                 pthread_mutex_lock(&m->mutex);
81                         else
82                         {
83                                 m->count++;
84                                 break;
85                         }
86                 }
87 }
88
89 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
90 {
91         if (!--m->count)
92                 pthread_mutex_unlock(&m->mutex);
93 }
94
95 #else /* MUTEXSIM */
96
97 #define pthread_mutex_lock_rec pthread_mutex_lock
98 #define pthread_mutex_unlock_rec pthread_mutex_unlock
99 #define pthread_mutex_rec_t pthread_mutex_t
100
101 #endif /* MUTEXSIM */
102
103 static void setPriority(pthread_t tid, int priority)
104 {
105         struct sched_param schedp;
106         int policy;
107
108         pthread_getschedparam(tid, &policy, &schedp);
109         schedp.sched_priority = priority;
110         pthread_setschedparam(tid, policy, &schedp);
111 }
112
113 #include "machine-instr.h"
114
115 static struct avl_table *criticaltree;
116 static threadobject *mainthreadobj;
117
118 #ifndef HAVE___THREAD
119 pthread_key_t tkey_threadinfo;
120 #else
121 __thread threadobject *threadobj;
122 #endif
123
124 static pthread_mutex_rec_t compiler_mutex;
125 static pthread_mutex_rec_t tablelock;
126
127 void compiler_lock()
128 {
129         pthread_mutex_lock_rec(&compiler_mutex);
130 }
131
132 void compiler_unlock()
133 {
134         pthread_mutex_unlock_rec(&compiler_mutex);
135 }
136
137 void tables_lock()
138 {
139     pthread_mutex_lock_rec(&tablelock);
140 }
141
142 void tables_unlock()
143 {
144     pthread_mutex_unlock_rec(&tablelock);
145 }
146
147 static int criticalcompare(const void *pa, const void *pb, void *param)
148 {
149         const threadcritnode *na = pa;
150         const threadcritnode *nb = pb;
151
152         if (na->mcodebegin < nb->mcodebegin)
153                 return -1;
154         if (na->mcodebegin > nb->mcodebegin)
155                 return 1;
156         return 0;
157 }
158
159 static const threadcritnode *findcritical(u1 *mcodeptr)
160 {
161     struct avl_node *n = criticaltree->avl_root;
162     const threadcritnode *m = NULL;
163     if (!n)
164         return NULL;
165     for (;;)
166     {
167         const threadcritnode *d = n->avl_data;
168         if (mcodeptr == d->mcodebegin)
169             return d;
170         if (mcodeptr < d->mcodebegin) {
171             if (n->avl_link[0])
172                 n = n->avl_link[0];
173             else
174                 return m;
175         } else {
176             if (n->avl_link[1]) {
177                 m = n->avl_data;
178                 n = n->avl_link[1];
179             } else
180                 return n->avl_data;
181         }
182     }
183 }
184
185 void thread_registercritical(threadcritnode *n)
186 {
187         avl_insert(criticaltree, n);
188 }
189
190 u1 *thread_checkcritical(u1 *mcodeptr)
191 {
192         const threadcritnode *n = findcritical(mcodeptr);
193         return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
194 }
195
196 static void thread_addstaticcritical()
197 {
198         threadcritnode *n = &asm_criticalsections;
199
200         while (n->mcodebegin)
201                 thread_registercritical(n++);
202 }
203
204 static pthread_mutex_t threadlistlock;
205
206 static pthread_mutex_t stopworldlock;
207 volatile int stopworldwhere;
208
209 static sem_t suspend_ack;
210 #if defined(__MIPS__)
211 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
212 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
213 #endif
214
215 /*
216  * where - 1 from within GC
217            2 class numbering
218  */
219 void lock_stopworld(int where)
220 {
221         pthread_mutex_lock(&stopworldlock);
222         stopworldwhere = where;
223 }
224
225 void unlock_stopworld()
226 {
227         stopworldwhere = 0;
228         pthread_mutex_unlock(&stopworldlock);
229 }
230
231 #if !defined(__DARWIN__)
232 /* Caller must hold threadlistlock */
233 static int cast_sendsignals(int sig, int count)
234 {
235         /* Count threads */
236         threadobject *tobj = mainthreadobj;
237         nativethread *infoself = THREADINFO;
238
239         if (count == 0)
240                 do {
241                         count++;
242                         tobj = tobj->info.next;
243                 } while (tobj != mainthreadobj);
244
245         do {
246                 nativethread *info = &tobj->info;
247                 if (info != infoself)
248                         pthread_kill(info->tid, sig);
249                 tobj = tobj->info.next;
250         } while (tobj != mainthreadobj);
251
252         return count-1;
253 }
254
255 #else
256
257 static void cast_darwinstop()
258 {
259         threadobject *tobj = mainthreadobj;
260         nativethread *infoself = THREADINFO;
261
262         do {
263                 nativethread *info = &tobj->info;
264                 if (info != infoself)
265                 {
266                         thread_state_flavor_t flavor = PPC_THREAD_STATE;
267                         mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
268                         ppc_thread_state_t thread_state;
269                         mach_port_t thread = info->mach_thread;
270                         kern_return_t r;
271
272                         r = thread_suspend(thread);
273                         if (r != KERN_SUCCESS)
274                                 panic("thread_suspend failed");
275
276                         r = thread_get_state(thread, flavor,
277                                 (natural_t*)&thread_state, &thread_state_count);
278                         if (r != KERN_SUCCESS)
279                                 panic("thread_get_state failed");
280
281                         thread_restartcriticalsection(&thread_state);
282
283                         r = thread_set_state(thread, flavor,
284                                 (natural_t*)&thread_state, thread_state_count);
285                         if (r != KERN_SUCCESS)
286                                 panic("thread_set_state failed");
287                 }
288                 tobj = tobj->info.next;
289         } while (tobj != mainthreadobj);
290 }
291
292 static void cast_darwinresume()
293 {
294         threadobject *tobj = mainthreadobj;
295         nativethread *infoself = THREADINFO;
296
297         do {
298                 nativethread *info = &tobj->info;
299                 if (info != infoself)
300                 {
301                         mach_port_t thread = info->mach_thread;
302                         kern_return_t r;
303
304                         r = thread_resume(thread);
305                         if (r != KERN_SUCCESS)
306                                 panic("thread_resume failed");
307                 }
308                 tobj = tobj->info.next;
309         } while (tobj != mainthreadobj);
310 }
311
312 #endif
313
314 #if defined(__MIPS__)
315 static void cast_irixresume()
316 {
317         pthread_mutex_lock(&suspend_ack_lock);
318         pthread_cond_broadcast(&suspend_cond);
319         pthread_mutex_unlock(&suspend_ack_lock);
320 }
321 #endif
322
323 void cast_stopworld()
324 {
325         int count, i;
326         lock_stopworld(2);
327         pthread_mutex_lock(&threadlistlock);
328 #if defined(__DARWIN__)
329         cast_darwinstop();
330 #else
331         count = cast_sendsignals(GC_signum1(), 0);
332         for (i=0; i<count; i++)
333                 sem_wait(&suspend_ack);
334 #endif
335         pthread_mutex_unlock(&threadlistlock);
336 }
337
338 void cast_startworld()
339 {
340         pthread_mutex_lock(&threadlistlock);
341 #if defined(__DARWIN__)
342         cast_darwinresume();
343 #elif defined(__MIPS__)
344         cast_irixresume();
345 #else
346         cast_sendsignals(GC_signum2(), -1);
347 #endif
348         pthread_mutex_unlock(&threadlistlock);
349         unlock_stopworld();
350 }
351
352 #if !defined(__DARWIN__)
353 static void sigsuspend_handler(ucontext_t *ctx)
354 {
355         int sig;
356         sigset_t sigs;
357         
358         thread_restartcriticalsection(ctx);
359
360         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
361            (not POSIX async-safe). */
362 #if defined(__IRIX__)
363         pthread_mutex_lock(&suspend_ack_lock);
364         sem_post(&suspend_ack);
365         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
366         pthread_mutex_unlock(&suspend_ack_lock);
367 #else
368         sem_post(&suspend_ack);
369
370         sig = GC_signum2();
371         sigfillset(&sigs);
372         sigdelset(&sigs, sig);
373         sigsuspend(&sigs);
374 #endif
375 }
376
377 int cacao_suspendhandler(ucontext_t *ctx)
378 {
379         if (stopworldwhere != 2)
380                 return 0;
381
382         sigsuspend_handler(ctx);
383         return 1;
384 }
385 #endif
386
387 static void setthreadobject(threadobject *thread)
388 {
389 #if !defined(HAVE___THREAD)
390         pthread_setspecific(tkey_threadinfo, thread);
391 #else
392         threadobj = thread;
393 #endif
394 }
395
396 static monitorLockRecord *dummyLR;
397
398 static void initPools();
399
400 /*
401  * Initialize threads.
402  */
403 void
404 initThreadsEarly()
405 {
406 #ifndef MUTEXSIM
407         pthread_mutexattr_t mutexattr;
408         pthread_mutexattr_init(&mutexattr);
409         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
410         pthread_mutex_init(&compiler_mutex, &mutexattr);
411         pthread_mutex_init(&tablelock, &mutexattr);
412         pthread_mutexattr_destroy(&mutexattr);
413 #else
414         pthread_mutex_init_rec(&compiler_mutex);
415         pthread_mutex_init_rec(&tablelock);
416 #endif
417
418         pthread_mutex_init(&threadlistlock, NULL);
419         pthread_mutex_init(&stopworldlock, NULL);
420
421         /* Allocate something so the garbage collector's signal handlers are  */
422         /* installed. */
423         heap_allocate(1, false, NULL);
424
425         mainthreadobj = NEW(threadobject);
426         memset(mainthreadobj, 0, sizeof(threadobject));
427         mainthreadobj->info.tid = pthread_self();
428 #if !defined(HAVE___THREAD)
429         pthread_key_create(&tkey_threadinfo, NULL);
430 #endif
431         setthreadobject(mainthreadobj);
432         initPools();
433
434     criticaltree = avl_create(criticalcompare, NULL, NULL);
435         thread_addstaticcritical();
436         sem_init(&suspend_ack, 0, 0);
437
438         /* Every newly created object's monitorPtr points here so we save a check
439          * against NULL */
440         dummyLR = mem_alloc(sizeof(monitorLockRecord));
441         dummyLR->o = NULL;
442         dummyLR->ownerThread = NULL;
443         dummyLR->waiting = false;
444 }
445
446 static pthread_attr_t threadattr;
447
448 static void freeLockRecordPools(lockRecordPool *);
449
450 void
451 initThreads(u1 *stackbottom)
452 {
453         classinfo *threadclass;
454         classinfo *threadgroupclass;
455         java_lang_String *threadname;
456         java_lang_Thread *mainthread;
457         java_lang_ThreadGroup *threadgroup;
458         threadobject *tempthread = mainthreadobj;
459         methodinfo *method;
460
461         threadclass = class_new(utf_new_char("java/lang/VMThread"));
462         class_load(threadclass);
463         class_link(threadclass);
464
465         if (!threadclass)
466                 throw_exception_exit();
467
468         freeLockRecordPools(mainthreadobj->ee.lrpool);
469         /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
470          * the execution environment there. No Thread object must have been created
471          * at an earlier time */
472         threadclass->instancesize = sizeof(threadobject);
473
474         /* Create a VMThread */
475         mainthreadobj = (threadobject *) builtin_new(threadclass);
476
477         if (!mainthreadobj)
478                 throw_exception_exit();
479
480         FREE(tempthread, threadobject);
481         initThread(&mainthreadobj->o);
482
483         setthreadobject(mainthreadobj);
484
485         initLocks();
486         mainthreadobj->info.next = mainthreadobj;
487         mainthreadobj->info.prev = mainthreadobj;
488
489         threadname = javastring_new(utf_new_char("main"));
490
491         /* Allocate and init ThreadGroup */
492         threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
493         threadgroup =
494                 (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
495
496         if (!threadgroup)
497                 throw_exception_exit();
498
499         /* Create a Thread */
500         threadclass = class_new(utf_new_char("java/lang/Thread"));
501         mainthread = (java_lang_Thread*) builtin_new(threadclass);
502         mainthreadobj->o.thread = mainthread;
503
504         if (!mainthread)
505                 throw_exception_exit();
506
507         /* Call Thread constructor */
508         method = class_resolveclassmethod(threadclass,
509                                                                           utf_new_char("<init>"),
510                                                                           utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
511                                                                           threadclass,
512                                                                           true);
513
514         if (!method)
515                 throw_exception_exit();
516
517         asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
518         if (*exceptionptr)
519                 throw_exception_exit();
520
521         mainthread->group = threadgroup;
522         /* XXX This is a hack because the fourth argument was omitted */
523         mainthread->daemon = false;
524
525         /* Add mainthread to ThreadGroup */
526         method = class_resolveclassmethod(threadgroupclass,
527                                                                           utf_new_char("addThread"),
528                                                                           utf_new_char("(Ljava/lang/Thread;)V"),
529                                                                           threadgroupclass,
530                                                                           true);
531
532         if (!method)
533                 throw_exception_exit();
534
535         asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
536         if (*exceptionptr)
537                 throw_exception_exit();
538
539         setPriority(pthread_self(), 5);
540
541         pthread_attr_init(&threadattr);
542         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
543 }
544
545 void initThread(java_lang_VMThread *t)
546 {
547         threadobject *thread = (threadobject*) t;
548         nativethread *info = &thread->info;
549         info->tid = pthread_self();
550         /* TODO destroy all those things */
551         pthread_mutex_init(&info->joinMutex, NULL);
552         pthread_cond_init(&info->joinCond, NULL);
553
554         pthread_mutex_init(&thread->waitLock, NULL);
555         pthread_cond_init(&thread->waitCond, NULL);
556         thread->interrupted = false;
557         thread->signaled = false;
558         thread->isSleeping = false;
559 }
560
561 static void initThreadLocks(threadobject *);
562
563 typedef struct {
564         threadobject *thread;
565         sem_t *psem;
566 } startupinfo;
567
568 static void *threadstartup(void *t)
569 {
570         startupinfo *startup = t;
571         threadobject *thread = startup->thread;
572         sem_t *psem = startup->psem;
573         nativethread *info = &thread->info;
574         threadobject *tnext;
575         methodinfo *method;
576
577         t = NULL;
578 #if defined(__DARWIN__)
579         info->mach_thread = mach_thread_self();
580 #endif
581         setthreadobject(thread);
582
583         pthread_mutex_lock(&threadlistlock);
584         info->prev = mainthreadobj;
585         info->next = tnext = mainthreadobj->info.next;
586         mainthreadobj->info.next = thread;
587         tnext->info.prev = thread;
588         pthread_mutex_unlock(&threadlistlock);
589
590         initThreadLocks(thread);
591
592         startup = NULL;
593         sem_post(psem);
594
595         setPriority(info->tid, thread->o.thread->priority);
596         sched_yield();
597
598         /* Find the run()V method and call it */
599         method = class_resolveclassmethod(thread->o.header.vftbl->class,
600                                                                           utf_new_char("run"),
601                                                                           utf_new_char("()V"),
602                                                                           thread->o.header.vftbl->class,
603                                                                           true);
604
605         /* if method != NULL, we had not exception */
606         if (method) {
607                 asm_calljavafunction(method, thread, NULL, NULL, NULL);
608
609         } else {
610                 throw_exception();
611         }
612
613         /* Allow lock record pools to be used by other threads. They cannot be
614          * deleted so we'd better not waste them. */
615         freeLockRecordPools(thread->ee.lrpool);
616
617         pthread_mutex_lock(&threadlistlock);
618         info->next->info.prev = info->prev;
619         info->prev->info.next = info->next;
620         pthread_mutex_unlock(&threadlistlock);
621
622         pthread_mutex_lock(&info->joinMutex);
623         info->tid = 0;
624         pthread_mutex_unlock(&info->joinMutex);
625         pthread_cond_broadcast(&info->joinCond);
626
627         return NULL;
628 }
629
630 void startThread(thread *t)
631 {
632         nativethread *info = &((threadobject*) t->vmThread)->info;
633         sem_t sem;
634         startupinfo startup;
635
636         startup.thread = (threadobject*) t->vmThread;
637         startup.psem = &sem;
638
639         sem_init(&sem, 0, 0);
640         
641         if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
642                 panic("pthread_create failed");
643
644         /* Wait here until the thread has entered itself into the thread list */
645         sem_wait(&sem);
646         sem_destroy(&sem);
647 }
648
649 /* At the end of the program, we wait for all running non-daemon threads to die
650  */
651
652 static threadobject *findNonDaemon(threadobject *thread)
653 {
654         while (thread != mainthreadobj) {
655                 if (!thread->o.thread->daemon)
656                         return thread;
657                 thread = thread->info.prev;
658         }
659
660         return NULL;
661 }
662
663 void joinAllThreads()
664 {
665         threadobject *thread;
666         pthread_mutex_lock(&threadlistlock);
667         while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
668                 nativethread *info = &thread->info;
669                 pthread_mutex_lock(&info->joinMutex);
670                 pthread_mutex_unlock(&threadlistlock);
671                 while (info->tid)
672                         pthread_cond_wait(&info->joinCond, &info->joinMutex);
673                 pthread_mutex_unlock(&info->joinMutex);
674                 pthread_mutex_lock(&threadlistlock);
675         }
676         pthread_mutex_unlock(&threadlistlock);
677 }
678
679 static void initLockRecord(monitorLockRecord *r, threadobject *t)
680 {
681         r->lockCount = 1;
682         r->ownerThread = t;
683         r->queuers = 0;
684         r->o = NULL;
685         r->waiter = NULL;
686         r->incharge = (monitorLockRecord *) &dummyLR;
687         r->waiting = false;
688         sem_init(&r->queueSem, 0, 0);
689         pthread_mutex_init(&r->resolveLock, NULL);
690         pthread_cond_init(&r->resolveWait, NULL);
691 }
692
693 /* No lock record must ever be destroyed because there may still be references
694  * to it.
695
696 static void destroyLockRecord(monitorLockRecord *r)
697 {
698         sem_destroy(&r->queueSem);
699         pthread_mutex_destroy(&r->resolveLock);
700         pthread_cond_destroy(&r->resolveWait);
701 }
702 */
703
704 void initLocks()
705 {
706         initThreadLocks(mainthreadobj);
707 }
708
709 static void initThreadLocks(threadobject *thread)
710 {
711         thread->ee.firstLR = NULL;
712         thread->ee.lrpool = NULL;
713         thread->ee.numlr = 0;
714 }
715
716 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
717 {
718         lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
719         int i;
720
721         p->header.size = size;
722         for (i=0; i<size; i++) {
723                 initLockRecord(&p->lr[i], thread);
724                 p->lr[i].nextFree = &p->lr[i+1];
725         }
726         p->lr[i-1].nextFree = NULL;
727         return p;
728 }
729
730 #define INITIALLOCKRECORDS 8
731
732 static pthread_mutex_t pool_lock;
733 static lockRecordPool *global_pool;
734
735 static void initPools()
736 {
737         pthread_mutex_init(&pool_lock, NULL);
738 }
739
740 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
741 {
742         pthread_mutex_lock(&pool_lock);
743         if (global_pool) {
744                 int i;
745                 lockRecordPool *pool = global_pool;
746                 global_pool = pool->header.next;
747                 pthread_mutex_unlock(&pool_lock);
748
749                 for (i=0; i < pool->header.size; i++)
750                         pool->lr[i].ownerThread = t;
751                 
752                 return pool;
753         }
754         pthread_mutex_unlock(&pool_lock);
755
756         return allocNewLockRecordPool(t, size);
757 }
758
759 static void freeLockRecordPools(lockRecordPool *pool)
760 {
761         lockRecordPoolHeader *last;
762         pthread_mutex_lock(&pool_lock);
763         last = &pool->header;
764         while (last->next)
765                 last = &last->next->header;
766         last->next = global_pool;
767         global_pool = pool;
768         pthread_mutex_unlock(&pool_lock);
769 }
770
771 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
772 {
773         monitorLockRecord *r = t->ee.firstLR;
774
775         if (!r) {
776                 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
777                 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
778                 pool->header.next = t->ee.lrpool;
779                 t->ee.lrpool = pool;
780                 r = &pool->lr[0];
781                 t->ee.numlr += pool->header.size;
782         }
783         
784         t->ee.firstLR = r->nextFree;
785         return r;
786 }
787
788 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
789 {
790         r->nextFree = t->ee.firstLR;
791         t->ee.firstLR = r;
792 }
793
794 void initObjectLock(java_objectheader *o)
795 {
796         o->monitorPtr = dummyLR;
797 }
798
799 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
800 {
801         atomic_add(&lr->queuers, 1);
802         MEMORY_BARRIER_AFTER_ATOMIC();
803         while (lr->o == o)
804                 sem_wait(&lr->queueSem);
805         atomic_add(&lr->queuers, -1);
806 }
807
808 static void freeLockRecord(monitorLockRecord *lr)
809 {
810         int q;
811         lr->o = NULL;
812         MEMORY_BARRIER();
813         q = lr->queuers;
814         while (q--)
815                 sem_post(&lr->queueSem);
816 }
817
818 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
819 {
820         if (lr->waiting)
821                 mlr->waiter = lr;
822 }
823
824 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
825 {
826         for (;;) {
827                 monitorLockRecord *lr = o->monitorPtr;
828                 if (lr->o != o) {
829                         monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
830                         mlr->o = o;
831                         if (mlr == lr) {
832                                 MEMORY_BARRIER();
833                                 nlr = o->monitorPtr;
834                                 if (nlr == lr) {
835                                         handleWaiter(mlr, lr);
836                                         return mlr;
837                                 }
838                         } else {
839                                 if (lr->ownerThread != t)
840                                         mlr->incharge = lr;
841                                 MEMORY_BARRIER_BEFORE_ATOMIC();
842                                 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
843                         }
844                         if (nlr == lr) {
845                                 if (mlr == lr || lr->o != o) {
846                                         handleWaiter(mlr, lr);
847                                         return mlr;
848                                 }
849                                 while (lr->o == o)
850                                         queueOnLockRecord(lr, o);
851                                 handleWaiter(mlr, lr);
852                                 return mlr;
853                         }
854                         freeLockRecord(mlr);
855                         recycleLockRecord(t, mlr);
856                         queueOnLockRecord(nlr, o);
857                 } else {
858                         if (lr->ownerThread == t) {
859                                 lr->lockCount++;
860                                 return lr;
861                         }
862                         queueOnLockRecord(lr, o);
863                 }
864         }
865 }
866
867 static void wakeWaiters(monitorLockRecord *lr)
868 {
869         do {
870                 int q = lr->queuers;
871                 while (q--)
872                         sem_post(&lr->queueSem);
873                 lr = lr->waiter;
874         } while (lr);
875 }
876
877 #define GRAB_LR(lr,t) \
878     if (lr->ownerThread != t) { \
879                 lr = lr->incharge; \
880         }
881
882 #define CHECK_MONITORSTATE(lr,t,mo,a) \
883     if (lr->o != mo || lr->ownerThread != t) { \
884                 *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
885                 a; \
886         }
887
888 bool monitorExit(threadobject *t, java_objectheader *o)
889 {
890         monitorLockRecord *lr = o->monitorPtr;
891         GRAB_LR(lr, t);
892         CHECK_MONITORSTATE(lr, t, o, return false);
893         if (lr->lockCount > 1) {
894                 lr->lockCount--;
895                 return true;
896         }
897         if (lr->waiter) {
898                 monitorLockRecord *wlr = lr->waiter;
899                 if (o->monitorPtr != lr ||
900                         (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
901                 {
902                         monitorLockRecord *nlr = o->monitorPtr;
903                         nlr->waiter = wlr;
904                         STORE_ORDER_BARRIER();
905                 } else
906                         wakeWaiters(wlr);
907                 lr->waiter = NULL;
908         }
909         freeLockRecord(lr);
910         recycleLockRecord(t, lr);
911         return true;
912 }
913
914 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
915 {
916         do {
917                 if (lr->waiter == wlr) {
918                         lr->waiter = wlr->waiter;
919                         break;
920                 }
921                 lr = lr->waiter;
922         } while (lr);
923 }
924
925 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
926 {
927         return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
928 }
929
930 static bool timeIsEarlier(const struct timespec *tv)
931 {
932         struct timeval tvnow;
933         struct timespec tsnow;
934         gettimeofday(&tvnow, NULL);
935         tsnow.tv_sec = tvnow.tv_sec;
936         tsnow.tv_nsec = tvnow.tv_usec * 1000;
937         return timespec_less(&tsnow, tv);
938 }
939
940 bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
941 {
942         bool wasinterrupted;
943
944         pthread_mutex_lock(&t->waitLock);
945         t->isSleeping = true;
946         if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
947                 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
948                         pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
949         else
950                 while (!t->interrupted && !t->signaled)
951                         pthread_cond_wait(&t->waitCond, &t->waitLock);
952         wasinterrupted = t->interrupted;
953         t->interrupted = false;
954         t->signaled = false;
955         t->isSleeping = false;
956         pthread_mutex_unlock(&t->waitLock);
957         return wasinterrupted;
958 }
959
960 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
961 {
962         if (millis || nanos) {
963                 struct timeval tv;
964                 long nsec;
965                 gettimeofday(&tv, NULL);
966                 tv.tv_sec += millis / 1000;
967                 millis %= 1000;
968                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
969                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
970                 tm->tv_nsec = nsec % 1000000000;
971         } else {
972                 tm->tv_sec = 0;
973                 tm->tv_nsec = 0;
974         }
975 }
976
977 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
978 {
979         bool wasinterrupted;
980         struct timespec wakeupTime;
981         monitorLockRecord *mlr, *lr = o->monitorPtr;
982         GRAB_LR(lr, t);
983         CHECK_MONITORSTATE(lr, t, o, return);
984
985         calcAbsoluteTime(&wakeupTime, millis, nanos);
986         
987         if (lr->waiter)
988                 wakeWaiters(lr->waiter);
989         lr->waiting = true;
990         STORE_ORDER_BARRIER();
991         freeLockRecord(lr);
992         wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
993         mlr = monitorEnter(t, o);
994         removeFromWaiters(mlr, lr);
995         mlr->lockCount = lr->lockCount;
996         lr->lockCount = 1;
997         lr->waiting = false;
998         lr->waiter = NULL;
999         recycleLockRecord(t, lr);
1000
1001         if (wasinterrupted)
1002                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1003 }
1004
1005 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1006 {
1007         monitorLockRecord *lr = o->monitorPtr;
1008         GRAB_LR(lr, t);
1009         CHECK_MONITORSTATE(lr, t, o, return);
1010         do {
1011                 threadobject *wthread;
1012                 monitorLockRecord *wlr = lr->waiter;
1013                 if (!wlr)
1014                         break;
1015                 wthread = wlr->ownerThread;
1016                 pthread_mutex_lock(&wthread->waitLock);
1017                 if (wthread->isSleeping)
1018                         pthread_cond_signal(&wthread->waitCond);
1019                 wthread->signaled = true;
1020                 pthread_mutex_unlock(&wthread->waitLock);
1021                 lr = wlr;
1022         } while (!one);
1023 }
1024
1025 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1026 {
1027         monitorLockRecord *lr = o->monitorPtr;
1028         GRAB_LR(lr, t);
1029         return lr->o == o && lr->ownerThread == t;
1030 }
1031
1032 void interruptThread(java_lang_VMThread *thread)
1033 {
1034         threadobject *t = (threadobject*) thread;
1035
1036         t->interrupted = true;
1037         pthread_mutex_lock(&t->waitLock);
1038         if (t->isSleeping)
1039                 pthread_cond_signal(&t->waitCond);
1040         pthread_mutex_unlock(&t->waitLock);
1041 }
1042
1043 bool interruptedThread()
1044 {
1045         threadobject *t = (threadobject*) THREADOBJECT;
1046         bool intr = t->interrupted;
1047         t->interrupted = false;
1048         return intr;
1049 }
1050
1051 bool isInterruptedThread(java_lang_VMThread *thread)
1052 {
1053         threadobject *t = (threadobject*) thread;
1054         return t->interrupted;
1055 }
1056
1057 void sleepThread(s8 millis, s4 nanos)
1058 {
1059         bool wasinterrupted;
1060         threadobject *t = (threadobject*) THREADOBJECT;
1061         monitorLockRecord *lr;
1062         struct timespec wakeupTime;
1063         calcAbsoluteTime(&wakeupTime, millis, nanos);
1064
1065         lr = allocLockRecordSimple(t);
1066         wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1067         recycleLockRecord(t, lr);
1068
1069         if (wasinterrupted)
1070                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1071 }
1072
1073 void yieldThread()
1074 {
1075         sched_yield();
1076 }
1077
1078 void setPriorityThread(thread *t, s4 priority)
1079 {
1080         nativethread *info = &((threadobject*) t->vmThread)->info;
1081         setPriority(info->tid, priority);
1082 }
1083
1084 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1085 {
1086         threadobject *t = (threadobject*) THREADOBJECT;
1087         monitorWait(t, o, time, nanos);
1088 }
1089
1090 void signal_cond_for_object(java_objectheader *o)
1091 {
1092         threadobject *t = (threadobject*) THREADOBJECT;
1093         notifyOneOrAll(t, o, true);
1094 }
1095
1096 void broadcast_cond_for_object(java_objectheader *o)
1097 {
1098         threadobject *t = (threadobject*) THREADOBJECT;
1099         notifyOneOrAll(t, o, false);
1100 }
1101
1102 #endif
1103
1104
1105 /*
1106  * These are local overrides for various environment variables in Emacs.
1107  * Please do not remove this and leave it at the end of the file, where
1108  * Emacs will automagically detect them.
1109  * ---------------------------------------------------------------------
1110  * Local variables:
1111  * mode: c
1112  * indent-tabs-mode: t
1113  * c-basic-offset: 4
1114  * tab-width: 4
1115  * End:
1116  */