Add forgotten test case for r203059.
[official-gcc.git] / libjava / sun / misc / natUnsafe.cc
blob0bd2d21eac55740b2b7b35776193c66b6121b3ed
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
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))
35 _Jv_ThreadYield ();
37 ~spinlock ()
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;
51 static inline bool
52 compareAndSwap (volatile jint *addr, jint old, jint new_val)
54 jboolean result = false;
55 spinlock lock;
56 if ((result = (*addr == old)))
57 *addr = new_val;
58 return result;
61 static inline bool
62 compareAndSwap (volatile jlong *addr, jlong old, jlong new_val)
64 jboolean result = false;
65 spinlock lock;
66 if ((result = (*addr == old)))
67 *addr = new_val;
68 return result;
71 static inline bool
72 compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)
74 jboolean result = false;
75 spinlock lock;
76 if ((result = (*addr == old)))
77 *addr = new_val;
78 return result;
82 jlong
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();
90 jint
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);
98 jint
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.
111 jboolean
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);
119 jboolean
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);
127 jboolean
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);
135 void
136 sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)
138 volatile jint *addr = (jint *) ((char *) obj + offset);
139 *addr = value;
142 void
143 sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)
145 volatile jlong *addr = (jlong *) ((char *) obj + offset);
146 spinlock lock;
147 *addr = value;
150 void
151 sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)
153 volatile jobject *addr = (jobject *) ((char *) obj + offset);
154 *addr = value;
157 void
158 sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)
160 write_barrier ();
161 volatile jint *addr = (jint *) ((char *) obj + offset);
162 *addr = value;
165 void
166 sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)
168 volatile jlong *addr = (jlong *) ((char *) obj + offset);
169 spinlock lock;
170 *addr = value;
173 void
174 sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)
176 write_barrier ();
177 volatile jobject *addr = (jobject *) ((char *) obj + offset);
178 *addr = value;
181 #if 0 // FIXME
182 void
183 sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)
185 jint *addr = (jint *) ((char *) obj + offset);
186 *addr = value;
188 #endif
190 void
191 sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)
193 jlong *addr = (jlong *) ((char *) obj + offset);
194 spinlock lock;
195 *addr = value;
198 void
199 sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)
201 jobject *addr = (jobject *) ((char *) obj + offset);
202 *addr = value;
205 jint
206 sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)
208 volatile jint *addr = (jint *) ((char *) obj + offset);
209 jint result = *addr;
210 read_barrier ();
211 return result;
214 jobject
215 sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)
217 volatile jobject *addr = (jobject *) ((char *) obj + offset);
218 jobject result = *addr;
219 read_barrier ();
220 return result;
223 jlong
224 sun::misc::Unsafe::getLong (jobject obj, jlong offset)
226 jlong *addr = (jlong *) ((char *) obj + offset);
227 spinlock lock;
228 return *addr;
231 jlong
232 sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)
234 volatile jlong *addr = (jlong *) ((char *) obj + offset);
235 spinlock lock;
236 return *addr;
239 void
240 sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
242 natThread *nt = (natThread *) thread->data;
243 nt->park_helper.unpark ();
246 void
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);