Implement java.util.concurrent support

Andrew Haley aph@redhat.com
Fri Sep 8 17:47:00 GMT 2006


This is still very much a work in progress, but it now works well
enought to pass almost all of the TCK, so I'm checking it in.

Some limitations:

1.  I use busy waiting on locks rather than proper locks.  This is
    obviously very inefficient...

2.  A few access checks are disabled because we don't have a working
    implementation of sun.reflect.Reflection.getCallerClass().

Andrew.


2006-09-08  Andrew Haley  <aph@redhat.com>

	* posix.cc (_Jv_platform_nanotime): Return nanoseconds, not
	microseconds.
	* sun/misc/natUnsafe.cc: Implement all methods.
	* sun/misc/Unsafe.java: Make class final.
	* java/lang/Thread.java (parkBlocker): new field.
	(parkPermit): Initialize to 1.
	* sun/misc/Unsafe.java: Make all of Class Unsafe final.

2006-09-08  Andrew Haley  <aph@redhat.com>

	* external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java: 
	(CASUpdater): Likewise.
	(LockedUpdater): Likewise.
	* external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java: 
	(AtomicReferenceFieldUpdaterImpl): Likewise.
	* external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java: 
	(AtomicIntegerFieldUpdaterImpl): Disable access checks.

Index: posix.cc
===================================================================
--- posix.cc	(revision 116678)
+++ posix.cc	(working copy)
@@ -82,12 +82,12 @@
   if (clock_gettime (id, &now) == 0)
     {
       jlong result = (jlong) now.tv_sec;
-      result = result * 1000 * 1000 + now.tv_nsec;
+      result = result * 1000 * 1000 * 1000 + now.tv_nsec;
       return result;
     }
   // clock_gettime failed, but we can fall through.
 #endif // HAVE_CLOCK_GETTIME
-  return _Jv_platform_gettimeofday () * 1000LL;
+  return _Jv_platform_gettimeofday () * 1000LL * 1000LL;
 }
 
 // Platform-specific VM initialization.
Index: java/lang/Thread.java
===================================================================
--- java/lang/Thread.java	(revision 116678)
+++ java/lang/Thread.java	(working copy)
@@ -150,6 +150,15 @@
   /** The uncaught exception handler.  */
   UncaughtExceptionHandler exceptionHandler;
 
+  /** This object is recorded while the thread is blocked to permit
+   * monitoring and diagnostic tools to identify the reasons that
+   * threads are blocked.
+   */
+  private Object parkBlocker;
+
+  /** Used by Unsafe.park and Unsafe.unpark.  */
+  int parkPermit = 1;
+
   // This describes the top-most interpreter frame for this thread.
   RawData interp_frame;
 
Index: classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
===================================================================
--- classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	(revision 116678)
+++ classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	(working copy)
@@ -244,11 +244,13 @@
 	    int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-		caller = sun.reflect.Reflection.getCallerClass(3);
+		// FIXME: gcj doesn't have sun.reflect.*
+
+// 		caller = sun.reflect.Reflection.getCallerClass(3);
 		modifiers = field.getModifiers();
-                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                    caller, tclass, null, modifiers); 
-		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+//                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+//                     caller, tclass, null, modifiers); 
+// 		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
             } catch(Exception ex) {
                 throw new RuntimeException(ex);
             }
Index: classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
===================================================================
--- classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	(revision 116678)
+++ classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	(working copy)
@@ -177,11 +177,13 @@
 	    int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-		caller = sun.reflect.Reflection.getCallerClass(3);
+		// FIXME: gcj doesn't have sun.reflect.*
+
+// 		caller = sun.reflect.Reflection.getCallerClass(3);
 		modifiers = field.getModifiers();
-                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                    caller, tclass, null, modifiers); 
-		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+//                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+//                     caller, tclass, null, modifiers); 
+// 		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                 fieldClass = field.getType();
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
Index: classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
===================================================================
--- classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	(revision 116678)
+++ classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	(working copy)
@@ -243,11 +243,13 @@
 	    int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-		caller = sun.reflect.Reflection.getCallerClass(3);
+		// FIXME: gcj doesn't have sun.reflect.*
+
+// 		caller = sun.reflect.Reflection.getCallerClass(3);
 		modifiers = field.getModifiers();
-                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                    caller, tclass, null, modifiers); 
-		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+//                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+//                     caller, tclass, null, modifiers); 
+// 		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
             } catch(Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -326,11 +328,13 @@
 	    int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-		caller = sun.reflect.Reflection.getCallerClass(3);
+		// FIXME: gcj doesn't have sun.reflect.*
+
+// 		caller = sun.reflect.Reflection.getCallerClass(3);
 		modifiers = field.getModifiers();
-                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                    caller, tclass, null, modifiers); 
-		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+//                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+//                     caller, tclass, null, modifiers); 
+// 		sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
             } catch(Exception ex) {
                 throw new RuntimeException(ex);
             }
Index: sun/misc/natUnsafe.cc
===================================================================
--- sun/misc/natUnsafe.cc	(revision 116678)
+++ sun/misc/natUnsafe.cc	(working copy)
@@ -1,145 +1,165 @@
-
-#include <config.h>
-
-#include <sun/misc/Unsafe.h>
 #include <gcj/cni.h>
-#include <java/lang/UnsupportedOperationException.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>
 
 jlong
-sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *)
+sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *field)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *) not implemented"));
+  _Jv_Field *fld = _Jv_FromReflectedField (field);
+  // FIXME: what if it is not an instance field?
+  return fld->getOffset();
 }
 
-
 jboolean
