From 4a47cea23e09316a6ddb581d74d3c6e16072d39b Mon Sep 17 00:00:00 2001 From: edwin Date: Thu, 18 May 2006 14:33:32 +0000 Subject: [PATCH] * src/threads/native/lock.h, src/threads/native/lock.c: Tasuki lock implementation (without lock deflation). This is a straight-forward implementation that uses an extra word in java_objectheader for the FLC (flat lock contention) bit. * src/vm/global.h (java_objectheader): Added field `flcword`. * src/threads/native/lock.h (Authors): Changed to myself, as there is none of the old code remaining in this file. * src/vm/jit/powerpc/codegen.c, src/vm/jit/alpha/codegen.c, src/vm/jit/mips/codegen.c, src/vm/jit/i386/codegen.c, src/vm/jit/x86_64/codegen.c (codegen, createnativestub): Add the FLC word when creating the fake object header for patcher synchronization. --- src/threads/native/lock.c | 560 +++++++++++++++++++++++++++-------- src/threads/native/lock.h | 22 +- src/vm/global.h | 3 +- src/vm/jit/alpha/codegen.c | 12 +- src/vm/jit/i386/codegen.c | 12 +- src/vm/jit/mips/codegen.c | 12 +- src/vm/jit/powerpc/codegen.c | 12 +- src/vm/jit/x86_64/codegen.c | 12 +- 8 files changed, 493 insertions(+), 152 deletions(-) diff --git a/src/threads/native/lock.c b/src/threads/native/lock.c index 0cf9c7d77..fd75800a7 100644 --- a/src/threads/native/lock.c +++ b/src/threads/native/lock.c @@ -60,15 +60,30 @@ #include "machine-instr.h" #endif + +/******************************************************************************/ +/* DEBUGGING MACROS */ +/******************************************************************************/ + /* #define LOCK_VERBOSE */ +#if defined(LOCK_VERBOSE) +#define LOCK_LOG(args) do { printf args; fflush(stdout); } while (0) +#else +#define LOCK_LOG(args) +#endif + /******************************************************************************/ /* MACROS */ /******************************************************************************/ /* number of lock records in the first pool allocated for a thread */ -#define INITIALLOCKRECORDS 8 +#define LOCK_INITIAL_LOCK_RECORDS 8 + +#define LOCK_INITIAL_HASHTABLE_SIZE 1613 /* a prime in the middle between 1024 and 2048 */ + +#define LOCK_HASH(obj) ((ptrint)(obj)) #define COMPARE_AND_SWAP_OLD_VALUE(address, oldvalue, newvalue) \ ((ptrint) compare_and_swap((long *)(address), (long)(oldvalue), (long)(newvalue))) @@ -78,11 +93,27 @@ (compare_and_swap((long *)(address), (long)(oldvalue), (long)(newvalue)) == (long)(oldvalue)) +/******************************************************************************/ +/* MACROS FOR THE FLAT LOCK CONTENTION BIT */ +/******************************************************************************/ + +#define LOCK_SET_FLC_BIT(obj) ((obj)->flcword = 1) +#define LOCK_CLEAR_FLC_BIT(obj) ((obj)->flcword = 0) +#define LOCK_TEST_FLC_BIT(obj) ((obj)->flcword != 0) + + /******************************************************************************/ /* MACROS FOR THIN/FAT LOCKS */ /******************************************************************************/ -/* We use a variant of the thin locks described in the paper +/* We use a variant of the tasuki locks described in the paper + * + * Tamiya Onodera, Kiyokuni Kawachiya + * A Study of Locking Objects with Bimodal Fields + * Proceedings of the ACM OOPSLA '99, pp. 223-237 + * 1999 + * + * The underlying thin locks are a variant of the thin locks described in * * Bacon, Konuru, Murthy, Serrano * Thin Locks: Featherweight Synchronization for Java @@ -147,6 +178,23 @@ lock_record_pool_t *lock_global_pool; /* mutex for synchronizing access to the global pool */ pthread_mutex_t lock_global_pool_lock; +/* hashtable mapping objects to lock records */ +static lock_hashtable_t lock_hashtable; + + +/******************************************************************************/ +/* PROTOTYPES */ +/******************************************************************************/ + +static void lock_hashtable_init(void); +static lock_record_t * lock_hashtable_get_lock_record(threadobject *t, java_objectheader *o); + +static lock_record_t * lock_record_alloc(threadobject *t); + +static void lock_record_enter(threadobject *t, lock_record_t *lr); +static void lock_record_exit(threadobject *t, lock_record_t *lr); +static void lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos); +static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one); /*============================================================================*/ @@ -163,6 +211,8 @@ pthread_mutex_t lock_global_pool_lock; void lock_init(void) { pthread_mutex_init(&lock_global_pool_lock, NULL); + + lock_hashtable_init(); } @@ -178,7 +228,7 @@ void lock_init(void) static void lock_record_init(lock_record_t *r, threadobject *t) { - r->owner = t; + r->owner = NULL; r->count = 0; r->waiters = NULL; @@ -307,7 +357,7 @@ static lock_record_pool_t *lock_record_alloc_pool(threadobject *t, int size) /* re-initialize owner and freelist chaining */ for (i=0; i < pool->header.size; i++) { - pool->lr[i].owner = t; + pool->lr[i].owner = NULL; pool->lr[i].nextfree = &pool->lr[i+1]; } pool->lr[i-1].nextfree = NULL; @@ -371,10 +421,6 @@ void lock_record_free_pools(lock_record_pool_t *pool) IN: t............the current thread - POST-CONDITION: - The current thread holds the mutex of the returned lock record - and is recored as owner of the record. - *******************************************************************************/ static lock_record_t *lock_record_alloc(threadobject *t) @@ -390,7 +436,8 @@ static lock_record_t *lock_record_alloc(threadobject *t) /* get a new pool */ - poolsize = t->ee.lockrecordcount ? t->ee.lockrecordcount * 2 : INITIALLOCKRECORDS; + poolsize = t->ee.lockrecordcount ? t->ee.lockrecordcount * 2 + : LOCK_INITIAL_LOCK_RECORDS; pool = lock_record_alloc_pool(t, poolsize); /* add it to our per-thread pool list */ @@ -410,10 +457,6 @@ static lock_record_t *lock_record_alloc(threadobject *t) r->nextfree = NULL; /* in order to find invalid uses of nextfree */ #endif - /* pre-acquire the mutex of the new lock record */ - - pthread_mutex_lock(&(r->mutex)); - return r; } @@ -433,7 +476,7 @@ static inline void lock_record_recycle(threadobject *t, lock_record_t *r) { assert(t); assert(r); - assert(r->owner == t); + assert(r->owner == NULL); assert(r->nextfree == NULL); r->nextfree = t->ee.firstfree; @@ -442,6 +485,157 @@ static inline void lock_record_recycle(threadobject *t, lock_record_t *r) +/*============================================================================*/ +/* HASHTABLE MAPPING OBJECTS TO LOCK RECORDS */ +/*============================================================================*/ + + +/* lock_hashtable_init ********************************************************* + + Initialize the global hashtable mapping objects to lock records. + +*******************************************************************************/ + +static void lock_hashtable_init(void) +{ + pthread_mutex_init(&(lock_hashtable.mutex), NULL); + + lock_hashtable.size = LOCK_INITIAL_HASHTABLE_SIZE; + lock_hashtable.entries = 0; + lock_hashtable.ptr = MNEW(lock_record_t *, lock_hashtable.size); + MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size); +} + + +/* lock_hashtable_grow ********************************************************* + + Grow the lock record hashtable to about twice its current size and + rehash the entries. + +*******************************************************************************/ + +/* must be called with hashtable mutex locked */ +static void lock_hashtable_grow(void) +{ + u4 oldsize; + u4 newsize; + lock_record_t **oldtable; + lock_record_t **newtable; + lock_record_t *lr; + lock_record_t *next; + u4 i; + u4 h; + u4 newslot; + + /* allocate a new table */ + + oldsize = lock_hashtable.size; + newsize = oldsize*2 + 1; /* XXX should use prime numbers */ + + LOCK_LOG(("growing lock hashtable to size %d\n", newsize)); + + oldtable = lock_hashtable.ptr; + newtable = MNEW(lock_record_t *, newsize); + MZERO(newtable, lock_record_t *, newsize); + + /* rehash the entries */ + + for (i=0; ihashlink; + + h = LOCK_HASH(lr->obj); + newslot = h % newsize; + + lr->hashlink = newtable[newslot]; + newtable[newslot] = lr; + + lr = next; + } + } + + /* replace the old table */ + + lock_hashtable.ptr = newtable; + lock_hashtable.size = newsize; + + MFREE(oldtable, lock_record_t *, oldsize); +} + + +/* lock_hashtable_get_lock_record ********************************************** + + Find the lock record for the given object. If it does not exists, yet, + create it and enter it in the hashtable. + + IN: + t.................the current thread + o.................the object to look up + + RETURN VALUE: + the lock record to use for this object + +*******************************************************************************/ + +static lock_record_t *lock_hashtable_get_lock_record(threadobject *t, java_objectheader *o) +{ + ptrint lockword; + u4 slot; + lock_record_t *lr; + + lockword = (ptrint) o->monitorPtr; + + if (IS_FAT_LOCK(lockword)) { + return GET_FAT_LOCK(lockword); + } + + /* lock the hashtable */ + + pthread_mutex_lock(&(lock_hashtable.mutex)); + + /* lookup the lock record in the hashtable */ + + slot = LOCK_HASH(o) % lock_hashtable.size; + lr = lock_hashtable.ptr[slot]; + while (lr) { + if (lr->obj == o) { + pthread_mutex_unlock(&(lock_hashtable.mutex)); + return lr; + } + + lr = lr->hashlink; + } + + /* not found, we must create a new one */ + + lr = lock_record_alloc(t); + lr->obj = o; + LOCK_LOG(("thread %d allocated for %p new lr %p\n", + t->index, (void*) o, (void*) lr)); + + /* enter it in the hashtable */ + + lr->hashlink = lock_hashtable.ptr[slot]; + lock_hashtable.ptr[slot] = lr; + lock_hashtable.entries++; + + /* check whether the hash should grow */ + + if (lock_hashtable.entries * 3 > lock_hashtable.size * 4) { + lock_hashtable_grow(); + } + + /* unlock the hashtable */ + + pthread_mutex_unlock(&(lock_hashtable.mutex)); + + /* return the new lock record */ + + return lr; +} + + /*============================================================================*/ /* OBJECT LOCK INITIALIZATION */ /*============================================================================*/ @@ -459,6 +653,7 @@ void lock_init_object_lock(java_objectheader *o) assert(o); o->monitorPtr = (lock_record_t *) THIN_UNLOCKED; + o->flcword = 0; } @@ -482,52 +677,94 @@ lock_record_t *lock_get_initial_lock_word(void) /*============================================================================*/ +/* lock_record_enter *********************************************************** + + Enter the lock represented by the given lock record. + + IN: + t.................the current thread + lr................the lock record + +*******************************************************************************/ + +static inline void lock_record_enter(threadobject *t, lock_record_t *lr) +{ + pthread_mutex_lock(&(lr->mutex)); + lr->owner = t; +} + + +/* lock_record_exit ************************************************************ + + Release the lock represented by the given lock record. + + IN: + t.................the current thread + lr................the lock record + + PRE-CONDITION: + The current thread must own the lock represented by this lock record. + This is NOT checked by this function! + +*******************************************************************************/ + +static inline void lock_record_exit(threadobject *t, lock_record_t *lr) +{ + lr->owner = NULL; + pthread_mutex_unlock(&(lr->mutex)); +} + + /* lock_inflate **************************************************************** Inflate the lock of the given object. This may only be called by the - owner of the monitor. + owner of the monitor of the object. IN: t............the current thread o............the object of which to inflate the lock - - RETURN VALUE: - the new lock record of the object + lr...........the lock record to install. The current thread must + own the lock of this lock record! PRE-CONDITION: - The current thread must be the owner of this object's monitor! + The current thread must be the owner of this object's monitor AND + of the lock record's lock! *******************************************************************************/ -static lock_record_t *lock_inflate(threadobject *t, java_objectheader *o) +static void lock_inflate(threadobject *t, java_objectheader *o, lock_record_t *lr) { - lock_record_t *lr; ptrint lockword; - ptrint count; /* get the current lock count */ lockword = (ptrint) o->monitorPtr; - assert( LOCK_WORD_WITHOUT_COUNT(lockword) == t->thinlock ); + if (IS_FAT_LOCK(lockword)) { + assert(GET_FAT_LOCK(lockword) == lr); + } + else { + assert( LOCK_WORD_WITHOUT_COUNT(lockword) == t->thinlock ); - count = (lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT; + /* copy the count from the thin lock */ - /* allocate a fat lock */ + lr->count = (lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT; + } - lr = lock_record_alloc(t); - lr->count = count; + LOCK_LOG(("thread %3d: inflating lock of object %p current lockword %lx, count %d\n", + t->index, (void*) o, (long)o->monitorPtr, (int)lr->count)); -#if defined(LOCK_VERBOSE) - printf("thread %3d: inflating lock of object %p current lockword %lx, count %d\n", - t->index, (void*) o, (long)o->monitorPtr, (int)count); -#endif + /* clear flat-lock-contention bit */ + + LOCK_CLEAR_FLC_BIT(o); + + /* notify waiting objects */ + + lock_record_notify(t, lr, false); /* install it */ o->monitorPtr = (lock_record_t *) MAKE_FAT_LOCK(lr); - - return lr; } @@ -583,7 +820,9 @@ void lock_monitor_enter(threadobject *t, java_objectheader *o) /* recursion count overflow */ - lr = lock_inflate(t, o); + lr = lock_hashtable_get_lock_record(t, o); + lock_record_enter(t, lr); + lock_inflate(t, o, lr); lr->count++; return; @@ -594,7 +833,6 @@ void lock_monitor_enter(threadobject *t, java_objectheader *o) { lock_record_t *lr; - ptrint fatlock; if (IS_FAT_LOCK(lockword)) { @@ -605,53 +843,54 @@ void lock_monitor_enter(threadobject *t, java_objectheader *o) lr->count++; return; } - } - else { - /* alloc a lock record owned by us */ - lr = lock_record_alloc(t); - fatlock = MAKE_FAT_LOCK(lr); -#if defined(LOCK_VERBOSE) - printf("thread %3d: SPINNING for inflating lock of %p, current lockword = %lx\n", - t->index, (void*)o, (long)lockword); -#endif + /* acquire the mutex of the lock record */ - /* SPIN LOOP */ - while (true) { - lockword = COMPARE_AND_SWAP_OLD_VALUE(&(o->monitorPtr), THIN_UNLOCKED, fatlock); - if (lockword == THIN_UNLOCKED) { -#if defined(LOCK_VERBOSE) - printf("thread %3d: successfully inflated lock of %p\n", - t->index, (void*)o); -#endif - /* we managed to install our lock record */ - /* The Java Memory Model requires a memory barrier here: */ - MEMORY_BARRIER(); - return; - } + lock_record_enter(t, lr); - if (IS_FAT_LOCK(lockword)) { -#if defined(LOCK_VERBOSE) - printf("thread %3d: lock of %p was inflated by other thread, lockword = %lx\n", - t->index, (void*)o, (long)lockword); -#endif - /* another thread inflated the lock */ - pthread_mutex_unlock(&(lr->mutex)); - lock_record_recycle(t, lr); + assert(lr->count == 0); - lr = GET_FAT_LOCK(lockword); - break; - } - } + return; } - /* acquire the mutex of the lock record */ - pthread_mutex_lock(&(lr->mutex)); + /****** inflation path ******/ + + /* first obtain the lock record for this object */ + + lr = lock_hashtable_get_lock_record(t, o); + + /* enter the monitor */ - /* enter us as the owner */ - lr->owner = t; + lock_record_enter(t, lr); - assert(lr->count == 0); + /* inflation loop */ + + while (IS_THIN_LOCK(lockword = (ptrint) o->monitorPtr)) { + /* Set the flat lock contention bit to let the owning thread */ + /* know that we want to be notified of unlocking. */ + + LOCK_SET_FLC_BIT(o); + + LOCK_LOG(("thread %d set flc bit on %p lr %p\n", + t->index, (void*) o, (void*) lr)); + + /* try to lock the object */ + + if (COMPARE_AND_SWAP_SUCCEEDS(&(o->monitorPtr), THIN_UNLOCKED, thinlock)) { + /* we can inflate the lock ourselves */ + LOCK_LOG(("thread %d inflating lock of %p to lr %p\n", + t->index, (void*) o, (void*) lr)); + lock_inflate(t, o, lr); + } + else { + /* wait until another thread sees the flc bit and notifies us of unlocking */ + LOCK_LOG(("thread %d waiting for notification on %p lr %p\n", + t->index, (void*) o, (void*) lr)); + lock_record_wait(t, lr, 0, 0); + } + } + + /* we own the inflated lock now */ return; } @@ -695,6 +934,33 @@ bool lock_monitor_exit(threadobject *t, java_objectheader *o) o->monitorPtr = THIN_UNLOCKED; /* memory barrier for thin locking */ MEMORY_BARRIER(); + + /* check if there has been a flat lock contention on this object */ + + if (LOCK_TEST_FLC_BIT(o)) { + lock_record_t *lr; + + LOCK_LOG(("thread %d saw flc bit on %p %s\n", + t->index, (void*) o, o->vftbl->class->name->text)); + + /* there has been a contention on this thin lock */ + + lr = lock_hashtable_get_lock_record(t, o); + + LOCK_LOG(("thread %d for %p got lr %p\n", + t->index, (void*) o, (void*) lr)); + + lock_record_enter(t, lr); + + if (LOCK_TEST_FLC_BIT(o)) { + /* notify a thread that it can try to inflate the lock now */ + + lock_record_notify(t, lr, true); + } + + lock_record_exit(t, lr); + } + return true; } @@ -781,56 +1047,28 @@ static void lock_record_remove_waiter(lock_record_t *lr, threadobject *t) } -/* lock_monitor_wait *********************************************************** +/* lock_record_wait ************************************************************ - Wait on an object for a given (maximum) amount of time. + Wait on a lock record for a given (maximum) amount of time. IN: t............the current thread - o............the object + lr...........the lock record millis.......milliseconds of timeout nanos........nanoseconds of timeout PRE-CONDITION: - The current thread must be the owner of the object's monitor. + The current thread must be the owner of the lock record. + This is NOT checked by this function! *******************************************************************************/ -static void lock_monitor_wait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos) +static void lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos) { - ptrint lockword; - lock_record_t *lr; lock_waiter_t *waiter; s4 lockcount; bool wasinterrupted; - lockword = (ptrint) o->monitorPtr; - - /* check if we own this monitor */ - /* We don't have to worry about stale values here, as any stale value */ - /* will fail this check. */ - - if (IS_FAT_LOCK(lockword)) { - - lr = GET_FAT_LOCK(lockword); - - if (lr->owner != t) { - *exceptionptr = new_illegalmonitorstateexception(); - return; - } - } - else { - /* it's a thin lock */ - - if (LOCK_WORD_WITHOUT_COUNT(lockword) != t->thinlock) { - *exceptionptr = new_illegalmonitorstateexception(); - return; - } - - /* inflate this lock */ - lr = lock_inflate(t, o); - } - /* { the thread t owns the fat lock record lr on the object o } */ /* register us as waiter for this object */ @@ -847,8 +1085,7 @@ static void lock_monitor_wait(threadobject *t, java_objectheader *o, s8 millis, /* unlock this record */ lr->count = 0; - lr->owner = NULL; - pthread_mutex_unlock(&(lr->mutex)); + lock_record_exit(t, lr); /* wait until notified/interrupted/timed out */ @@ -856,11 +1093,7 @@ static void lock_monitor_wait(threadobject *t, java_objectheader *o, s8 millis, /* re-enter the monitor */ - lock_monitor_enter(t, o); - - /* assert that the lock record is still the same */ - - assert( GET_FAT_LOCK((ptrint) o->monitorPtr) == lr ); + lock_record_enter(t, lr); /* remove us from the list of waiting threads */ @@ -877,26 +1110,25 @@ static void lock_monitor_wait(threadobject *t, java_objectheader *o, s8 millis, } -/* lock_monitor_notify ********************************************************* +/* lock_monitor_wait *********************************************************** - Notify one thread or all threads waiting on the given object. + Wait on an object for a given (maximum) amount of time. IN: t............the current thread o............the object - one..........if true, only notify one thread + millis.......milliseconds of timeout + nanos........nanoseconds of timeout PRE-CONDITION: The current thread must be the owner of the object's monitor. *******************************************************************************/ -static void lock_monitor_notify(threadobject *t, java_objectheader *o, bool one) +static void lock_monitor_wait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos) { - ptrint lockword; + ptrint lockword; lock_record_t *lr; - lock_waiter_t *waiter; - threadobject *waitingthread; lockword = (ptrint) o->monitorPtr; @@ -922,11 +1154,39 @@ static void lock_monitor_notify(threadobject *t, java_objectheader *o, bool one) } /* inflate this lock */ - lr = lock_inflate(t, o); + lr = lock_hashtable_get_lock_record(t, o); + lock_record_enter(t, lr); + lock_inflate(t, o, lr); } /* { the thread t owns the fat lock record lr on the object o } */ + lock_record_wait(t, lr, millis, nanos); +} + + +/* lock_record_notify ********************************************************** + + Notify one thread or all threads waiting on the given lock record. + + IN: + t............the current thread + lr...........the lock record + one..........if true, only notify one thread + + PRE-CONDITION: + The current thread must be the owner of the lock record. + This is NOT checked by this function! + +*******************************************************************************/ + +static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one) +{ + lock_waiter_t *waiter; + threadobject *waitingthread; + + /* { the thread t owns the fat lock record lr on the object o } */ + /* for each waiter: */ for (waiter = lr->waiters; waiter; waiter = waiter->next) { @@ -949,6 +1209,60 @@ static void lock_monitor_notify(threadobject *t, java_objectheader *o, bool one) } +/* lock_monitor_notify ********************************************************* + + Notify one thread or all threads waiting on the given object. + + IN: + t............the current thread + o............the object + one..........if true, only notify one thread + + PRE-CONDITION: + The current thread must be the owner of the object's monitor. + +*******************************************************************************/ + +static void lock_monitor_notify(threadobject *t, java_objectheader *o, bool one) +{ + ptrint lockword; + lock_record_t *lr; + + lockword = (ptrint) o->monitorPtr; + + /* check if we own this monitor */ + /* We don't have to worry about stale values here, as any stale value */ + /* will fail this check. */ + + if (IS_FAT_LOCK(lockword)) { + + lr = GET_FAT_LOCK(lockword); + + if (lr->owner != t) { + *exceptionptr = new_illegalmonitorstateexception(); + return; + } + } + else { + /* it's a thin lock */ + + if (LOCK_WORD_WITHOUT_COUNT(lockword) != t->thinlock) { + *exceptionptr = new_illegalmonitorstateexception(); + return; + } + + /* inflate this lock */ + lr = lock_hashtable_get_lock_record(t, o); + lock_record_enter(t, lr); + lock_inflate(t, o, lr); + } + + /* { the thread t owns the fat lock record lr on the object o } */ + + lock_record_notify(t, lr, one); +} + + /*============================================================================*/ /* INQUIRY FUNCIONS */ diff --git a/src/threads/native/lock.h b/src/threads/native/lock.h index 29c69a3f3..93de86514 100644 --- a/src/threads/native/lock.h +++ b/src/threads/native/lock.h @@ -24,10 +24,9 @@ Contact: cacao@cacaojvm.org - Authors: Stefan Ring + Authors: Edwin Steiner - Changes: Christian Thalinger - Edwin Steiner + Changes: $Id: threads.h 4866 2006-05-01 21:40:38Z edwin $ @@ -48,6 +47,7 @@ typedef struct lock_record_t lock_record_t; typedef struct lock_record_pool_header_t lock_record_pool_header_t; typedef struct lock_record_pool_t lock_record_pool_t; typedef struct lock_waiter_t lock_waiter_t; +typedef struct lock_hashtable_t lock_hashtable_t; /* lock_execution_env_t ******************************************************** @@ -82,11 +82,27 @@ struct lock_waiter_t { *******************************************************************************/ struct lock_record_t { + java_objectheader *obj; /* object for which this lock is */ struct threadobject *owner; /* current owner of this monitor */ s4 count; /* recursive lock count */ pthread_mutex_t mutex; /* mutex for synchronizing */ lock_waiter_t *waiters; /* list of threads waiting */ lock_record_t *nextfree; /* next in free list */ + lock_record_t *hashlink; /* next record in hash chain */ +}; + + +/* lock_hashtable_t ************************************************************ + + The global hashtable mapping objects to lock records. + +*******************************************************************************/ + +struct lock_hashtable_t { + pthread_mutex_t mutex; /* mutex for synch. access to the table */ + u4 size; /* number of slots */ + u4 entries; /* current number of entries */ + lock_record_t **ptr; /* the table of slots, uses ext. chain. */ }; diff --git a/src/vm/global.h b/src/vm/global.h index dd6b02d27..01aa3c625 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -33,7 +33,7 @@ Joseph Wenninger Christian Thalinger - $Id: global.h 4921 2006-05-15 14:24:36Z twisti $ + $Id: global.h 4937 2006-05-18 14:33:32Z edwin $ */ @@ -199,6 +199,7 @@ struct java_objectheader { /* header for all objects */ struct _vftbl *vftbl; /* pointer to virtual function table */ #if defined(ENABLE_THREADS) struct lock_record_t *monitorPtr; + ptrint flcword; /* word containing the FLC bit */ #endif }; diff --git a/src/vm/jit/alpha/codegen.c b/src/vm/jit/alpha/codegen.c index 4e0bb0d85..f4cb5628f 100644 --- a/src/vm/jit/alpha/codegen.c +++ b/src/vm/jit/alpha/codegen.c @@ -32,7 +32,7 @@ Christian Ullrich Edwin Steiner - $Id: codegen.c 4921 2006-05-15 14:24:36Z twisti $ + $Id: codegen.c 4937 2006-05-18 14:33:32Z edwin $ */ @@ -3853,8 +3853,9 @@ gen_method: #if defined(ENABLE_THREADS) /* create a virtual java_objectheader */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_LDA(REG_ITMP3, REG_PV, disp); M_AST(REG_ITMP3, REG_SP, 4 * 8); @@ -4376,8 +4377,9 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) #if defined(ENABLE_THREADS) /* create a virtual java_objectheader */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_LDA(REG_ITMP3, REG_PV, disp); M_AST(REG_ITMP3, REG_SP, 4 * 8); diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index 9288991f4..014a77c8e 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -31,7 +31,7 @@ Christian Ullrich Edwin Steiner - $Id: codegen.c 4921 2006-05-15 14:24:36Z twisti $ + $Id: codegen.c 4937 2006-05-18 14:33:32Z edwin $ */ @@ -5200,8 +5200,9 @@ gen_method: /* move pointer to java_objectheader onto stack */ #if defined(ENABLE_THREADS) - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - off = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + off = dseg_addaddress(cd, NULL); /* vftbl */ M_MOV_IMM(0, REG_ITMP3); dseg_adddata(cd); @@ -5674,8 +5675,9 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) #if defined(ENABLE_THREADS) /* create a virtual java_objectheader */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_MOV_IMM(0, REG_ITMP3); dseg_adddata(cd); diff --git a/src/vm/jit/mips/codegen.c b/src/vm/jit/mips/codegen.c index 417b66674..db3681920 100644 --- a/src/vm/jit/mips/codegen.c +++ b/src/vm/jit/mips/codegen.c @@ -35,7 +35,7 @@ This module generates MIPS machine code for a sequence of intermediate code commands (ICMDs). - $Id: codegen.c 4921 2006-05-15 14:24:36Z twisti $ + $Id: codegen.c 4937 2006-05-18 14:33:32Z edwin $ */ @@ -3850,8 +3850,9 @@ gen_method: #if defined(ENABLE_THREADS) /* create a virtual java_objectheader */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_LDA(REG_ITMP3, REG_PV, disp); M_AST(REG_ITMP3, REG_SP, 4 * 8); @@ -4374,8 +4375,9 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) #if defined(ENABLE_THREADS) /* order reversed because of data segment layout */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_LDA(REG_ITMP3, REG_PV, disp); M_AST(REG_ITMP3, REG_SP, 4 * 8); diff --git a/src/vm/jit/powerpc/codegen.c b/src/vm/jit/powerpc/codegen.c index 5dbca06f5..57f99fdd2 100644 --- a/src/vm/jit/powerpc/codegen.c +++ b/src/vm/jit/powerpc/codegen.c @@ -31,7 +31,7 @@ Christian Ullrich Edwin Steiner - $Id: codegen.c 4933 2006-05-17 12:10:25Z twisti $ + $Id: codegen.c 4937 2006-05-18 14:33:32Z edwin $ */ @@ -3575,8 +3575,9 @@ gen_method: #if defined(ENABLE_THREADS) /* order reversed because of data segment layout */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_LDA(REG_ITMP3, REG_PV, disp); M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 4); @@ -4137,8 +4138,9 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) #if defined(ENABLE_THREADS) /* order reversed because of data segment layout */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ M_LDA(REG_ITMP3, REG_PV, disp); M_AST(REG_ITMP3, REG_SP, 4 * 4); diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index 6d5b11b11..1910aaa3a 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -30,7 +30,7 @@ Changes: Christian Ullrich Edwin Steiner - $Id: codegen.c 4921 2006-05-15 14:24:36Z twisti $ + $Id: codegen.c 4937 2006-05-18 14:33:32Z edwin $ */ @@ -3926,8 +3926,9 @@ gen_method: #if defined(ENABLE_THREADS) /* create a virtual java_objectheader */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - a = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + a = dseg_addaddress(cd, NULL); /* vftbl */ emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP3); M_PUSH(REG_ITMP3); @@ -4386,8 +4387,9 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) #if defined(ENABLE_THREADS) /* create a virtual java_objectheader */ - (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ - disp = dseg_addaddress(cd, NULL); /* vftbl */ + (void) dseg_addaddress(cd, NULL); /* flcword */ + (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */ + disp = dseg_addaddress(cd, NULL); /* vftbl */ emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP3); M_PUSH(REG_ITMP3); -- 2.25.1