OSDN Git Service

2008-02-06 Matthias Klose <doko@ubuntu.com>
[pf3gnuchains/gcc-fork.git] / libjava / sun / misc / natUnsafe.cc
1 // natUnsafe.cc - Implementation of sun.misc.Unsafe native methods.
2
3 /* Copyright (C) 2006
4    Free Software Foundation
5
6    This file is part of libgcj.
7
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10 details.  */
11
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>
19
20 #include <java/lang/Thread.h>
21 #include <java/lang/Long.h>
22
23 #include "sysdep/locks.h"
24
25 // Use a spinlock for multi-word accesses
26 class spinlock
27 {
28   static volatile obj_addr_t lock;
29
30 public:
31
32 spinlock ()
33   {
34     while (! compare_and_swap (&lock, 0, 1))
35       ;
36   }
37   ~spinlock ()
38   {
39     release_set (&lock, 0);
40   }
41 };
42   
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;
49
50
51 static inline bool
52 compareAndSwap (volatile jint *addr, jint old, jint new_val)
53 {
54   jboolean result = false;
55   spinlock lock;
56   if ((result = (*addr == old)))
57     *addr = new_val;
58   return result;
59 }
60   
61 static inline bool
62 compareAndSwap (volatile jlong *addr, jlong old, jlong new_val)
63 {
64   jboolean result = false;
65   spinlock lock;
66   if ((result = (*addr == old)))
67     *addr = new_val;
68   return result;
69 }
70   
71 static inline bool
72 compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)
73 {
74   jboolean result = false;
75   spinlock lock;
76   if ((result = (*addr == old)))
77     *addr = new_val;
78   return result;
79 }
80   
81
82 jlong
83 sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *field)
84 {
85   _Jv_Field *fld = _Jv_FromReflectedField (field);
86   // FIXME: what if it is not an instance field?
87   return fld->getOffset();
88 }
89
90 jint
91 sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass)
92 {
93   // FIXME: assert that arrayClass is array.
94   jclass eltClass = arrayClass->getComponentType();
95   return (jint)(jlong) _Jv_GetArrayElementFromElementType (NULL, eltClass);
96 }
97
98 jint
99 sun::misc::Unsafe::arrayIndexScale (jclass arrayClass)
100 {
101   // FIXME: assert that arrayClass is array.
102   jclass eltClass = arrayClass->getComponentType();
103   if (eltClass->isPrimitive())
104     return eltClass->size();
105   return sizeof (void *);
106 }
107
108 // These methods are used when the compiler fails to generate inline
109 // versions of the compare-and-swap primitives.
110
111 jboolean
112 sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,
113                                       jint expect, jint update)
114 {
115   jint *addr = (jint *)((char *)obj + offset);
116   return compareAndSwap (addr, expect, update);
117 }
118
119 jboolean
120 sun::misc::Unsafe::compareAndSwapLong (jobject obj, jlong offset,
121                                        jlong expect, jlong update)
122 {
123   volatile jlong *addr = (jlong*)((char *) obj + offset);
124   return compareAndSwap (addr, expect, update);
125 }
126
127 jboolean
128 sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,
129                                          jobject expect, jobject update)
130 {
131   jobject *addr = (jobject*)((char *) obj + offset);
132   return compareAndSwap (addr, expect, update);
133 }
134
135 void
136 sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)
137 {
138   volatile jint *addr = (jint *) ((char *) obj + offset);
139   *addr = value;
140 }
141
142 void
143 sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)
144 {
145   volatile jlong *addr = (jlong *) ((char *) obj + offset);
146   spinlock lock;
147   *addr = value;
148 }
149
150 void
151 sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)
152 {
153   volatile jobject *addr = (jobject *) ((char *) obj + offset);
154   *addr = value;
155 }
156
157 void
158 sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)
159 {
160   write_barrier ();
161   volatile jint *addr = (jint *) ((char *) obj + offset);
162   *addr = value;
163 }
164
165 void
166 sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)
167 {
168   volatile jlong *addr = (jlong *) ((char *) obj + offset);
169   spinlock lock;
170   *addr = value;
171 }
172
173 void
174 sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)
175 {
176   write_barrier ();
177   volatile jobject *addr = (jobject *) ((char *) obj + offset);
178   *addr = value;
179 }
180
181 #if 0  // FIXME
182 void
183 sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)
184 {
185   jint *addr = (jint *) ((char *) obj + offset);
186   *addr = value;
187 }
188 #endif
189
190 void
191 sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)
192 {
193   jlong *addr = (jlong *) ((char *) obj + offset);
194   spinlock lock;
195   *addr = value;
196 }
197
198 void
199 sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)
200 {
201   jobject *addr = (jobject *) ((char *) obj + offset);
202   *addr = value;
203 }
204
205 jint
206 sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)
207 {
208   volatile jint *addr = (jint *) ((char *) obj + offset);
209   jint result = *addr;
210   read_barrier ();
211   return result;
212 }
213
214 jobject
215 sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)
216 {
217   volatile jobject *addr = (jobject *) ((char *) obj + offset);
218   jobject result = *addr;
219   read_barrier ();
220   return result;
221 }
222
223 jlong
224 sun::misc::Unsafe::getLong (jobject obj, jlong offset)
225 {
226   jlong *addr = (jlong *) ((char *) obj + offset);
227   spinlock lock;
228   return *addr;
229 }
230
231 jlong
232 sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)
233 {
234   volatile jlong *addr = (jlong *) ((char *) obj + offset);
235   spinlock lock;
236   return *addr;
237 }
238
239 void
240 sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
241 {
242   natThread *nt = (natThread *) thread->data;
243   nt->park_helper.unpark ();
244 }
245
246 void
247 sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)
248 {
249   using namespace ::java::lang;
250   Thread *thread = Thread::currentThread();
251   natThread *nt = (natThread *) thread->data;
252   nt->park_helper.park (isAbsolute, time);
253 }