#include <config.h>
#include <platform.h>
#include <string.h>
#pragma implementation "Object.h"
#include <gcj/cni.h>
#include <jvm.h>
#include <java/lang/Object.h>
#include <java-threads.h>
#include <java-signal.h>
#include <java/lang/CloneNotSupportedException.h>
#include <java/lang/IllegalArgumentException.h>
#include <java/lang/IllegalMonitorStateException.h>
#include <java/lang/InterruptedException.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/Class.h>
#include <java/lang/Cloneable.h>
#include <java/lang/Thread.h>
#ifdef LOCK_DEBUG
# include <stdio.h>
#endif
struct _Jv_SyncInfo
{
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
bool init;
#endif
_Jv_ConditionVariable_t condition;
_Jv_Mutex_t mutex;
};
jclass
java::lang::Object::getClass (void)
{
_Jv_VTable **dt = (_Jv_VTable **) this;
return (*dt)->clas;
}
jint
java::lang::Object::hashCode (void)
{
return _Jv_HashCode (this);
}
jobject
java::lang::Object::clone (void)
{
jclass klass = getClass ();
jobject r;
jint size;
if (klass->isArray())
{
__JArray *array = (__JArray *) this;
jclass comp = getClass()->getComponentType();
jint eltsize;
if (comp->isPrimitive())
{
r = _Jv_NewPrimArray (comp, array->length);
eltsize = comp->size();
}
else
{
r = _Jv_NewObjectArray (array->length, comp, NULL);
eltsize = sizeof (jobject);
}
size = (_Jv_GetArrayElementFromElementType (array, comp) - (char *) array
+ array->length * eltsize);
}
else
{
if (! java::lang::Cloneable::class$.isAssignableFrom(klass))
throw new CloneNotSupportedException;
size = klass->size();
r = JvAllocObject (klass, size);
}
memcpy ((void *) r, (void *) this, size);
return r;
}
void
_Jv_FinalizeObject (jobject obj)
{
try
{
obj->finalize ();
}
catch (java::lang::Throwable *t)
{
}
}
#ifndef JV_HASH_SYNCHRONIZATION
static _Jv_Mutex_t sync_mutex;
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
# define INIT_NEEDED(Obj) (! (Obj)->sync_info \
|| ! ((_Jv_SyncInfo *) ((Obj)->sync_info))->init)
#else
# define INIT_NEEDED(Obj) (! (Obj)->sync_info)
#endif
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
static void
finalize_sync_info (jobject obj)
{
_Jv_SyncInfo *si = (_Jv_SyncInfo *) obj;
#if defined (_Jv_HaveCondDestroy)
_Jv_CondDestroy (&si->condition);
#endif
#if defined (_Jv_HaveMutexDestroy)
_Jv_MutexDestroy (&si->mutex);
#endif
si->init = false;
}
#endif
void
java::lang::Object::sync_init (void)
{
_Jv_MutexLock (&sync_mutex);
if (INIT_NEEDED (this))
{
_Jv_SyncInfo *si;
si = (_Jv_SyncInfo *) _Jv_AllocBytes (sizeof (_Jv_SyncInfo));
_Jv_MutexInit (&si->mutex);
_Jv_CondInit (&si->condition);
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
si->init = true;
_Jv_RegisterFinalizer (si, finalize_sync_info);
#endif
sync_info = (jobject) si;
}
_Jv_MutexUnlock (&sync_mutex);
}
void
java::lang::Object::notify (void)
{
if (__builtin_expect (INIT_NEEDED (this), false))
sync_init ();
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
if (__builtin_expect (_Jv_CondNotify (&si->condition, &si->mutex), false))
throw new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner"));
}
void
java::lang::Object::notifyAll (void)
{
if (__builtin_expect (INIT_NEEDED (this), false))
sync_init ();
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
if (__builtin_expect (_Jv_CondNotifyAll (&si->condition, &si->mutex), false))
throw new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner"));
}
void
java::lang::Object::wait (jlong timeout, jint nanos)
{
if (__builtin_expect (INIT_NEEDED (this), false))
sync_init ();
if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, false))
throw new IllegalArgumentException;
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
switch (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos))
{
case _JV_NOT_OWNER:
throw new IllegalMonitorStateException (JvNewStringLatin1
("current thread not owner"));
case _JV_INTERRUPTED:
if (Thread::interrupted ())
throw new InterruptedException;
}
}
void
_Jv_InitializeSyncMutex (void)
{
_Jv_MutexInit (&sync_mutex);
}
void
_Jv_MonitorEnter (jobject obj)
{
#ifndef HANDLE_SEGV
if (__builtin_expect (! obj, false))
throw new java::lang::NullPointerException;
#endif
if (__builtin_expect (INIT_NEEDED (obj), false))
obj->sync_init ();
_Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
_Jv_MutexLock (&si->mutex);
}
void
_Jv_MonitorExit (jobject obj)
{
JvAssert (obj);
JvAssert (! INIT_NEEDED (obj));
_Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
if (__builtin_expect (_Jv_MutexUnlock (&si->mutex), false))
throw new java::lang::IllegalMonitorStateException;
}
#else
#ifndef HAVE_BOEHM_GC
# error Hash synchronization currently requires boehm-gc
#else
# include "gc.h"
#endif
#include <assert.h>
#include <limits.h>
#include <unistd.h> // for usleep, sysconf.
#include <gcj/javaprims.h>
#include <sysdep/locks.h>
#include <java/lang/Thread.h>
static bool
is_mp()
{
#ifdef _SC_NPROCESSORS_ONLN
long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
return (nprocs > 1);
#else
return false;
#endif
}
inline static void
keep_live(obj_addr_t p)
{
__asm__ __volatile__("" : : "rm"(p) : "memory");
}
struct heavy_lock {
void * reserved_for_gc;
struct heavy_lock *next; void * old_client_data; GC_finalization_proc old_finalization_proc;
obj_addr_t address; _Jv_SyncInfo si;
};
#ifdef LOCK_DEBUG
void
print_hl_list(heavy_lock *hl)
{
heavy_lock *p = hl;
for (; 0 != p; p = p->next)
fprintf (stderr, "(hl = %p, addr = %p)", p, (void *)(p -> address));
}
#endif
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
static inline void
heavy_lock_finalization_proc (heavy_lock *hl)
{
#if defined (_Jv_HaveCondDestroy)
_Jv_CondDestroy (&hl->si.condition);
#endif
#if defined (_Jv_HaveMutexDestroy)
_Jv_MutexDestroy (&hl->si.mutex);
#endif
hl->si.init = false;
}
#endif
struct hash_entry {
volatile obj_addr_t address; # define LOCKED 1 // This hash entry is locked, and its
# define HEAVY 2 // There may be heavyweight locks
# define REQUEST_CONVERSION 4 // The lightweight lock is held. But
# define FLAGS (LOCKED | HEAVY | REQUEST_CONVERSION)
volatile _Jv_ThreadId_t light_thr_id;
# define INVALID_THREAD_ID 0 // Works for Linux?
volatile unsigned short light_count;
unsigned short heavy_count; struct heavy_lock * heavy_locks;
};
#ifndef JV_SYNC_TABLE_SZ
# define JV_SYNC_TABLE_SZ 2048
#endif
hash_entry light_locks[JV_SYNC_TABLE_SZ];
#define JV_SYNC_HASH(p) (((long)p ^ ((long)p >> 10)) % JV_SYNC_TABLE_SZ)
#ifdef LOCK_DEBUG
void print_he(hash_entry *he)
{
fprintf(stderr, "lock hash entry = %p, index = %d, address = 0x%lx\n"
"\tlight_thr_id = 0x%lx, light_count = %d, "
"heavy_count = %d\n\theavy_locks:", he,
he - light_locks, he -> address, he -> light_thr_id,
he -> light_count, he -> heavy_count);
print_hl_list(he -> heavy_locks);
fprintf(stderr, "\n");
}
#endif
static bool mp = false;
static void
spin(unsigned n)
{
const unsigned MP_SPINS = 10;
const unsigned YIELDS = 4;
const unsigned SPINS_PER_UNIT = 30;
const unsigned MIN_SLEEP_USECS = 2001; const unsigned MAX_SLEEP_USECS = 200000;
static unsigned spin_limit = 0;
static unsigned yield_limit = YIELDS;
static bool spin_initialized = false;
if (!spin_initialized)
{
mp = is_mp();
if (mp)
{
spin_limit = MP_SPINS;
yield_limit = MP_SPINS + YIELDS;
}
spin_initialized = true;
}
if (n < spin_limit)
{
unsigned i = SPINS_PER_UNIT << n;
for (; i > 0; --i)
__asm__ __volatile__("");
}
else if (n < yield_limit)
{
_Jv_ThreadYield();
}
else
{
unsigned duration = MIN_SLEEP_USECS << (n - yield_limit);
if (n >= 15 + yield_limit || duration > MAX_SLEEP_USECS)
duration = MAX_SLEEP_USECS;
_Jv_platform_usleep(duration);
}
}
static void
wait_unlocked (hash_entry *he)
{
unsigned i = 0;
while (he -> address & LOCKED)
spin (i++);
}
static inline heavy_lock *
find_heavy (obj_addr_t addr, hash_entry *he)
{
heavy_lock *hl = he -> heavy_locks;
while (hl != 0 && hl -> address != addr) hl = hl -> next;
return hl;
}
static inline void
unlink_heavy (obj_addr_t addr, hash_entry *he)
{
heavy_lock **currentp = &(he -> heavy_locks);
while ((*currentp) -> address != addr)
currentp = &((*currentp) -> next);
*currentp = (*currentp) -> next;
}
static void
heavy_lock_obj_finalization_proc (void *obj, void *cd)
{
heavy_lock *hl = (heavy_lock *)cd;
#ifdef JV_LINKER_CANNOT_8BYTE_ALIGN_STATICS
obj_addr_t addr = (obj_addr_t)obj & ~((obj_addr_t)0x7);
#else
obj_addr_t addr = (obj_addr_t)obj;
#endif
hash_entry *he = light_locks + JV_SYNC_HASH(addr);
obj_addr_t he_address = (he -> address & ~LOCKED);
while (!compare_and_swap(&(he -> address), he_address, he_address|LOCKED ))
{
wait_unlocked(he);
he_address = (he -> address & ~LOCKED);
}
if (0 == hl -> address)
{
release_set(&(he -> address), he_address);
return;
}
assert(hl -> address == addr);
GC_finalization_proc old_finalization_proc = hl -> old_finalization_proc;
if (old_finalization_proc != 0)
{
void * old_client_data = hl -> old_client_data;
hl -> old_finalization_proc = 0;
hl -> old_client_data = 0;
# ifdef HAVE_BOEHM_GC
GC_REGISTER_FINALIZER_NO_ORDER(obj, heavy_lock_obj_finalization_proc, cd, 0, 0);
# endif
release_set(&(he -> address), he_address);
old_finalization_proc(obj, old_client_data);
}
else
{
unlink_heavy(addr, he);
hl -> address = 0; release_set(&(he -> address), he_address);
# if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
_Jv_MutexLock(&(hl->si.mutex));
_Jv_MutexUnlock(&(hl->si.mutex));
heavy_lock_finalization_proc (hl);
# endif
}
}
static void
remove_all_heavy (hash_entry *he, obj_addr_t new_address_val)
{
assert(he -> heavy_count == 0);
assert(he -> address & LOCKED);
heavy_lock *hl = he -> heavy_locks;
he -> heavy_locks = 0;
for(; 0 != hl; hl = hl->next)
{
obj_addr_t obj = hl -> address;
assert(0 != obj); hl -> address = 0; GC_finalization_proc old_finalization_proc = hl -> old_finalization_proc;
void * old_client_data = hl -> old_client_data;
# ifdef HAVE_BOEHM_GC
GC_REGISTER_FINALIZER_NO_ORDER((GC_PTR)obj, old_finalization_proc,
old_client_data, 0, 0);
# endif
# if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
_Jv_MutexLock(&(hl->si.mutex));
_Jv_MutexUnlock(&(hl->si.mutex));
heavy_lock_finalization_proc (hl);
# endif
}
release_set(&(he -> address), new_address_val);
}
static inline void
maybe_remove_all_heavy (hash_entry *he, obj_addr_t new_address_val)
{
static const int max_len = 5;
heavy_lock *hl = he -> heavy_locks;
for (int i = 0; i < max_len; ++i)
{
if (0 == hl)
{
release_set(&(he -> address), new_address_val);
return;
}
hl = hl -> next;
}
remove_all_heavy(he, new_address_val);
}
static heavy_lock *
alloc_heavy(obj_addr_t addr, hash_entry *he)
{
heavy_lock * hl = (heavy_lock *) _Jv_AllocTraceTwo(sizeof (heavy_lock));
hl -> address = addr;
_Jv_MutexInit (&(hl -> si.mutex));
_Jv_CondInit (&(hl -> si.condition));
# if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
hl->si.init = true; # endif
hl -> next = he -> heavy_locks;
he -> heavy_locks = hl;
# ifdef HAVE_BOEHM_GC
GC_REGISTER_FINALIZER_NO_ORDER(
(void *)addr, heavy_lock_obj_finalization_proc,
hl, &hl->old_finalization_proc,
&hl->old_client_data);
# endif
return hl;
}
static heavy_lock *
get_heavy(obj_addr_t addr, hash_entry *he)
{
heavy_lock *hl = find_heavy(addr, he);
if (0 == hl)
hl = alloc_heavy(addr, he);
return hl;
}
void
_Jv_MonitorEnter (jobject obj)
{
#ifdef JV_LINKER_CANNOT_8BYTE_ALIGN_STATICS
obj_addr_t addr = (obj_addr_t)obj & ~((obj_addr_t)FLAGS);
#else
obj_addr_t addr = (obj_addr_t)obj;
#endif
obj_addr_t address;
unsigned hash = JV_SYNC_HASH(addr);
hash_entry * he = light_locks + hash;
_Jv_ThreadId_t self = _Jv_ThreadSelf();
unsigned count;
const unsigned N_SPINS = 18;
if (__builtin_expect(!addr, false))
throw new java::lang::NullPointerException;
assert(!(addr & FLAGS));
retry:
if (__builtin_expect(compare_and_swap(&(he -> address),
0, addr),true))
{
assert(he -> light_thr_id == INVALID_THREAD_ID);
assert(he -> light_count == 0);
he -> light_thr_id = self;
return;
}
address = he -> address;
if ((address & ~(HEAVY | REQUEST_CONVERSION)) == addr)
{
if (he -> light_thr_id == self)
{
count = he -> light_count;
if (count == USHRT_MAX)
{
throw new java::lang::IllegalMonitorStateException(
JvNewStringLatin1("maximum monitor nesting level exceeded"));
}
he -> light_count = count + 1;
return;
}
else
{
for (unsigned int i = 0; i < N_SPINS; ++i)
{
if ((he -> address & ~LOCKED) != (address & ~LOCKED)) goto retry;
spin(i);
}
address &= ~LOCKED;
if (!compare_and_swap(&(he -> address), address, address | LOCKED ))
{
wait_unlocked(he);
goto retry;
}
heavy_lock *hl = get_heavy(addr, he);
++ (he -> heavy_count);
_Jv_MutexLock(&(hl->si.mutex));
assert(he -> address == address | LOCKED );
release_set(&(he -> address), (address | REQUEST_CONVERSION | HEAVY));
while ((he -> address & ~FLAGS) == (address & ~FLAGS))
{
_Jv_CondWait (&(hl->si.condition), &(hl->si.mutex), 0, 0);
}
keep_live(addr);
assert(he -> address & HEAVY);
return;
}
}
obj_addr_t was_heavy = (address & HEAVY);
address &= ~LOCKED;
if (!compare_and_swap(&(he -> address), address, (address | LOCKED )))
{
wait_unlocked(he);
goto retry;
}
if ((address & ~(HEAVY | REQUEST_CONVERSION)) == 0)
{
assert(!(address & REQUEST_CONVERSION));
heavy_lock *hl;
hl = (was_heavy? find_heavy(addr, he) : 0);
if (0 == hl)
{
he -> light_thr_id = self; assert(he -> light_count == 0);
assert(was_heavy == (he -> address & HEAVY));
release_set(&(he -> address), (addr | was_heavy));
}
else
{
++ (he -> heavy_count);
assert(0 == (address & ~HEAVY));
release_set(&(he -> address), HEAVY);
_Jv_MutexLock(&(hl->si.mutex));
keep_live(addr);
}
return;
}
{
assert(0 == he -> heavy_count || (address & HEAVY));
heavy_lock *hl = get_heavy(addr, he);
++ (he -> heavy_count);
release_set(&(he -> address), address | HEAVY);
_Jv_MutexLock(&(hl->si.mutex));
keep_live(addr);
}
}
void
_Jv_MonitorExit (jobject obj)
{
#ifdef JV_LINKER_CANNOT_8BYTE_ALIGN_STATICS
obj_addr_t addr = (obj_addr_t)obj & ~((obj_addr_t)FLAGS);
#else
obj_addr_t addr = (obj_addr_t)obj;
#endif
_Jv_ThreadId_t self = _Jv_ThreadSelf();
unsigned hash = JV_SYNC_HASH(addr);
hash_entry * he = light_locks + hash;
_Jv_ThreadId_t light_thr_id;
unsigned count;
obj_addr_t address;
retry:
light_thr_id = he -> light_thr_id;
address = he -> address;
if (__builtin_expect(light_thr_id == self, true))
{
count = he -> light_count;
if (__builtin_expect((address & ~HEAVY) == addr, true))
{
if (count != 0)
{
he -> light_count = count - 1;
return;
}
else
{
he -> light_thr_id = INVALID_THREAD_ID;
if (compare_and_swap_release(&(he -> address), address,
address & HEAVY))
return;
else
{
he -> light_thr_id = light_thr_id; goto retry;
}
}
}
}
else
{
if (__builtin_expect(!addr, false))
throw new java::lang::NullPointerException;
if ((address & ~(HEAVY | REQUEST_CONVERSION)) == addr)
{
# ifdef LOCK_DEBUG
fprintf(stderr, "Lightweight lock held by other thread\n\t"
"light_thr_id = 0x%lx, self = 0x%lx, "
"address = 0x%lx, pid = %d\n",
light_thr_id, self, address, getpid());
print_he(he);
for(;;) {}
# endif
throw new java::lang::IllegalMonitorStateException(
JvNewStringLatin1("current thread not owner"));
}
else
count = he -> light_count;
}
if (address & LOCKED)
{
wait_unlocked(he);
goto retry;
}
if ((address & ~FLAGS) == addr)
{
if (0 != count)
{
he -> light_count = count - 1;
return;
}
assert(he -> light_thr_id == self);
assert(address & REQUEST_CONVERSION);
if (!compare_and_swap(&(he -> address), address, address | LOCKED))
goto retry;
heavy_lock *hl = find_heavy(addr, he);
assert (0 != hl);
he -> light_count = 0;
assert(he -> heavy_count > 0);
_Jv_MutexLock(&(hl->si.mutex));
he -> light_thr_id = INVALID_THREAD_ID;
release_set(&(he -> address), HEAVY);
_Jv_CondNotifyAll(&(hl->si.condition), &(hl->si.mutex));
_Jv_MutexUnlock(&(hl->si.mutex));
keep_live(addr);
return;
}
assert(!(address & LOCKED));
assert((address & ~FLAGS) != addr);
if (!compare_and_swap(&(he -> address), address, address | LOCKED))
goto retry;
heavy_lock *hl = find_heavy(addr, he);
if (NULL == hl)
{
# ifdef LOCK_DEBUG
fprintf(stderr, "Failed to find heavyweight lock for addr 0x%lx"
" pid = %d\n", addr, getpid());
print_he(he);
for(;;) {}
# endif
throw new java::lang::IllegalMonitorStateException(
JvNewStringLatin1("current thread not owner"));
}
assert(address & HEAVY);
count = he -> heavy_count;
assert(count > 0);
--count;
he -> heavy_count = count;
if (0 == count)
{
const unsigned test_freq = 16; static volatile unsigned counter = 0;
unsigned my_counter = counter;
counter = my_counter + 1;
if (my_counter%test_freq == 0)
{
counter = my_counter + (my_counter >> 4) % (test_freq/2);
_Jv_MutexUnlock(&(hl->si.mutex));
maybe_remove_all_heavy(he, address &~HEAVY);
}
else
{
release_set(&(he -> address), address &~HEAVY);
_Jv_MutexUnlock(&(hl->si.mutex));
}
}
else
{
release_set(&(he -> address), address);
_Jv_MutexUnlock(&(hl->si.mutex));
}
keep_live(addr);
}
void
java::lang::Object::wait (jlong timeout, jint nanos)
{
#ifdef JV_LINKER_CANNOT_8BYTE_ALIGN_STATICS
obj_addr_t addr = (obj_addr_t)this & ~((obj_addr_t)FLAGS);
#else
obj_addr_t addr = (obj_addr_t)this;
#endif
_Jv_ThreadId_t self = _Jv_ThreadSelf();
unsigned hash = JV_SYNC_HASH(addr);
hash_entry * he = light_locks + hash;
unsigned count;
obj_addr_t address;
heavy_lock *hl;
if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, false))
throw new IllegalArgumentException;
retry:
address = he -> address;
address &= ~LOCKED;
if (!compare_and_swap(&(he -> address), address, address | LOCKED))
{
wait_unlocked(he);
goto retry;
}
if ((address & ~FLAGS) == addr)
{
if (he -> light_thr_id != self)
{
# ifdef LOCK_DEBUG
fprintf(stderr, "Found wrong lightweight lock owner in wait "
"address = 0x%lx pid = %d\n", address, getpid());
print_he(he);
for(;;) {}
# endif
release_set(&(he -> address), address);
throw new IllegalMonitorStateException (JvNewStringLatin1
("current thread not owner"));
}
count = he -> light_count;
hl = get_heavy(addr, he);
he -> light_count = 0;
he -> heavy_count += count + 1;
for (unsigned i = 0; i <= count; ++i)
_Jv_MutexLock(&(hl->si.mutex));
he -> light_thr_id = INVALID_THREAD_ID;
release_set(&(he -> address), HEAVY); if (address & REQUEST_CONVERSION)
_Jv_CondNotify (&(hl->si.condition), &(hl->si.mutex));
}
else
{
hl = find_heavy(addr, he);
release_set(&(he -> address), address);
if (0 == hl)
{
# ifdef LOCK_DEBUG
fprintf(stderr, "Couldn't find heavy lock in wait "
"addr = 0x%lx pid = %d\n", addr, getpid());
print_he(he);
for(;;) {}
# endif
throw new IllegalMonitorStateException (JvNewStringLatin1
("current thread not owner"));
}
assert(address & HEAVY);
}
switch (_Jv_CondWait (&(hl->si.condition), &(hl->si.mutex), timeout, nanos))
{
case _JV_NOT_OWNER:
throw new IllegalMonitorStateException (JvNewStringLatin1
("current thread not owner"));
case _JV_INTERRUPTED:
if (Thread::interrupted ())
throw new InterruptedException;
}
}
void
java::lang::Object::notify (void)
{
#ifdef JV_LINKER_CANNOT_8BYTE_ALIGN_STATICS
obj_addr_t addr = (obj_addr_t)this & ~((obj_addr_t)FLAGS);
#else
obj_addr_t addr = (obj_addr_t)this;
#endif
_Jv_ThreadId_t self = _Jv_ThreadSelf();
unsigned hash = JV_SYNC_HASH(addr);
hash_entry * he = light_locks + hash;
heavy_lock *hl;
obj_addr_t address;
int result;
retry:
address = ((he -> address) & ~LOCKED);
if (!compare_and_swap(&(he -> address), address, address | LOCKED))
{
wait_unlocked(he);
goto retry;
}
if ((address & ~FLAGS) == addr && he -> light_thr_id == self)
{
release_set(&(he -> address), address); return;
}
hl = find_heavy(addr, he);
release_set(&(he -> address), address); if (0 == hl)
{
throw new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner"));
return;
}
result = _Jv_CondNotify(&(hl->si.condition), &(hl->si.mutex));
keep_live(addr);
if (__builtin_expect (result, 0))
throw new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner"));
}
void
java::lang::Object::notifyAll (void)
{
#ifdef JV_LINKER_CANNOT_8BYTE_ALIGN_STATICS
obj_addr_t addr = (obj_addr_t)this & ~((obj_addr_t)FLAGS);
#else
obj_addr_t addr = (obj_addr_t)this;
#endif
_Jv_ThreadId_t self = _Jv_ThreadSelf();
unsigned hash = JV_SYNC_HASH(addr);
hash_entry * he = light_locks + hash;
heavy_lock *hl;
obj_addr_t address;
int result;
retry:
address = (he -> address) & ~LOCKED;
if (!compare_and_swap(&(he -> address), address, address | LOCKED))
{
wait_unlocked(he);
goto retry;
}
hl = find_heavy(addr, he);
if ((address & ~FLAGS) == addr && he -> light_thr_id == self)
{
release_set(&(he -> address), address); return;
}
release_set(&(he -> address), address); if (0 == hl)
{
throw new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner"));
}
result = _Jv_CondNotifyAll(&(hl->si.condition), &(hl->si.mutex));
if (__builtin_expect (result, 0))
throw new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner"));
}
void
java::lang::Object::sync_init (void)
{
throw new IllegalMonitorStateException(JvNewStringLatin1
("internal error: sync_init"));
}
void
_Jv_InitializeSyncMutex (void)
{
}
#endif