GNU header update.
[cacao.git] / src / threads / native / threads.c
index e8d3b5cdb0c2474bf5dc65c1887bc4b4fb14b0ca..d7b64be0fd4f4db9edf0e04b6c135b8218f2c81e 100644 (file)
@@ -1,6 +1,35 @@
-#include "global.h"
+/* threads/native/threads.c - native threads support
+
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Stefan Ring
+
+   $Id: threads.c 1735 2004-12-07 14:33:27Z twisti $
+
+*/
 
-#if defined(NATIVE_THREADS)
 
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <errno.h>
 
-#include "config.h"
-#include "thread.h"
 #include "codegen.h"
-#include "locks.h"
-#include "tables.h"
-#include "native.h"
-#include "loader.h"
-#include "builtin.h"
-#include "asmpart.h"
-#include "exceptions.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "toolbox/avl.h"
+#include "config.h"
 #include "mm/boehm.h"
-
-#include "nat/java_lang_Object.h"
-#include "nat/java_lang_Throwable.h"
-#include "nat/java_lang_Thread.h"
-#include "nat/java_lang_ThreadGroup.h"
+#include "mm/memory.h"
+#include "native/native.h"
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_Throwable.h"
+#include "native/include/java_lang_Thread.h"
+#include "native/include/java_lang_ThreadGroup.h"
+#include "native/include/java_lang_VMThread.h"
+#include "threads/native/threads.h"
+#include "toolbox/avl.h"
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
 
 #include <pthread.h>
 #include <semaphore.h>
 #elif defined(__MIPS__)
 #define GC_IRIX_THREADS
 #endif
-#include "../mm/boehm-gc/include/gc.h"
+#include "boehm-gc/include/gc.h"
 #endif
 
 #ifdef MUTEXSIM
 
+/* We need this for older MacOSX (10.1.x) */
+
 typedef struct {
        pthread_mutex_t mutex;
        pthread_t owner;
@@ -97,6 +128,16 @@ static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
 
 #endif /* MUTEXSIM */
 
+static void setPriority(pthread_t tid, int priority)
+{
+       struct sched_param schedp;
+       int policy;
+
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
+}
+
 #include "machine-instr.h"
 
 static struct avl_table *criticaltree;
@@ -285,6 +326,9 @@ static void cast_darwinresume()
                nativethread *info = &tobj->info;
                if (info != infoself)
                {
+                       mach_port_t thread = info->mach_thread;
+                       kern_return_t r;
+
                        r = thread_resume(thread);
                        if (r != KERN_SUCCESS)
                                panic("thread_resume failed");
@@ -343,7 +387,7 @@ static void sigsuspend_handler(ucontext_t *ctx)
 
        /* Do as Boehm does. On IRIX a condition variable is used for wake-up
           (not POSIX async-safe). */
-#if defined(__MIPS__)
+#if defined(__IRIX__)
        pthread_mutex_lock(&suspend_ack_lock);
        sem_post(&suspend_ack);
        pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
@@ -377,6 +421,10 @@ static void setthreadobject(threadobject *thread)
 #endif
 }
 
+static monitorLockRecord *dummyLR;
+
+static void initPools();
+
 /*
  * Initialize threads.
  */
@@ -403,18 +451,27 @@ initThreadsEarly()
        heap_allocate(1, false, NULL);
 
        mainthreadobj = NEW(threadobject);
-       memset(mainthreadobj, 0, sizeof(threadobject));
+       mainthreadobj->info.tid = pthread_self();
 #if !defined(HAVE___THREAD)
        pthread_key_create(&tkey_threadinfo, NULL);
 #endif
        setthreadobject(mainthreadobj);
+       initPools();
 
     criticaltree = avl_create(criticalcompare, NULL, NULL);
        thread_addstaticcritical();
        sem_init(&suspend_ack, 0, 0);
+
+       /* Every newly created object's monitorPtr points here so we save a check
+        * against NULL */
+       dummyLR = NEW(monitorLockRecord);
+       dummyLR->o = NULL;
+       dummyLR->ownerThread = NULL;
+       dummyLR->waiting = false;
 }
 
 static pthread_attr_t threadattr;
+
 static void freeLockRecordPools(lockRecordPool *);
 
 void
