1 // natUnsafe.cc - Implementation of sun.misc.Unsafe native methods.
3 /* Copyright (C) 2006, 2007
4 Free Software Foundation
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 #include <gcj/field.h>
14 #include <gcj/javaprims.h>
16 #include <sun/misc/Unsafe.h>
17 #include <java/lang/System.h>
18 #include <java/lang/InterruptedException.h>
20 #include <java/lang/Thread.h>
21 #include <java/lang/Long.h>
23 #include "sysdep/locks.h"
25 // Use a spinlock for multi-word accesses
28 static volatile obj_addr_t lock
;
34 while (! compare_and_swap (&lock
, 0, 1))
39 release_set (&lock
, 0);
43 // This is a single lock that is used for all synchronized accesses if
44 // the compiler can't generate inline compare-and-swap operations. In
45 // most cases it'll never be used, but the i386 needs it for 64-bit
46 // locked accesses and so does PPC32. It's worth building libgcj with
47 // target=i486 (or above) to get the inlines.
48 volatile obj_addr_t
spinlock::lock
;
52 compareAndSwap (volatile jint
*addr
, jint old
, jint new_val
)
54 jboolean result
= false;
56 if ((result
= (*addr
== old
)))
62 compareAndSwap (volatile jlong
*addr
, jlong old
, jlong new_val
)
64 jboolean result
= false;
66 if ((result
= (*addr
== old
)))
72 compareAndSwap (volatile jobject
*addr
, jobject old
, jobject new_val
)
74 jboolean result
= false;
76 if ((result
= (*addr
== old
)))
83 sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field
*field
)
85 _Jv_Field
*fld
= _Jv_FromReflectedField (field
);
86 // FIXME: what if it is not an instance field?
87 return fld
->getOffset();
91 sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass
)
93 // FIXME: assert that arrayClass is array.
94 jclass eltClass
= arrayClass
->getComponentType();
95 return (jint
)(jlong
) _Jv_GetArrayElementFromElementType (NULL
, eltClass
);
99 sun::misc::Unsafe::arrayIndexScale (jclass arrayClass
)
101 // FIXME: assert that arrayClass is array.
102 jclass eltClass
= arrayClass
->getComponentType();
103 if (eltClass
->isPrimitive())
104 return eltClass
->size();
105 return sizeof (void *);
108 // These methods are used when the compiler fails to generate inline
109 // versions of the compare-and-swap primitives.
112 sun::misc::Unsafe::compareAndSwapInt (jobject obj
, jlong offset
,
113 jint expect
, jint update
)
115 jint
*addr
= (jint
*)((char *)obj
+ offset
);
116 return compareAndSwap (addr
, expect
, update
);
120 sun::misc::Unsafe::compareAndSwapLong (jobject obj
, jlong offset
,
121 jlong expect
, jlong update
)
123 volatile jlong
*addr
= (jlong
*)((char *) obj
+ offset
);
124 return compareAndSwap (addr
, expect
, update
);
128 sun::misc::Unsafe::compareAndSwapObject (jobject obj
, jlong offset
,
129 jobject expect
, jobject update
)
131 jobject
*addr
= (jobject
*)((char *) obj
+ offset
);
132 return compareAndSwap (addr
, expect
, update
);
136 sun::misc::Unsafe::putOrderedInt (jobject obj
, jlong offset
, jint value
)
138 volatile jint
*addr
= (jint
*) ((char *) obj
+ offset
);
143 sun::misc::Unsafe::putOrderedLong (jobject obj
, jlong offset
, jlong value
)
145 volatile jlong
*addr
= (jlong
*) ((char *) obj
+ offset
);
151 sun::misc::Unsafe::putOrderedObject (jobject obj
, jlong offset
, jobject value
)
153 volatile jobject
*addr
= (jobject
*) ((char *) obj
+ offset
);
158 sun::misc::Unsafe::putIntVolatile (jobject obj
, jlong offset
, jint value
)
161 volatile jint
*addr
= (jint
*) ((char *) obj
+ offset
);
166 sun::misc::Unsafe::putLongVolatile (jobject obj
, jlong offset
, jlong value
)
168 volatile jlong
*addr
= (jlong
*) ((char *) obj
+ offset
);
174 sun::misc::Unsafe::putObjectVolatile (jobject obj
, jlong offset
, jobject value
)
177 volatile jobject
*addr
= (jobject
*) ((char *) obj
+ offset
);
183 sun::misc::Unsafe::putInt (jobject obj
, jlong offset
, jint value
)
185 jint
*addr
= (jint
*) ((char *) obj
+ offset
);
191 sun::misc::Unsafe::putLong (jobject obj
, jlong offset
, jlong value
)
193 jlong
*addr
= (jlong
*) ((char *) obj
+ offset
);
199 sun::misc::Unsafe::putObject (jobject obj
, jlong offset
, jobject value
)
201 jobject
*addr
= (jobject
*) ((char *) obj
+ offset
);
206 sun::misc::Unsafe::getIntVolatile (jobject obj
, jlong offset
)
208 volatile jint
*addr
= (jint
*) ((char *) obj
+ offset
);
215 sun::misc::Unsafe::getObjectVolatile (jobject obj
, jlong offset
)
217 volatile jobject
*addr
= (jobject
*) ((char *) obj
+ offset
);
218 jobject result
= *addr
;
224 sun::misc::Unsafe::getLong (jobject obj
, jlong offset
)
226 jlong
*addr
= (jlong
*) ((char *) obj
+ offset
);
232 sun::misc::Unsafe::getLongVolatile (jobject obj
, jlong offset
)
234 volatile jlong
*addr
= (jlong
*) ((char *) obj
+ offset
);
240 sun::misc::Unsafe::unpark (::java::lang::Thread
*thread
)
242 natThread
*nt
= (natThread
*) thread
->data
;
243 nt
->park_helper
.unpark ();
247 sun::misc::Unsafe::park (jboolean isAbsolute
, jlong time
)
249 using namespace ::java::lang
;
250 Thread
*thread
= Thread::currentThread();
251 natThread
*nt
= (natThread
*) thread
->data
;
252 nt
->park_helper
.park (isAbsolute
, time
);