Merged gcj-eclipse branch to trunk.
[official-gcc.git] / libjava / sun / misc / natUnsafe.cc
blob7aa422e58dc63312fcecb31d8c2efd648cbce9b0
1 // natUnsafe.cc - Implementation of sun.misc.Unsafe native methods.
3 /* Copyright (C) 2006
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
10 details. */
12 #include <gcj/cni.h>
13 #include <gcj/field.h>
14 #include <gcj/javaprims.h>
15 #include <jvm.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
26 class spinlock
28 static volatile obj_addr_t lock;
30 public:
32 spinlock ()
34 while (! compare_and_swap (&lock, 0, 1));
36 ~spinlock ()
38 release_set (&lock, 0);
42 // This is a single lock that is used for all synchronized accesses if
43 // the compiler can't generate inline compare-and-swap operations. In
44 // most cases it'll never be used, but the i386 needs it for 64-bit
45 // locked accesses and so does PPC32. It's worth building libgcj with
46 // target=i486 (or above) to get the inlines.
47 volatile obj_addr_t spinlock::lock;
50 static inline bool
51 compareAndSwap (volatile jint *addr, jint old, jint new_val)
53 jboolean result = false;
54 spinlock lock;
55 if ((result = (*addr == old)))
56 *addr = new_val;
57 return result;
60 static inline bool
61 compareAndSwap (volatile jlong *addr, jlong old, jlong new_val)
63 jboolean result = false;
64 spinlock lock;
65 if ((result = (*addr == old)))
66 *addr = new_val;
67 return result;
70 static inline bool
71 compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)
73 jboolean result = false;
74 spinlock lock;
75 if ((result = (*addr == old)))
76 *addr = new_val;
77 return result;
81 jlong
82 sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *field)
84 _Jv_Field *fld = _Jv_FromReflectedField (field);
85 // FIXME: what if it is not an instance field?
86 return fld->getOffset();
89 jint
90 sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass)
92 // FIXME: assert that arrayClass is array.
93 jclass eltClass = arrayClass->getComponentType();
94 return (jint)(jlong) _Jv_GetArrayElementFromElementType (NULL, eltClass);
97 jint
98 sun::misc::Unsafe::arrayIndexScale (jclass arrayClass)
100 // FIXME: assert that arrayClass is array.
101 jclass eltClass = arrayClass->getComponentType();
102 if (eltClass->isPrimitive())
103 return eltClass->size();
104 return sizeof (void *);
107 // These methods are used when the compiler fails to generate inline
108 // versions of the compare-and-swap primitives.
110 jboolean
111 sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,
112 jint expect, jint update)
114 jint *addr = (jint *)((char *)obj + offset);
115 return compareAndSwap (addr, expect, update);
118 jboolean
119 sun::misc::Unsafe::compareAndSwapLong (jobject obj, jlong offset,
120 jlong expect, jlong update)
122 volatile jlong *addr = (jlong*)((char *) obj + offset);
123 return compareAndSwap (addr, expect, update);
126 jboolean
127 sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,
128 jobject expect, jobject update)
130 jobject *addr = (jobject*)((char *) obj + offset);
131 return compareAndSwap (addr, expect, update);
134 void
135 sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)
137 volatile jint *addr = (jint *) ((char *) obj + offset);
138 *addr = value;
141 void
142 sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)
144 volatile jlong *addr = (jlong *) ((char *) obj + offset);
145 spinlock lock;
146 *addr = value;
149 void
150 sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)
152 volatile jobject *addr = (jobject *) ((char *) obj + offset);
153 *addr = value;
156 void
157 sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)
159 write_barrier ();
160 volatile jint *addr = (jint *) ((char *) obj + offset);
161 *addr = value;
164 void
165 sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)
167 volatile jlong *addr = (jlong *) ((char *) obj + offset);
168 spinlock lock;
169 *addr = value;
172 void
173 sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)
175 write_barrier ();
176 volatile jobject *addr = (jobject *) ((char *) obj + offset);
177 *addr = value;
180 #if 0 // FIXME
181 void
182 sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)
184 jint *addr = (jint *) ((char *) obj + offset);
185 *addr = value;
187 #endif
189 void
190 sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)
192 jlong *addr = (jlong *) ((char *) obj + offset);
193 spinlock lock;
194 *addr = value;
197 void
198 sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)
200 jobject *addr = (jobject *) ((char *) obj + offset);
201 *addr = value;
204 jint
205 sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)
207 volatile jint *addr = (jint *) ((char *) obj + offset);
208 jint result = *addr;
209 read_barrier ();
210 return result;
213 jobject
214 sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)
216 volatile jobject *addr = (jobject *) ((char *) obj + offset);
217 jobject result = *addr;
218 read_barrier ();
219 return result;
222 jlong
223 sun::misc::Unsafe::getLong (jobject obj, jlong offset)
225 jlong *addr = (jlong *) ((char *) obj + offset);
226 spinlock lock;
227 return *addr;
230 jlong
231 sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)
233 volatile jlong *addr = (jlong *) ((char *) obj + offset);
234 spinlock lock;
235 return *addr;
238 void
239 sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
241 natThread *nt = (natThread *) thread->data;
242 nt->park_helper.unpark ();
245 void
246 sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)
248 using namespace ::java::lang;
249 Thread *thread = Thread::currentThread();
250 natThread *nt = (natThread *) thread->data;
251 nt->park_helper.park (isAbsolute, time);