@@ -422,10 +479,13 @@ initThreads(u1 *stackbottom)
 {
        classinfo *threadclass;
        classinfo *threadgroupclass;
+       java_lang_String *threadname;
        java_lang_Thread *mainthread;
+       java_lang_ThreadGroup *threadgroup;
        threadobject *tempthread = mainthreadobj;
+       methodinfo *method;
 
-       threadclass = class_new(utf_new_char("java/lang/Thread"));
+       threadclass = class_new(utf_new_char("java/lang/VMThread"));
        class_load(threadclass);
        class_link(threadclass);
 
@@ -433,8 +493,12 @@ initThreads(u1 *stackbottom)
                throw_exception_exit();
 
        freeLockRecordPools(mainthreadobj->ee.lrpool);
+       /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
+        * the execution environment there. No Thread object must have been created
+        * at an earlier time */
        threadclass->instancesize = sizeof(threadobject);
 
+       /* Create a VMThread */
        mainthreadobj = (threadobject *) builtin_new(threadclass);
 
        if (!mainthreadobj)
@@ -443,36 +507,82 @@ initThreads(u1 *stackbottom)
        FREE(tempthread, threadobject);
        initThread(&mainthreadobj->o);
 
-#if !defined(HAVE___THREAD)
-       pthread_setspecific(tkey_threadinfo, mainthreadobj);
-#else
-       threadobj = mainthreadobj;
-#endif
+       setthreadobject(mainthreadobj);
 
-       mainthread = &mainthreadobj->o;
        initLocks();
        mainthreadobj->info.next = mainthreadobj;
        mainthreadobj->info.prev = mainthreadobj;
 
-       mainthread->name=javastring_new(utf_new_char("main"));
+       threadname = javastring_new(utf_new_char("main"));
 
        /* Allocate and init ThreadGroup */
        threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
-       mainthread->group =
+       threadgroup =
                (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
 
-       if (!mainthread->group)
+       if (!threadgroup)
                throw_exception_exit();
 
+       /* Create a Thread */
+       threadclass = class_new(utf_new_char("java/lang/Thread"));
+       mainthread = (java_lang_Thread*) builtin_new(threadclass);
+       mainthreadobj->o.thread = mainthread;
+
+       if (!mainthread)
+               throw_exception_exit();
+
+       /* Call Thread constructor */
+       method = class_resolveclassmethod(threadclass,
+                                                                         utf_new_char("<init>"),
+                                                                         utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
+                                                                         threadclass,
+                                                                         true);
+
+       if (!method)
+               throw_exception_exit();
+
+       asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
+       if (*exceptionptr)
+               throw_exception_exit();
+
+       mainthread->group = threadgroup;
+       /* XXX This is a hack because the fourth argument was omitted */
+       mainthread->daemon = false;
+
+       /* Add mainthread to ThreadGroup */
+       method = class_resolveclassmethod(threadgroupclass,
+                                                                         utf_new_char("addThread"),
+                                                                         utf_new_char("(Ljava/lang/Thread;)V"),
+                                                                         threadgroupclass,
+                                                                         true);
+
+       if (!method)
+               throw_exception_exit();
+
+       asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
+       if (*exceptionptr)
+               throw_exception_exit();
+
+       setPriority(pthread_self(), 5);
+
        pthread_attr_init(&threadattr);
        pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
 }
 
-void initThread(java_lang_Thread *t)
+void initThread(java_lang_VMThread *t)
 {
-       nativethread *info = &((threadobject*) t)->info;
+       threadobject *thread = (threadobject*) t;
+       nativethread *info = &thread->info;
+       info->tid = pthread_self();
+       /* TODO destroy all those things */
        pthread_mutex_init(&info->joinMutex, NULL);
        pthread_cond_init(&info->joinCond, NULL);
+
+       pthread_mutex_init(&thread->waitLock, NULL);
+       pthread_cond_init(&thread->waitCond, NULL);
+       thread->interrupted = false;
+       thread->signaled = false;
+       thread->isSleeping = false;
 }
 
 static void initThreadLocks(threadobject *);
@@ -509,6 +619,9 @@ static void *threadstartup(void *t)
        startup = NULL;
        sem_post(psem);
 
+       setPriority(info->tid, thread->o.thread->priority);
+       sched_yield();
+
        /* Find the run()V method and call it */
        method = class_resolveclassmethod(thread->o.header.vftbl->class,
                                                                          utf_new_char("run"),
@@ -524,6 +637,8 @@ static void *threadstartup(void *t)
                throw_exception();
        }
 
+       /* Allow lock record pools to be used by other threads. They cannot be
+        * deleted so we'd better not waste them. */
        freeLockRecordPools(thread->ee.lrpool);
 
        pthread_mutex_lock(&threadlistlock);
@@ -539,13 +654,13 @@ static void *threadstartup(void *t)
        return NULL;
 }
 