-sun::misc::Unsafe::compareAndSwapInt (::java::lang::Object *, jlong, jint, jint)
+sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,
+				      jint expect, jint update)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::compareAndSwapInt (::java::lang::Object *, jlong, jint, jint) not implemented"));
+  jint *addr = (jint *)((char *)obj + offset);
+  return __sync_bool_compare_and_swap (addr, expect, update);
 }
 
-
-jboolean
-sun::misc::Unsafe::compareAndSwapLong (::java::lang::Object *, jlong, jlong, jlong)
+jint
+sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::compareAndSwapLong (::java::lang::Object *, jlong, jlong, jlong) not implemented"));
+  // 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 *);
+}
 
 jboolean
-sun::misc::Unsafe::compareAndSwapObject (::java::lang::Object *, jlong, ::java::lang::Object *, ::java::lang::Object *)
+sun::misc::Unsafe::compareAndSwapLong (jobject obj, jlong offset,
+				       jlong expect, jlong update)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::compareAndSwapObject (::java::lang::Object *, jlong, ::java::lang::Object *, ::java::lang::Object *) not implemented"));
+  jlong *addr = (jlong*)((char *) obj + offset);
+  return __sync_bool_compare_and_swap (addr, expect, update);
 }
 
-
-void
-sun::misc::Unsafe::putOrderedInt (::java::lang::Object *, jlong, jint)
+jboolean
+sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,
+					 jobject expect, jobject update)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putOrderedInt (::java::lang::Object *, jlong, jint) not implemented"));
+  jobject *addr = (jobject*)((char *) obj + offset);
+  return __sync_bool_compare_and_swap (addr, expect, update);
 }
 
-
 void
-sun::misc::Unsafe::putOrderedLong (::java::lang::Object *, jlong, jlong)
+sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putOrderedLong (::java::lang::Object *, jlong, jlong) not implemented"));
+  jint *addr = (jint *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
 void
-sun::misc::Unsafe::putOrderedObject (::java::lang::Object *, jlong, ::java::lang::Object *)
+sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putOrderedObject (::java::lang::Object *, jlong, ::java::lang::Object *) not implemented"));
+  jlong *addr = (jlong *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
 void
-sun::misc::Unsafe::putIntVolatile (::java::lang::Object *, jlong, jint)
+sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putIntVolatile (::java::lang::Object *, jlong, jint) not implemented"));
+  jobject *addr = (jobject *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
-jint
-sun::misc::Unsafe::getIntVolatile (::java::lang::Object *, jlong)
+void
+sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::getIntVolatile (::java::lang::Object *, jlong) not implemented"));
+  jint *addr = (jint *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
 void
-sun::misc::Unsafe::putLongVolatile (::java::lang::Object *, jlong, jlong)
+sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putLongVolatile (::java::lang::Object *, jlong, jlong) not implemented"));
+  jlong *addr = (jlong *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
 void
-sun::misc::Unsafe::putLong (::java::lang::Object *, jlong, jlong)
+sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putLong (::java::lang::Object *, jlong, jlong) not implemented"));
+  jobject *addr = (jobject *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
-jlong
-sun::misc::Unsafe::getLongVolatile (::java::lang::Object *, jlong)
+#if 0  // FIXME
+void
+sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::getLongVolatile (::java::lang::Object *, jlong) not implemented"));
+  jint *addr = (jint *) ((char *) obj + offset);
+  *addr = value;
 }
+#endif
 
-
-jlong
-sun::misc::Unsafe::getLong (::java::lang::Object *, jlong)
+void
+sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::getLong (::java::lang::Object *, jlong) not implemented"));
+  jlong *addr = (jlong *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
 void
-sun::misc::Unsafe::putObjectVolatile (::java::lang::Object *, jlong, ::java::lang::Object *)
+sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putObjectVolatile (::java::lang::Object *, jlong, ::java::lang::Object *) not implemented"));
+  jobject *addr = (jobject *) ((char *) obj + offset);
+  *addr = value;
 }
 
-
-void
-sun::misc::Unsafe::putObject (::java::lang::Object *, jlong, ::java::lang::Object *)
+jint
+sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::putObject (::java::lang::Object *, jlong, ::java::lang::Object *) not implemented"));
+  jint *addr = (jint *) ((char *) obj + offset);
+  return *addr;
 }
 
-
-::java::lang::Object *
-sun::misc::Unsafe::getObjectVolatile (::java::lang::Object *, jlong)
+jobject
+sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::getObjectVolatile (::java::lang::Object *, jlong) not implemented"));
+  jobject *addr = (jobject *) ((char *) obj + offset);
+  return *addr;
 }
 
-
-jint
-sun::misc::Unsafe::arrayBaseOffset (::java::lang::Class *)
+jlong
+sun::misc::Unsafe::getLong (jobject obj, jlong offset)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::arrayBaseOffset (::java::lang::Class *) not implemented"));
+  jlong *addr = (jlong *) ((char *) obj + offset);
+  return *addr;
 }
 
-
-jint
-sun::misc::Unsafe::arrayIndexScale (::java::lang::Class *)
+jlong
+sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::arrayIndexScale (::java::lang::Class *) not implemented"));
+  jlong *addr = (jlong *) ((char *) obj + offset);
+  return *addr;
 }
 
-
 void
-sun::misc::Unsafe::unpark (::java::lang::Thread *)
+sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::unpark (::java::lang::Thread *) not implemented"));
+  return;
 }
 
-
 void
-sun::misc::Unsafe::park (jboolean, jlong)
+sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)
 {
-  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 ("sun::misc::Unsafe::park (jboolean, jlong) not implemented"));
+//   ::java::lang::Thread::yield ();
 }



More information about the Java-patches mailing list