123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- // natUnsafe.cc - Implementation of sun.misc.Unsafe native methods.
- /* Copyright (C) 2006, 2007
- Free Software Foundation
- This file is part of libgcj.
- This software is copyrighted work licensed under the terms of the
- Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
- details. */
- #include <gcj/cni.h>
- #include <gcj/field.h>
- #include <gcj/javaprims.h>
- #include <jvm.h>
- #include <sun/misc/Unsafe.h>
- #include <java/lang/System.h>
- #include <java/lang/InterruptedException.h>
- #include <java/lang/Thread.h>
- #include <java/lang/Long.h>
- #include "sysdep/locks.h"
- // Use a spinlock for multi-word accesses
- class spinlock
- {
- static volatile obj_addr_t lock;
- public:
- spinlock ()
- {
- while (! compare_and_swap (&lock, 0, 1))
- _Jv_ThreadYield ();
- }
- ~spinlock ()
- {
- release_set (&lock, 0);
- }
- };
-
- // This is a single lock that is used for all synchronized accesses if
- // the compiler can't generate inline compare-and-swap operations. In
- // most cases it'll never be used, but the i386 needs it for 64-bit
- // locked accesses and so does PPC32. It's worth building libgcj with
- // target=i486 (or above) to get the inlines.
- volatile obj_addr_t spinlock::lock;
- static inline bool
- compareAndSwap (volatile jint *addr, jint old, jint new_val)
- {
- jboolean result = false;
- spinlock lock;
- if ((result = (*addr == old)))
- *addr = new_val;
- return result;
- }
-
- static inline bool
- compareAndSwap (volatile jlong *addr, jlong old, jlong new_val)
- {
- jboolean result = false;
- spinlock lock;
- if ((result = (*addr == old)))
- *addr = new_val;
- return result;
- }
-
- static inline bool
- compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)
- {
- jboolean result = false;
- spinlock lock;
- if ((result = (*addr == old)))
- *addr = new_val;
- return result;
- }
-
- jlong
- sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *field)
- {
- _Jv_Field *fld = _Jv_FromReflectedField (field);
- // FIXME: what if it is not an instance field?
- return fld->getOffset();
- }
- jint
- sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass)
- {
- // FIXME: assert that arrayClass is array.
- jclass eltClass = arrayClass->getComponentType();
- return (jint)(jlong) _Jv_GetArrayElementFromElementType (NULL, eltClass);
- }
- jint
- sun::misc::Unsafe::arrayIndexScale (jclass arrayClass)
- {
- // FIXME: assert that arrayClass is array.
- jclass eltClass = arrayClass->getComponentType();
- if (eltClass->isPrimitive())
- return eltClass->size();
- return sizeof (void *);
- }
- // These methods are used when the compiler fails to generate inline
- // versions of the compare-and-swap primitives.
- jboolean
- sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,
- jint expect, jint update)
- {
- jint *addr = (jint *)((char *)obj + offset);
- return compareAndSwap (addr, expect, update);
- }
- jboolean
- sun::misc::Unsafe::compareAndSwapLong (jobject obj, jlong offset,
- jlong expect, jlong update)
- {
- volatile jlong *addr = (jlong*)((char *) obj + offset);
- return compareAndSwap (addr, expect, update);
- }
- jboolean
- sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,
- jobject expect, jobject update)
- {
- jobject *addr = (jobject*)((char *) obj + offset);
- return compareAndSwap (addr, expect, update);
- }
- void
- sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)
- {
- volatile jint *addr = (jint *) ((char *) obj + offset);
- *addr = value;
- }
- void
- sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)
- {
- volatile jlong *addr = (jlong *) ((char *) obj + offset);
- spinlock lock;
- *addr = value;
- }
- void
- sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)
- {
- volatile jobject *addr = (jobject *) ((char *) obj + offset);
- *addr = value;
- }
- void
- sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)
- {
- write_barrier ();
- volatile jint *addr = (jint *) ((char *) obj + offset);
- *addr = value;
- }
- void
- sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)
- {
- volatile jlong *addr = (jlong *) ((char *) obj + offset);
- spinlock lock;
- *addr = value;
- }
- void
- sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)
- {
- write_barrier ();
- volatile jobject *addr = (jobject *) ((char *) obj + offset);
- *addr = value;
- }
- #if 0 // FIXME
- void
- sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)
- {
- jint *addr = (jint *) ((char *) obj + offset);
- *addr = value;
- }
- #endif
- void
- sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)
- {
- jlong *addr = (jlong *) ((char *) obj + offset);
- spinlock lock;
- *addr = value;
- }
- void
- sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)
- {
- jobject *addr = (jobject *) ((char *) obj + offset);
- *addr = value;
- }
- jint
- sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)
- {
- volatile jint *addr = (jint *) ((char *) obj + offset);
- jint result = *addr;
- read_barrier ();
- return result;
- }
- jobject
- sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)
- {
- volatile jobject *addr = (jobject *) ((char *) obj + offset);
- jobject result = *addr;
- read_barrier ();
- return result;
- }
- jlong
- sun::misc::Unsafe::getLong (jobject obj, jlong offset)
- {
- jlong *addr = (jlong *) ((char *) obj + offset);
- spinlock lock;
- return *addr;
- }
- jlong
- sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)
- {
- volatile jlong *addr = (jlong *) ((char *) obj + offset);
- spinlock lock;
- return *addr;
- }
- void
- sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
- {
- natThread *nt = (natThread *) thread->data;
- nt->park_helper.unpark ();
- }
- void
- sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)
- {
- using namespace ::java::lang;
- Thread *thread = Thread::currentThread();
- natThread *nt = (natThread *) thread->data;
- nt->park_helper.park (isAbsolute, time);
- }
|