-void startThread(threadobject *t)
+void startThread(thread *t)
 {
-       nativethread *info = &t->info;
+       nativethread *info = &((threadobject*) t->vmThread)->info;
        sem_t sem;
        startupinfo startup;
 
-       startup.thread = t;
+       startup.thread = (threadobject*) t->vmThread;
        startup.psem = &sem;
 
        sem_init(&sem, 0, 0);
@@ -553,19 +668,34 @@ void startThread(threadobject *t)
        if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
                panic("pthread_create failed");
 
-       /* Wait here until thread has entered itself into the thread list */
+       /* Wait here until the thread has entered itself into the thread list */
        sem_wait(&sem);
        sem_destroy(&sem);
 }
 
+/* At the end of the program, we wait for all running non-daemon threads to die
+ */
+
+static threadobject *findNonDaemon(threadobject *thread)
+{
+       while (thread != mainthreadobj) {
+               if (!thread->o.thread->daemon)
+                       return thread;
+               thread = thread->info.prev;
+       }
+
+       return NULL;
+}
+
 void joinAllThreads()
 {
+       threadobject *thread;
        pthread_mutex_lock(&threadlistlock);
-       while (mainthreadobj->info.prev != mainthreadobj) {
-               nativethread *info = &mainthreadobj->info.prev->info;
+       while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
+               nativethread *info = &thread->info;
                pthread_mutex_lock(&info->joinMutex);
                pthread_mutex_unlock(&threadlistlock);
-               if (info->tid)
+               while (info->tid)
                        pthread_cond_wait(&info->joinCond, &info->joinMutex);
                pthread_mutex_unlock(&info->joinMutex);
                pthread_mutex_lock(&threadlistlock);
@@ -573,54 +703,30 @@ void joinAllThreads()
        pthread_mutex_unlock(&threadlistlock);
 }
 
-bool aliveThread(java_lang_Thread *t)
-{
-       return ((threadobject*) t)->info.tid != 0;
-}
-
-void sleepThread(s8 millis, s4 nanos)
-{
-       struct timespec tv;
-       tv.tv_sec = millis / 1000;
-       tv.tv_nsec = millis % 1000 * 1000000 + nanos;
-       do { } while (nanosleep(&tv, &tv) == EINTR);
-}
-
-void yieldThread()
-{
-       sched_yield();
-}
-
-static void timedCondWait(pthread_cond_t *cond, pthread_mutex_t *mutex, s8 millis)
+static void initLockRecord(monitorLockRecord *r, threadobject *t)
 {
-       struct timeval now;
-       struct timespec desttime;
-       gettimeofday(&now, NULL);
-       desttime.tv_sec = millis / 1000;
-       desttime.tv_nsec = millis % 1000 * 1000000;
-       pthread_cond_timedwait(cond, mutex, &desttime);
+       r->lockCount = 1;
+       r->ownerThread = t;
+       r->queuers = 0;
+       r->o = NULL;
+       r->waiter = NULL;
+       r->incharge = (monitorLockRecord *) &dummyLR;
+       r->waiting = false;
+       sem_init(&r->queueSem, 0, 0);
+       pthread_mutex_init(&r->resolveLock, NULL);
+       pthread_cond_init(&r->resolveWait, NULL);
 }
 
+/* No lock record must ever be destroyed because there may still be references
+ * to it.
 
-#define NEUTRAL 0
-#define LOCKED 1
-#define WAITERS 2
-#define BUSY 3
-
-static void initExecutionEnvironment(ExecEnvironment *ee)
-{
-       pthread_mutex_init(&ee->metaLockMutex, NULL);
-       pthread_cond_init(&ee->metaLockCond, NULL);
-       pthread_mutex_init(&ee->monitorLockMutex, NULL);
-       pthread_cond_init(&ee->monitorLockCond, NULL);
-}
-
-static void initLockRecord(monitorLockRecord *r, threadobject *t)
+static void destroyLockRecord(monitorLockRecord *r)
 {
-       r->owner = t;
-       r->lockCount = 1;
-       r->queue = NULL;
+       sem_destroy(&r->queueSem);
+       pthread_mutex_destroy(&r->resolveLock);
+       pthread_cond_destroy(&r->resolveWait);
 }
+*/
 
 void initLocks()
 {
@@ -629,34 +735,12 @@ void initLocks()
 
 static void initThreadLocks(threadobject *thread)
 {
-       int i;
-
-       initExecutionEnvironment(&thread->ee);
-       for (i=0; i<INITIALLOCKRECORDS; i++) {
-               monitorLockRecord *r = &thread->ee.lr[i];
-               initLockRecord(r, thread);
-               r->nextFree = &thread->ee.lr[i+1];
-       }
-       thread->ee.lr[i-1].nextFree = NULL;
-       thread->ee.firstLR = &thread->ee.lr[0];
-}
-
-static inline int lockState(long r)
-{
-       return (int) r & 3;
-}
-
-static inline void *lockRecord(long r)
-{
-       return (void*) (r & ~3L);
-}
-
-static inline long makeLockBits(void *r, long l)
-{
-       return ((long) r) | l;
+       thread->ee.firstLR = NULL;
+       thread->ee.lrpool = NULL;
+       thread->ee.numlr = 0;
 }
 
-static lockRecordPool *allocLockRecordPool(threadobject *thread, int size)
+static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
 {
        lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
        int i;
@@ -670,286 +754,364 @@ static lockRecordPool *allocLockRecordPool(threadobject *thread, int size)
        return p;
 }
 
-static void freeLockRecordPools(lockRecordPool *pool)
+#define INITIALLOCKRECORDS 8
+
+static pthread_mutex_t pool_lock;
+static lockRecordPool *global_pool;
+
+static void initPools()
 {
-       while (pool) {
-               lockRecordPool *n = pool->header.next;
-               mem_free(pool, sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * pool->header.size);
-               pool = n;
+       pthread_mutex_init(&pool_lock, NULL);
+}
+
+static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
+{
+       pthread_mutex_lock(&pool_lock);
+       if (global_pool) {
+               int i;
+               lockRecordPool *pool = global_pool;
+               global_pool = pool->header.next;
+               pthread_mutex_unlock(&pool_lock);
+
+               for (i=0; i < pool->header.size; i++)
+                       pool->lr[i].ownerThread = t;
+               
+               return pool;
        }
+       pthread_mutex_unlock(&pool_lock);
+
+       return allocNewLockRecordPool(t, size);
+}
+
+static void freeLockRecordPools(lockRecordPool *pool)
+{
+       lockRecordPoolHeader *last;
+       pthread_mutex_lock(&pool_lock);
+       last = &pool->header;
+       while (last->next)
+               last = &last->next->header;
+       last->next = global_pool;
+       global_pool = pool;
+       pthread_mutex_unlock(&pool_lock);
 }
 
-static monitorLockRecord *allocLockRecord(threadobject *t)
+static monitorLockRecord *allocLockRecordSimple(threadobject *t)
 {
        monitorLockRecord *r = t->ee.firstLR;
 
        if (!r) {
-               int poolsize = t->ee.lrpool ? t->ee.lrpool->header.size * 2 : INITIALLOCKRECORDS * 2;
+               int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
                lockRecordPool *pool = allocLockRecordPool(t, poolsize);
                pool->header.next = t->ee.lrpool;
                t->ee.lrpool = pool;
                r = &pool->lr[0];
+               t->ee.numlr += pool->header.size;
        }
        
        t->ee.firstLR = r->nextFree;
        return r;
 }
 
-static void recycleLockRecord(threadobject *t, monitorLockRecord *r)
+static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
 {
        r->nextFree = t->ee.firstLR;
        t->ee.firstLR = r;
 }
 
-static monitorLockRecord *appendToQueue(monitorLockRecord *queue, monitorLockRecord *lr)
+void initObjectLock(java_objectheader *o)
 {
-       monitorLockRecord *queuestart = queue;
-       if (!queue)
-               return lr;
-       while (queue->queue)
-               queue = queue->queue;
-       queue->queue = lr;
-       return queuestart;
+       o->monitorPtr = dummyLR;
 }
 
-static monitorLockRecord *moveMyLRToFront(threadobject *t, monitorLockRecord *lr)
+static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
 {
-       monitorLockRecord *pred = NULL;
-       monitorLockRecord *firstLR = lr;
-       while (lr->owner != t) {
-               pred = lr;
-               lr = lr->queue;
-       }
-       if (!pred)
-               return lr;
-       pred->queue = lr->queue;
-       lr->queue = firstLR;
-       lr->storedBits = firstLR->storedBits;
-       return lr;
+       atomic_add(&lr->queuers, 1);
+       MEMORY_BARRIER_AFTER_ATOMIC();
+       while (lr->o == o)
+               sem_wait(&lr->queueSem);
+       atomic_add(&lr->queuers, -1);
 }
 
-static long getMetaLockSlow(threadobject *t, long predBits);
-static void releaseMetaLockSlow(threadobject *t, long releaseBits);
+static void freeLockRecord(monitorLockRecord *lr)
+{
+       int q;
+       lr->o = NULL;
+       MEMORY_BARRIER();
+       q = lr->queuers;
+       while (q--)
+               sem_post(&lr->queueSem);
+}
 
-static long getMetaLock(threadobject *t, java_objectheader *o)
+static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
 {
-       long busyBits = makeLockBits(t, BUSY);
-       long lockBits = atomic_swap(&o->monitorBits, busyBits);
-       return lockState(lockBits) != BUSY ? lockBits : getMetaLockSlow(t, lockBits);
+       if (lr->waiting)
+               mlr->waiter = lr;
 }
 
-static long getMetaLockSlow(threadobject *t, long predBits)
+monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
 {
-       long bits;
-       threadobject *pred = lockRecord(predBits);
-       pthread_mutex_lock(&pred->ee.metaLockMutex);
-       if (!pred->ee.bitsForGrab) {
-               pred->ee.succ = t;
-               do {
-                       pthread_cond_wait(&pred->ee.metaLockCond, &pred->ee.metaLockMutex);
-               } while (!t->ee.gotMetaLockSlow);
-               t->ee.gotMetaLockSlow = false;
-               bits = t->ee.metaLockBits;
-       } else {
-               bits = pred->ee.metaLockBits;
-               pred->ee.bitsForGrab = false;
-               pthread_cond_signal(&pred->ee.metaLockCond);
+       for (;;) {
+               monitorLockRecord *lr = o->monitorPtr;
+               if (lr->o != o) {
+                       monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
+                       mlr->o = o;
+                       if (mlr == lr) {
+                               MEMORY_BARRIER();
+                               nlr = o->monitorPtr;
+                               if (nlr == lr) {
+                                       handleWaiter(mlr, lr);
+                                       return mlr;
+                               }
+                       } else {
+                               if (lr->ownerThread != t)
+                                       mlr->incharge = lr;
+                               MEMORY_BARRIER_BEFORE_ATOMIC();
+                               nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
+                       }
+                       if (nlr == lr) {
+                               if (mlr == lr || lr->o != o) {
+                                       handleWaiter(mlr, lr);
+                                       return mlr;
+                               }
+                               while (lr->o == o)
+                                       queueOnLockRecord(lr, o);
+                               handleWaiter(mlr, lr);
+                               return mlr;
+                       }
+                       freeLockRecord(mlr);
+                       recycleLockRecord(t, mlr);
+                       queueOnLockRecord(nlr, o);
+               } else {
+                       if (lr->ownerThread == t) {
+                               lr->lockCount++;
+                               return lr;
+                       }
+                       queueOnLockRecord(lr, o);
+               }
        }
-       pthread_mutex_unlock(&pred->ee.metaLockMutex);
-       return bits;
 }
 
-static void releaseMetaLock(threadobject *t, java_objectheader *o, long releaseBits)
+static void wakeWaiters(monitorLockRecord *lr)
 {
-       long busyBits = makeLockBits(t, BUSY);
-       int locked = compare_and_swap(&o->monitorBits, busyBits, releaseBits) != 0;
-       
-       if (!locked)
-               releaseMetaLockSlow(t, releaseBits);
+       do {
+               int q = lr->queuers;
+               while (q--)
+                       sem_post(&lr->queueSem);
+               lr = lr->waiter;
+       } while (lr);
 }
 
-static void releaseMetaLockSlow(threadobject *t, long releaseBits)
-{
-       pthread_mutex_lock(&t->ee.metaLockMutex);
-       if (t->ee.succ) {
-               assert(!t->ee.succ->ee.bitsForGrab);
-               assert(!t->ee.bitsForGrab);
-               assert(!t->ee.succ->ee.gotMetaLockSlow);
-               t->ee.succ->ee.metaLockBits = releaseBits;
-               t->ee.succ->ee.gotMetaLockSlow = true;
-               t->ee.succ = NULL;
-               pthread_cond_signal(&t->ee.metaLockCond);
-       } else {
-               t->ee.metaLockBits = releaseBits;
-               t->ee.bitsForGrab = true;
-               do {
-                       pthread_cond_wait(&t->ee.metaLockCond, &t->ee.metaLockMutex);
-               } while (t->ee.bitsForGrab);
+#define GRAB_LR(lr,t) \
+    if (lr->ownerThread != t) { \
+               lr = lr->incharge; \
        }
-       pthread_mutex_unlock(&t->ee.metaLockMutex);
-}
 
-static void monitorEnterSlow(threadobject *t, java_objectheader *o, long r);
+#define CHECK_MONITORSTATE(lr,t,mo,a) \
+    if (lr->o != mo || lr->ownerThread != t) { \
+               *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
+               a; \
+       }
 
-void monitorEnter(threadobject *t, java_objectheader *o)
+bool monitorExit(threadobject *t, java_objectheader *o)
 {
-       long r = getMetaLock(t, o);
-       int state = lockState(r);
-
-       if (state == NEUTRAL) {
-               monitorLockRecord *lr = allocLockRecord(t);
-               lr->storedBits = r;
-               releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
-       } else if (state == LOCKED) {
-               monitorLockRecord *ownerLR = lockRecord(r);
-               if (ownerLR->owner == t) {
-                       ownerLR->lockCount++;
-                       releaseMetaLock(t, o, r);
-               } else {
-                       monitorLockRecord *lr = allocLockRecord(t);
-                       ownerLR->queue = appendToQueue(ownerLR->queue, lr);
-                       monitorEnterSlow(t, o, r);
-               }
-       } else if (state == WAITERS) {
-               monitorLockRecord *lr = allocLockRecord(t);
-               monitorLockRecord *firstWaiterLR = lockRecord(r);
-               lr->queue = firstWaiterLR;
-               lr->storedBits = firstWaiterLR->storedBits;
-               releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
+       monitorLockRecord *lr = o->monitorPtr;
+       GRAB_LR(lr, t);
+       CHECK_MONITORSTATE(lr, t, o, return false);
+       if (lr->lockCount > 1) {
+               lr->lockCount--;
+               return true;
+       }
+       if (lr->waiter) {
+               monitorLockRecord *wlr = lr->waiter;
+               if (o->monitorPtr != lr ||
+                       (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
+               {
+                       monitorLockRecord *nlr = o->monitorPtr;
+                       nlr->waiter = wlr;
+                       STORE_ORDER_BARRIER();
+               } else
+                       wakeWaiters(wlr);
+               lr->waiter = NULL;
        }
+       freeLockRecord(lr);
+       recycleLockRecord(t, lr);
+       return true;
 }
 
-static void monitorEnterSlow(threadobject *t, java_objectheader *o, long r)
+static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
 {
-       monitorLockRecord *lr;
-       while (lockState(r) == LOCKED) {
-               pthread_mutex_lock(&t->ee.monitorLockMutex);
-               releaseMetaLock(t, o, r);
-               pthread_cond_wait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex);
-               pthread_mutex_unlock(&t->ee.monitorLockMutex);
-               r = getMetaLock(t, o);
-       }
-       assert(lockState(r) == WAITERS);
-       lr = moveMyLRToFront(t, lockRecord(r));
-       releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
+       do {
+               if (lr->waiter == wlr) {
+                       lr->waiter = wlr->waiter;
+                       break;
+               }
+               lr = lr->waiter;
+       } while (lr);
 }
 
-static void monitorExitSlow(threadobject *t, java_objectheader *o, monitorLockRecord *lr);
+static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
+{
+       return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
+}
 
-void monitorExit(threadobject *t, java_objectheader *o)
+static bool timeIsEarlier(const struct timespec *tv)
 {
-       long r = getMetaLock(t, o);
-       monitorLockRecord *ownerLR = lockRecord(r);
-       int state = lockState(r);
+       struct timeval tvnow;
+       struct timespec tsnow;
+       gettimeofday(&tvnow, NULL);
+       tsnow.tv_sec = tvnow.tv_sec;
+       tsnow.tv_nsec = tvnow.tv_usec * 1000;
+       return timespec_less(&tsnow, tv);
+}
 
-       if (state == LOCKED && ownerLR->owner == t) {
-               assert(ownerLR->lockCount >= 1);
-               if (ownerLR->lockCount == 1) {
-                       if (ownerLR->queue == NULL) {
-                               assert(lockState(ownerLR->storedBits) == NEUTRAL);
-                               releaseMetaLock(t, o, ownerLR->storedBits);
-                       } else {
-                               ownerLR->queue->storedBits = ownerLR->storedBits;
-                               monitorExitSlow(t, o, ownerLR->queue);
-                               ownerLR->queue = NULL;
-                       }
-                       recycleLockRecord(t, ownerLR);
-               } else {
-                       ownerLR->lockCount--;
-                       releaseMetaLock(t, o, r);
-               }
+bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
+{
+       bool wasinterrupted;
+
+       pthread_mutex_lock(&t->waitLock);
+       t->isSleeping = true;
+       if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
+               while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
+                       pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
+       else
+               while (!t->interrupted && !t->signaled)
+                       pthread_cond_wait(&t->waitCond, &t->waitLock);
+       wasinterrupted = t->interrupted;
+       t->interrupted = false;
+       t->signaled = false;
+       t->isSleeping = false;
+       pthread_mutex_unlock(&t->waitLock);
+       return wasinterrupted;
+}
 
+static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
+{
+       if (millis || nanos) {
+               struct timeval tv;
+               long nsec;
+               gettimeofday(&tv, NULL);
+               tv.tv_sec += millis / 1000;
+               millis %= 1000;
+               nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
+               tm->tv_sec = tv.tv_sec + nsec / 1000000000;
+               tm->tv_nsec = nsec % 1000000000;
        } else {
-               releaseMetaLock(t, o, r);
-
-               /* throw an exception */
-
-               *exceptionptr =
-                       new_exception(string_java_lang_IllegalMonitorStateException);
+               tm->tv_sec = 0;
+               tm->tv_nsec = 0;
        }
 }
 
-static threadobject *wakeupEE(monitorLockRecord *lr)
+void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
 {
-       while (lr->queue && lr->queue->owner->ee.isWaitingForNotify)
-               lr = lr->queue;
-       return lr->owner;
+       bool wasinterrupted;
+       struct timespec wakeupTime;
+       monitorLockRecord *mlr, *lr = o->monitorPtr;
+       GRAB_LR(lr, t);
+       CHECK_MONITORSTATE(lr, t, o, return);
+
+       calcAbsoluteTime(&wakeupTime, millis, nanos);
+       
+       if (lr->waiter)
+               wakeWaiters(lr->waiter);
+       lr->waiting = true;
+       STORE_ORDER_BARRIER();
+       freeLockRecord(lr);
+       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
+       mlr = monitorEnter(t, o);
+       removeFromWaiters(mlr, lr);
+       mlr->lockCount = lr->lockCount;
+       lr->lockCount = 1;
+       lr->waiting = false;
+       lr->waiter = NULL;
+       recycleLockRecord(t, lr);
+
+       if (wasinterrupted)
+               *exceptionptr = new_exception(string_java_lang_InterruptedException);
 }
 
-static void monitorExitSlow(threadobject *t, java_objectheader *o, monitorLockRecord *lr)
+static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
 {
-       threadobject *wakeEE = wakeupEE(lr);
-       if (wakeEE) {
-               pthread_mutex_lock(&wakeEE->ee.monitorLockMutex);
-               releaseMetaLock(t, o, makeLockBits(lr, WAITERS));
-               pthread_cond_signal(&wakeEE->ee.monitorLockCond);
-               pthread_mutex_unlock(&wakeEE->ee.monitorLockMutex);
-       } else {
-               releaseMetaLock(t, o, makeLockBits(lr, WAITERS));
-       }
+       monitorLockRecord *lr = o->monitorPtr;
+       GRAB_LR(lr, t);
+       CHECK_MONITORSTATE(lr, t, o, return);
+       do {
+               threadobject *wthread;
+               monitorLockRecord *wlr = lr->waiter;
+               if (!wlr)
+                       break;
+               wthread = wlr->ownerThread;
+               pthread_mutex_lock(&wthread->waitLock);
+               if (wthread->isSleeping)
+                       pthread_cond_signal(&wthread->waitCond);
+               wthread->signaled = true;
+               pthread_mutex_unlock(&wthread->waitLock);
+               lr = wlr;
+       } while (!one);
 }
 
-void monitorWait(threadobject *t, java_objectheader *o, s8 millis)
+bool threadHoldsLock(threadobject *t, java_objectheader *o)
 {
-       long r = getMetaLock(t, o);
-       monitorLockRecord *ownerLR = lockRecord(r);
-       int state = lockState(r);
+       monitorLockRecord *lr = o->monitorPtr;
+       GRAB_LR(lr, t);
+       return lr->o == o && lr->ownerThread == t;
+}
 
-       if (state == LOCKED && ownerLR->owner == t) {
-               pthread_mutex_lock(&t->ee.monitorLockMutex);
-               t->ee.isWaitingForNotify = true;
-               monitorExitSlow(t, o, ownerLR);
-               if (millis == -1)
-                       pthread_cond_wait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex);
-               else
-                       timedCondWait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex, millis);
-               t->ee.isWaitingForNotify = false;
-               pthread_mutex_unlock(&t->ee.monitorLockMutex);
-               r = getMetaLock(t, o);
-               monitorEnterSlow(t, o, r);
+void interruptThread(java_lang_VMThread *thread)
+{
+       threadobject *t = (threadobject*) thread;
 
-       } else {
-               releaseMetaLock(t, o, r);
+       t->interrupted = true;
+       pthread_mutex_lock(&t->waitLock);
+       if (t->isSleeping)
+               pthread_cond_signal(&t->waitCond);
+       pthread_mutex_unlock(&t->waitLock);
+}
 
-               /* throw an exception */
+bool interruptedThread()
+{
+       threadobject *t = (threadobject*) THREADOBJECT;
+       bool intr = t->interrupted;
+       t->interrupted = false;
+       return intr;
+}
 
-               *exceptionptr =
-                       new_exception(string_java_lang_IllegalMonitorStateException);
-       }
+bool isInterruptedThread(java_lang_VMThread *thread)
+{
+       threadobject *t = (threadobject*) thread;
+       return t->interrupted;
 }
 
-static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
+void sleepThread(s8 millis, s4 nanos)
 {
-       long r = getMetaLock(t, o);
-       monitorLockRecord *ownerLR = lockRecord(r);
-       int state = lockState(r);
-
-       if (state == LOCKED && ownerLR->owner == t) {
-               monitorLockRecord *q = ownerLR->queue;
-               while (q) {
-                       if (q->owner->ee.isWaitingForNotify) {
-                               q->owner->ee.isWaitingForNotify = false;
-                               if (one)
-                                       break;
-                       }
-                       q = q->queue;
-               }
-               releaseMetaLock(t, o, r);
+       bool wasinterrupted;
+       threadobject *t = (threadobject*) THREADOBJECT;
+       monitorLockRecord *lr;
+       struct timespec wakeupTime;
+       calcAbsoluteTime(&wakeupTime, millis, nanos);
 
-       } else {
-               releaseMetaLock(t, o, r);
+       lr = allocLockRecordSimple(t);
+       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
+       recycleLockRecord(t, lr);
 
-               /* throw an exception */
+       if (wasinterrupted)
+               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+}
 
-               *exceptionptr =
-                       new_exception(string_java_lang_IllegalMonitorStateException);
-       }
+void yieldThread()
+{
+       sched_yield();
 }
 
-void wait_cond_for_object(java_objectheader *o, s8 time)
+void setPriorityThread(thread *t, s4 priority)
+{
+       nativethread *info = &((threadobject*) t->vmThread)->info;
+       setPriority(info->tid, priority);
+}
+
+void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
 {
        threadobject *t = (threadobject*) THREADOBJECT;
-       monitorWait(t, o, time);
+       monitorWait(t, o, time, nanos);
 }
 
 void signal_cond_for_object(java_objectheader *o)
@@ -964,8 +1126,6 @@ void broadcast_cond_for_object(java_objectheader *o)
        notifyOneOrAll(t, o, false);
 }
 
-#endif
-
 
 /*
  * These are local overrides for various environment variables in Emacs.