SF.net SVN: jikesrvm:[14791] rvmroot/trunk

View: New views
1 Messages — Rating Filter:   Alert me  

SF.net SVN: jikesrvm:[14791] rvmroot/trunk

by captain5050 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Revision: 14791
          http://jikesrvm.svn.sourceforge.net/jikesrvm/?rev=14791&view=rev
Author:   captain5050
Date:     2008-07-24 20:24:53 +0000 (Thu, 24 Jul 2008)

Log Message:
-----------
RVM-598: increase use of unpreemptible, in particular thread yield and locking code should be unpreemptible as it can cause a context switch.

Modified Paths:
--------------
    rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Collection.java
    rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ReferenceProcessor.java
    rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java
    rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/gcspy/Util.java
    rvmroot/trunk/rvm/src/org/jikesrvm/Services.java
    rvmroot/trunk/rvm/src/org/jikesrvm/VM.java
    rvmroot/trunk/rvm/src/org/jikesrvm/adaptive/measurements/organizers/Organizer.java
    rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMType.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineExceptionDeliverer.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/CompiledMethod.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/ExceptionTable.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/HardwareTrapCompiledMethod.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptSaveVolatile.java
    rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ia32/OptExceptionDeliverer.java
    rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNICompiledMethod.java
    rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNIEnvironment.java
    rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java
    rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/Handshake.java
    rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java
    rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/JavaHeader.java
    rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/ObjectModel.java
    rvmroot/trunk/rvm/src/org/jikesrvm/runtime/ExceptionDeliverer.java
    rvmroot/trunk/rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Processor.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/RVMThread.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Scheduler.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/ThinLock.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenLock.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadEventWaitQueue.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java
    rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/Wait.java

Modified: rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Collection.java
===================================================================
--- rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Collection.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Collection.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -12,28 +12,29 @@
  */
 package org.jikesrvm.mm.mmtk;
 
-import org.mmtk.plan.Plan;
-import org.mmtk.plan.CollectorContext;
-import org.mmtk.plan.MutatorContext;
-import org.mmtk.utility.Finalizer;
-import org.mmtk.utility.options.Options;
-
+import org.jikesrvm.ArchitectureSpecific;
 import org.jikesrvm.VM;
+import org.jikesrvm.classloader.Atom;
+import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.compilers.common.CompiledMethod;
 import org.jikesrvm.compilers.common.CompiledMethods;
+import org.jikesrvm.mm.mminterface.Selected;
+import org.jikesrvm.mm.mminterface.CollectorThread;
 import org.jikesrvm.runtime.Magic;
 import org.jikesrvm.scheduler.Processor;
+import org.jikesrvm.scheduler.RVMThread;
 import org.jikesrvm.scheduler.Scheduler;
-import org.jikesrvm.scheduler.RVMThread;
-import org.jikesrvm.ArchitectureSpecific;
-import org.jikesrvm.classloader.Atom;
-import org.jikesrvm.classloader.RVMMethod;
-import org.jikesrvm.mm.mminterface.Selected;
-import org.jikesrvm.mm.mminterface.CollectorThread;
+import org.mmtk.plan.CollectorContext;
+import org.mmtk.plan.MutatorContext;
+import org.mmtk.plan.Plan;
+import org.mmtk.utility.Finalizer;
+import org.mmtk.utility.options.Options;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Interruptible;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.unboxed.Address;
 
-import org.vmmagic.unboxed.*;
-import org.vmmagic.pragma.*;
-
 @Uninterruptible
 public class Collection extends org.mmtk.vm.Collection implements org.mmtk.utility.Constants,
                                                                   org.jikesrvm.Constants {
@@ -73,7 +74,7 @@
    * @param why the reason why a collection was triggered.  0 to
    * <code>TRIGGER_REASONS - 1</code>.
    */
-  @LogicallyUninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public final void triggerCollection(int why) {
     triggerCollectionStatic(why);
   }
@@ -81,7 +82,7 @@
   /**
    * Joins a collection.
    */
-  @LogicallyUninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public final void joinCollection() {
     if (Options.verbose.getValue() >= 4) {
       VM.sysWriteln("Entered Collection.joinCollection().  Stack:");
@@ -101,7 +102,7 @@
    * @param why the reason why a collection was triggered.  0 to
    * <code>TRIGGER_REASONS - 1</code>.
    */
-  @LogicallyUninterruptible
+  @Unpreemptible("Change state of thread possibly context switching if generating exception")
   public static void triggerCollectionStatic(int why) {
     if (VM.VerifyAssertions) VM._assert((why >= 0) && (why < TRIGGER_REASONS));
 
@@ -135,7 +136,7 @@
    * Check if there is an out of memory error waiting.
    */
   @Inline
-  @LogicallyUninterruptible
+  @Unpreemptible("Exceptions may possibly cause yields")
   private static void checkForOutOfMemoryError(boolean afterCollection) {
     RVMThread myThread = Scheduler.getCurrentThread();
     OutOfMemoryError oome = myThread.getOutOfMemoryError();
@@ -193,6 +194,7 @@
    * Trigger an asynchronous collection, checking for memory
    * exhaustion first.
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public final void triggerAsyncCollection(int why) {
     Plan.setCollectionTriggered();
     if (Options.verbose.getValue() >= 1) {
@@ -313,6 +315,7 @@
    * true if yielded.
    */
   @Inline
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public boolean yieldpoint() {
     if (Processor.getCurrentProcessor().takeYieldpoint != 0) {
       RVMThread.yieldpointFromBackedge();

Modified: rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ReferenceProcessor.java
===================================================================
--- rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ReferenceProcessor.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ReferenceProcessor.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -53,7 +53,7 @@
    * Class fields
    */
 
-  private static Lock lock = new Lock("ReferenceProcessor");
+  private static final Lock lock = new Lock("ReferenceProcessor");
 
   private static final ReferenceProcessor softReferenceProcessor =
     new ReferenceProcessor(Semantics.SOFT);
@@ -202,6 +202,7 @@
    * @param ref The reference to add
    */
   @NoInline
+  @Unpreemptible("Non-preemptible but yield when table needs to be grown")
   private void addCandidate(Reference<?> ref, ObjectReference referent) {
     if (TRACE) {
       ObjectReference referenceAsAddress = ObjectReference.fromObject(ref);

Modified: rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java
===================================================================
--- rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -18,7 +18,8 @@
 
 import org.vmmagic.pragma.*;
 
-@Uninterruptible public final class Strings extends org.mmtk.vm.Strings {
+@Uninterruptible
+public final class Strings extends org.mmtk.vm.Strings {
   /**
    * Log a message.
    *
@@ -46,24 +47,28 @@
    * <b>TODO:</b> There are special memory management semantics here that
    * someone should document.
    *
-   * @param src the source string
+   * @param str the source string
    * @param dst the destination array
    * @param dstBegin the start offset in the desination array
    * @param dstEnd the index after the last character in the
    * destination to copy to
    * @return the number of characters copied.
    */
-  @LogicallyUninterruptible
-  public int copyStringToChars(String src, char [] dst,
+  public int copyStringToChars(String str, char [] dst,
                                      int dstBegin, int dstEnd) {
-    if (VM.runningVM)
+    if (VM.runningVM) {
       Processor.getCurrentProcessor().disableThreadSwitching("Disabled for MMTk string copy");
-    int len = src.length();
-    int n = (dstBegin + len <= dstEnd) ? len : (dstEnd - dstBegin);
-    for (int i = 0; i < n; i++)
-      Services.setArrayNoBarrier(dst, dstBegin + i, src.charAt(i));
-    if (VM.runningVM)
+    }
+    char[] str_backing = java.lang.JikesRVMSupport.getBackingCharArray(str);
+    int str_length = java.lang.JikesRVMSupport.getStringLength(str);
+    int str_offset = java.lang.JikesRVMSupport.getStringOffset(str);
+    int n = (dstBegin + str_length <= dstEnd) ? str_length : (dstEnd - dstBegin);
+    for (int i = 0; i < n; i++) {
+      Services.setArrayNoBarrier(dst, dstBegin + i, str_backing[str_offset+i]);
+    }
+    if (VM.runningVM) {
       Processor.getCurrentProcessor().enableThreadSwitching();
+    }
     return n;
   }
 }

Modified: rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/gcspy/Util.java
===================================================================
--- rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/gcspy/Util.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/gcspy/Util.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -19,7 +19,6 @@
 
 import org.jikesrvm.runtime.Magic;
 import static org.jikesrvm.runtime.SysCall.sysCall;
-import org.jikesrvm.scheduler.Synchronization;
 import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.objectmodel.ObjectModel;
 import org.jikesrvm.runtime.RuntimeEntrypoints;
@@ -32,8 +31,8 @@
  */
 @Uninterruptible public class Util extends org.mmtk.vm.gcspy.Util implements Constants {
   private static final boolean DEBUG_ = false;
-  private static final int LOG_BYTES_IN_WORD = LOG_BYTES_IN_INT;
-  private static final int BYTES_IN_WORD = 1 << LOG_BYTES_IN_WORD;
+  public static final int KILOBYTE = 1024;
+  public static final int MEGABYTE = 1024 * 1024;
 
   /**
    * Allocate an array of bytes with malloc
@@ -63,27 +62,6 @@
         sysCall.sysFree(addr);
   }
 
-
-  // From VM.java
-  @SuppressWarnings({"unused", "CanBeFinal", "UnusedDeclaration"}) // Accessed by native code
-  private static int sysWriteLock = 0;
-  private static Offset sysWriteLockOffset = Offset.max();
-
-  private static void swLock() {
-    if (org.jikesrvm.VM.BuildWithGCSpy) {
-      if (sysWriteLockOffset.isMax()) return;
-      while (!Synchronization.testAndSet(Magic.getJTOC(), sysWriteLockOffset, 1))
-        ;
-    }
-  }
-
-  private static void swUnlock() {
-    if (org.jikesrvm.VM.BuildWithGCSpy) {
-      if (sysWriteLockOffset.isMax()) return;
-      Synchronization.fetchAndStore(Magic.getJTOC(), sysWriteLockOffset, 0);
-    }
-  }
-
   /**
    * Convert a String to a 0-terminated array of bytes
    *
@@ -94,7 +72,7 @@
    * which are interruptible. We protect these calls with a
    * swLock/swUnlock mechanism, as per VM.sysWrite on String
    */
-  @LogicallyUninterruptible
+  @Unpreemptible
   public final Address getBytes(String str) {
     if (org.jikesrvm.VM.BuildWithGCSpy) {
       if (str == null)
@@ -106,36 +84,20 @@
 
       // Grab some memory sufficient to hold the null terminated string,
       // rounded up to an integral number of ints.
-      int len;
-      swLock();
-        len = str.length();
-      swUnlock();
-      int size = ((len >>> LOG_BYTES_IN_WORD) + 1) << LOG_BYTES_IN_WORD;
+      char[] str_backing = java.lang.JikesRVMSupport.getBackingCharArray(str);
+      int str_length = java.lang.JikesRVMSupport.getStringLength(str);
+      int str_offset = java.lang.JikesRVMSupport.getStringOffset(str);
+      int size = (str_length + 4) & -4;
       Address rtn = malloc(size);
 
-      // Write the string into it, one word at a time, being carefull about endianism
-      for (int w = 0; w <= (len >>> LOG_BYTES_IN_WORD); w++)  {
-        int value = 0;
-        int offset = w << LOG_BYTES_IN_WORD;
-        int shift = 0;
-        for (int b = 0; b < BYTES_IN_WORD; b++) {
-          byte byteVal = 0;
-          if (offset + b < len) {
-            swLock();
-              byteVal = (byte) str.charAt(offset + b);    // dodgy conversion!
-            swUnlock();
-          }
-          // Endianism matters
-          if (org.jikesrvm.VM.BuildForIA32) {
-            value = (byteVal << shift) | value;
-          } else {
-            org.jikesrvm.VM._assert(org.jikesrvm.VM.NOT_REACHED);
-            value = (value << shift) | byteVal; // not tested
-          }
-          shift += BITS_IN_BYTE;
-        }
-        rtn.store(value, Offset.fromIntSignExtend(offset));
+      // Write the string into it, one byte at a time (dodgy conversion)
+      for (int i=0; i < str_length; i++)  {
+        rtn.store((byte)str_backing[str_offset+i], Offset.fromIntSignExtend(i));
       }
+      // Zero rest of byte[]
+      for (int i=str_length; i < size; i++)  {
+        rtn.store((byte)0, Offset.fromIntSignExtend(i-str_offset));
+      }
       if (DEBUG_) {
         sysCall.sysWriteBytes(2/*SysTraceFd*/, rtn, size); Log.write("\n");
       }
@@ -145,9 +107,6 @@
     }
   }
 
-  public static final int KILOBYTE = 1024;
-  public static final int MEGABYTE = 1024 * 1024;
-
   /**
    * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
    *
@@ -223,4 +182,3 @@
       return 0;
   }
 }
-

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/Services.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/Services.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/Services.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -21,6 +21,8 @@
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.UninterruptibleNoWarn;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -434,4 +436,18 @@
     else
       return src[index];
   }
+
+  @Unpreemptible("Creates arrays possibly causes scheduling")
+  public static String stringConcatenator(String... args) {
+    String result="";
+    for (String s:args) {
+      result = stringConcatenate(result, s);
+    }
+    return result;
+  }
+
+  @UnpreemptibleNoWarn("Creates arrays possibly causes scheduling, no warning on call to string API")
+  public static String stringConcatenate(String a, String b) {
+    return a.concat(b);
+  }
 }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/VM.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/VM.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/VM.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -50,10 +50,11 @@
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Interruptible;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.UninterruptibleNoWarn;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.ObjectReference;
@@ -982,15 +983,22 @@
     }
   }
 
-  @LogicallyUninterruptible
   @NoInline
   /* don't waste code space inlining these --dave */
   public static void writeField(int fieldWidth, String s) {
     write(s);
-    int len = s.length();
+    int len = getStringLength(s);
     while (fieldWidth > len++) write(" ");
   }
 
+  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
+  private static int getStringLength(String s) {
+    if (VM.runningVM) {
+      return java.lang.JikesRVMSupport.getStringLength(s);
+    } else {
+      return s.length();
+    }
+  }
   /**
    * Low level print to console.
    * @param value       print value and left-fill with enough spaces to print at least fieldWidth characters
@@ -2158,8 +2166,8 @@
    * Exit virtual machine.
    * @param value  value to pass to host o/s
    */
-  @LogicallyUninterruptible /* TODO: This is completely wrong.  This method is very much Interruptible */
   @NoInline
+  @UnpreemptibleNoWarn
   public static void sysExit(int value) {
     handlePossibleRecursiveCallToSysExit();
     if (Options.stackTraceAtExit) {
@@ -2185,6 +2193,7 @@
    * Should only be called if the VM is running.
    * @param value  exit value
    */
+  @Uninterruptible
   public static void shutdown(int value) {
     handlePossibleRecursiveShutdown();
 
@@ -2381,7 +2390,7 @@
    * they are never called while gc is disabled.
    */
   @Inline
-  @Interruptible
+  @Unpreemptible("We may boost the size of the stack with GC disabled and may get preempted doing this")
   public static void disableGC() {
     disableGC(false);           // Recursion is not allowed in this context.
   }
@@ -2393,7 +2402,7 @@
    * enableGC().
    */
   @Inline
-  @Interruptible
+  @Unpreemptible("We may boost the size of the stack with GC disabled and may get preempted doing this")
   public static void disableGC(boolean recursiveOK) {
     // current (non-gc) thread is going to be holding raw addresses, therefore we must:
     //

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/adaptive/measurements/organizers/Organizer.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/adaptive/measurements/organizers/Organizer.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/adaptive/measurements/organizers/Organizer.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -18,6 +18,7 @@
 import org.jikesrvm.scheduler.greenthreads.GreenThreadQueue;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 
 /**
  * An Organizer acts an an intermediary between the low level
@@ -84,7 +85,7 @@
    * listener uses its own protocol to ensure that exactly 1
    * thread will attempt to activate the organizer.
    */
-  @Uninterruptible
+  @Unpreemptible
   private void passivate() {
     if (listener != null) {
       if (VM.VerifyAssertions) VM._assert(!listener.isActive());

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMType.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMType.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/classloader/RVMType.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -296,6 +296,18 @@
   }
 
   /**
+   * Instance of java.lang.Class corresponding to this type.
+   * This is commonly used for reflection.
+   */
+  @Uninterruptible
+  public final Class<?> getResolvedClassForType() {
+    // Resolve the class so that we don't need to resolve it
+    // in reflection code
+    if (VM.VerifyAssertions) VM._assert(VM.runningVM && isResolved());
+    return classForType;
+  }
+
+  /**
    * Get offset of tib slot from start of jtoc, in bytes.
    */
   @Uninterruptible

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -30,6 +30,7 @@
 import org.jikesrvm.runtime.StackBrowser;
 import org.vmmagic.pragma.SynchronizedObject;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -161,6 +162,7 @@
     return exceptionDeliverer;
   }
 
+  @Unpreemptible
   public int findCatchBlockForInstruction(Offset instructionOffset, RVMType exceptionType) {
     if (eTable == null) {
       return -1;
@@ -298,6 +300,7 @@
   }
 
   /** Get the lock acquisition offset */
+  @Uninterruptible
   public Offset getLockAcquisitionOffset() {
     return Offset.fromIntZeroExtend(lockOffset);
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -119,6 +119,7 @@
   /**
    * The last true local
    */
+  @Uninterruptible
   public static int getEmptyStackOffset(NormalMethod m) {
     return getFirstLocalOffset(m) - (m.getLocalWords() << LG_WORDSIZE) + WORDSIZE;
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineExceptionDeliverer.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineExceptionDeliverer.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineExceptionDeliverer.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -24,6 +24,7 @@
 import org.jikesrvm.scheduler.Processor;
 import org.jikesrvm.scheduler.Scheduler;
 import org.jikesrvm.scheduler.RVMThread;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
@@ -37,6 +38,7 @@
    * Pass control to a catch block.
    */
   @Override
+  @Unpreemptible("Deliver exception possibly from unpreemptible code")
   public void deliverException(CompiledMethod compiledMethod, Address catchBlockInstructionAddress,
                                Throwable exceptionObject, ArchitectureSpecific.Registers registers) {
     Address fp = registers.getInnermostFramePointer();
@@ -78,6 +80,7 @@
   /**
    * Unwind a stackframe.
    */
+  @Unpreemptible("Unwind stack possibly from unpreemptible code")
   public void unwindStackFrame(CompiledMethod compiledMethod, ArchitectureSpecific.Registers registers) {
     NormalMethod method = (NormalMethod) compiledMethod.getMethod();
     Address fp = registers.getInnermostFramePointer();
@@ -88,7 +91,7 @@
       if (instr.sGT(lockOffset)) { // we actually have the lock, so must unlock it.
         Object lock;
         if (method.isStatic()) {
-          lock = method.getDeclaringClass().getClassForType();
+          lock = method.getDeclaringClass().getResolvedClassForType();
         } else {
           lock =
               Magic.addressAsObject(fp.plus(BaselineCompilerImpl.locationToOffset(((BaselineCompiledMethod) compiledMethod).getGeneralLocalLocation(
@@ -107,5 +110,3 @@
     registers.unwindStackFrame();
   }
 }
-
-

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/CompiledMethod.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/CompiledMethod.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/CompiledMethod.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -27,6 +27,7 @@
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.SynchronizedObject;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
@@ -426,6 +427,7 @@
    * gc disabled when called by RuntimeEntrypoints.deliverException().
    * </ul>
    */
+  @Unpreemptible
   public abstract int findCatchBlockForInstruction(Offset instructionOffset, RVMType exceptionType);
 
   /**

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/ExceptionTable.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/ExceptionTable.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/ExceptionTable.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -17,6 +17,7 @@
 import org.jikesrvm.classloader.DynamicTypeCheck;
 import org.jikesrvm.classloader.RVMType;
 import org.jikesrvm.objectmodel.TIB;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -42,6 +43,7 @@
    * @param exceptionType the type of exception that was raised
    * @return the machine code offset of the catch block.
    */
+  @Unpreemptible
   public static int findCatchBlockForInstruction(int[] eTable, Offset instructionOffset, RVMType exceptionType) {
     for (int i = 0, n = eTable.length; i < n; i += 4) {
       // note that instructionOffset points to the instruction after the PEI

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/HardwareTrapCompiledMethod.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/HardwareTrapCompiledMethod.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/common/HardwareTrapCompiledMethod.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -20,6 +20,7 @@
 import org.jikesrvm.runtime.StackBrowser;
 import org.vmmagic.pragma.SynchronizedObject;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -52,6 +53,7 @@
     return null;
   }
 
+  @Unpreemptible
   public int findCatchBlockForInstruction(Offset instructionOffset, RVMType exceptionType) {
     return -1;
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -41,6 +41,7 @@
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.SynchronizedObject;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -84,7 +85,7 @@
   /**
    * Find "catch" block for a machine instruction of this method.
    */
-  @Interruptible
+  @Unpreemptible
   public int findCatchBlockForInstruction(Offset instructionOffset, RVMType exceptionType) {
     if (eTable == null) {
       return -1;

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptSaveVolatile.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptSaveVolatile.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptSaveVolatile.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -21,7 +21,7 @@
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.SaveVolatile;
-import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
@@ -37,7 +37,7 @@
  * @see org.jikesrvm.compilers.opt.driver.OptimizingCompiler (hooks to recognize & specially compile this class)
  */
 @SaveVolatile
-@Uninterruptible
+@Unpreemptible("Yield methods shouldn't be preempted")
 public class OptSaveVolatile {
 
   /**

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ia32/OptExceptionDeliverer.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ia32/OptExceptionDeliverer.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ia32/OptExceptionDeliverer.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -23,6 +23,7 @@
 import org.jikesrvm.scheduler.Processor;
 import org.jikesrvm.scheduler.Scheduler;
 import org.jikesrvm.scheduler.RVMThread;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
@@ -38,6 +39,7 @@
   /**
    * Pass control to a catch block.
    */
+  @Unpreemptible("Deliver exception possibly from unpreemptible code")
   public void deliverException(CompiledMethod compiledMethod, Address catchBlockInstructionAddress,
                                Throwable exceptionObject, Registers registers) {
     OptCompiledMethod optMethod = (OptCompiledMethod) compiledMethod;
@@ -116,6 +118,7 @@
   /**
    * Unwind a stackframe.
    */
+  @Unpreemptible("Unwind stack possibly from unpreemptible code")
   public void unwindStackFrame(CompiledMethod compiledMethod, Registers registers) {
     Address fp = registers.getInnermostFramePointer();
     OptCompiledMethod optMethod = (OptCompiledMethod) compiledMethod;
@@ -154,4 +157,3 @@
     }
   }
 }
-

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNICompiledMethod.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNICompiledMethod.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNICompiledMethod.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -21,6 +21,7 @@
 import org.jikesrvm.runtime.StackBrowser;
 import org.vmmagic.pragma.SynchronizedObject;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -67,6 +68,7 @@
     return false;
   }
 
+  @Unpreemptible
   public int findCatchBlockForInstruction(Offset instructionOffset, RVMType exceptionType) {
     return -1;
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNIEnvironment.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNIEnvironment.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/jni/JNIEnvironment.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -19,6 +19,7 @@
 import org.jikesrvm.scheduler.Processor;
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.pragma.Untraced;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.AddressArray;
@@ -27,7 +28,7 @@
 /**
  * A JNIEnvironment is created for each Java thread.
  */
-public class JNIEnvironment implements SizeConstants {
+public final class JNIEnvironment implements SizeConstants {
 
   /**
    * initial size for JNI refs, later grow as needed
@@ -179,6 +180,7 @@
    * terminating a thread that has a JNI environment allocated to it.
    * @param env the JNIEnvironment to deallocate
    */
+  @Unpreemptible("Deallocate environment but may contend with environment being allocated")
   public static synchronized void deallocateEnvironment(JNIEnvironment env) {
     env.next = pool;
     pool = env;
@@ -188,27 +190,27 @@
    * accessor methods
    */
   @Uninterruptible
-  public final boolean hasNativeStackFrame() {
+  public boolean hasNativeStackFrame() {
     return alwaysHasNativeFrame || JNIRefsTop != 0;
   }
 
   @Uninterruptible
-  public final Address topJavaFP() {
+  public Address topJavaFP() {
     return JNITopJavaFP;
   }
 
   @Uninterruptible
-  public final AddressArray refsArray() {
+  public AddressArray refsArray() {
     return JNIRefs;
   }
 
   @Uninterruptible
-  public final int refsTop() {
+  public int refsTop() {
     return JNIRefsTop;
   }
 
   @Uninterruptible
-  public final int savedRefsFP() {
+  public int savedRefsFP() {
     return JNIRefsSavedFP;
   }
 
@@ -219,7 +221,7 @@
    * @param ref the object to put on stack
    * @return offset of entry in JNIRefs stack
    */
-  public final int pushJNIRef(Object ref) {
+  public int pushJNIRef(Object ref) {
     if (ref == null) {
       return 0;
     }
@@ -252,7 +254,7 @@
    * @param offset in JNIRefs stack
    * @return reference at that offset
    */
-  public final Object getJNIRef(int offset) {
+  public Object getJNIRef(int offset) {
     if (offset > JNIRefsTop) {
       VM.sysWrite("JNI ERROR: getJNIRef for illegal offset > TOP, ");
       VM.sysWrite(offset);
@@ -272,7 +274,7 @@
    * Remove a reference from the JNIRefs stack.
    * @param offset in JNIRefs stack
    */
-  public final void deleteJNIRef(int offset) {
+  public void deleteJNIRef(int offset) {
     if (offset > JNIRefsTop) {
       VM.sysWrite("JNI ERROR: getJNIRef for illegal offset > TOP, ");
       VM.sysWrite(offset);
@@ -290,7 +292,7 @@
    * Dump the JNIRefs stack to the sysWrite stream
    */
   @Uninterruptible
-  public final void dumpJniRefsStack() {
+  public void dumpJniRefsStack() {
     int jniRefOffset = JNIRefsTop;
     VM.sysWrite("\n* * dump of JNIEnvironment JniRefs Stack * *\n");
     VM.sysWrite("* JNIRefs = ");
@@ -316,7 +318,7 @@
    * to the Java caller;  clear the exception by recording null
    * @param e  An exception or error
    */
-  public final void recordException(Throwable e) {
+  public void recordException(Throwable e) {
     // don't overwrite the first exception except to clear it
     if (pendingException == null || e == null) {
       pendingException = e;
@@ -326,7 +328,7 @@
   /**
    * @return the pending exception
    */
-  public final Throwable getException() {
+  public Throwable getException() {
     return pendingException;
   }
 

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -36,6 +36,7 @@
 import org.vmmagic.pragma.NoOptCompile;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
@@ -280,7 +281,7 @@
    *
    * @param handshake Handshake for the requested collection
    */
-  @Uninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void asyncCollect(Handshake handshake, int why) {
     handshake.requestAndContinue(why);
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/Handshake.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/Handshake.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/Handshake.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -20,6 +20,7 @@
 import org.jikesrvm.scheduler.greenthreads.GreenThread;
 import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 
 /**
  * Handshake handles mutator requests to initiate a collection, and
@@ -82,7 +83,7 @@
    * caller continues until it yields to the GC.  It may thus make
    * this call at an otherwise unsafe point.
    */
-  @Uninterruptible
+  @Unpreemptible("Change state of thread possibly context switching if generating exception")
   public void requestAndContinue(int why) {
     request(why);
   }
@@ -119,7 +120,7 @@
    * for the collection. They reside in the thread dispatch queues of their
    * processors, until the collector threads re-enable thread switching.
    */
-  @Uninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   private void initiateCollection() {
 
     /* check that scheduler initialization is complete */
@@ -174,7 +175,7 @@
    *
    * @return The number of GC threads.
    */
-  @Uninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   private int waitForPrecedingGC() {
     /*
      * Get the number of GC threads.  Include NativeDaemonProcessor
@@ -228,7 +229,7 @@
    *
    * @return true if the completion flag is not already set.
    */
-  @Uninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   private boolean request(int why) {
     lock.acquire();
     if (completionFlag) {
@@ -274,5 +275,3 @@
     lock.release();
   }
 }
-
-

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -55,6 +55,8 @@
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.Pure;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.ObjectReference;
@@ -669,7 +671,7 @@
    * See also: bytecode 0xbc ("newarray") and 0xbd ("anewarray")
    */
   @Inline
-  @Interruptible
+  @Unpreemptible
   public static Object allocateArray(int numElements, int logElementSize, int headerSize, TIB tib, int allocator,
                                      int align, int offset, int site) {
     int elemBytes = numElements << logElementSize;
@@ -688,7 +690,7 @@
    * so it can be forced out of line.
    */
   @NoInline
-  @Interruptible
+  @UnpreemptibleNoWarn
   private static void throwLargeArrayOutOfMemoryError() {
     throw new OutOfMemoryError();
   }
@@ -819,7 +821,7 @@
    * @return The stack
    */
   @Inline
-  @Interruptible
+  @Unpreemptible
   public static byte[] newStack(int bytes, boolean immortal) {
     if (!VM.runningVM) {
       return new byte[bytes];

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/JavaHeader.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/JavaHeader.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/JavaHeader.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -29,6 +29,7 @@
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.ObjectReference;
 import org.vmmagic.unboxed.Offset;
@@ -576,6 +577,7 @@
   /**
    * Generic lock
    */
+  @Unpreemptible("Become another thread when lock is contended, don't preempt in other cases")
   public static void genericLock(Object o) {
     ThinLock.lock(o, STATUS_OFFSET);
   }
@@ -583,6 +585,7 @@
   /**
    * Generic unlock
    */
+  @Unpreemptible("No interruption unless of exceptions")
   public static void genericUnlock(Object o) {
     ThinLock.unlock(o, STATUS_OFFSET);
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/ObjectModel.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/ObjectModel.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/objectmodel/ObjectModel.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -26,6 +26,7 @@
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.ObjectReference;
@@ -462,6 +463,7 @@
    * Generic lock
    */
   @Entrypoint
+  @Unpreemptible("Become another thread when lock is contended, don't preempt in other cases")
   public static void genericLock(Object o) {
     JavaHeader.genericLock(o);
   }
@@ -470,6 +472,7 @@
    * Generic unlock
    */
   @Entrypoint
+  @Unpreemptible("No preemption normally, but may raise exceptions")
   public static void genericUnlock(Object o) {
     JavaHeader.genericUnlock(o);
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/runtime/ExceptionDeliverer.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/runtime/ExceptionDeliverer.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/runtime/ExceptionDeliverer.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -14,6 +14,7 @@
 
 import org.jikesrvm.ArchitectureSpecific.Registers;
 import org.jikesrvm.compilers.common.CompiledMethod;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 
 /**
@@ -59,6 +60,7 @@
    * @param registers registers to be loaded before passing control to
    * catch block
    */
+  @Unpreemptible("Deliver exception possibly from unpreemptible code")
   public abstract void deliverException(CompiledMethod compiledMethod, Address catchBlockInstructionAddress,
                                         Throwable exceptionObject, Registers registers);
 
@@ -82,5 +84,6 @@
    * @param registers thread state to be updated by restoring non-volatiles
    *                  and unwinding the stackframe
    */
+  @Unpreemptible("Unwind stack possibly from unpreemptible code")
   public abstract void unwindStackFrame(CompiledMethod compiledMethod, Registers registers);
 }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -36,6 +36,8 @@
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.Pure;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
@@ -583,6 +585,7 @@
    */
   @NoInline
   @Entrypoint
+  @Unpreemptible("Deliver exception possibly from unpreemptible code")
   public static void athrow(Throwable exceptionObject) {
     RVMThread myThread = Scheduler.getCurrentThread();
     Registers exceptionRegisters = myThread.getExceptionRegisters();
@@ -923,6 +926,7 @@
    *  <li> <em> or </em> current thread is terminated if no catch block is found
    * </ul>
    */
+  @Unpreemptible("Deliver exception trying to avoid preemption")
   private static void deliverException(Throwable exceptionObject, Registers exceptionRegisters) {
     if (VM.TraceExceptionDelivery) {
       VM.sysWriteln("RuntimeEntrypoints.deliverException() entered; just got an exception object.");
@@ -966,11 +970,14 @@
       VM.sysWriteln("RuntimeEntrypoints.deliverException() found no catch block.");
     }
     /* No appropriate catch block found. */
+    handleUncaughtException(exceptionObject);
+  }
 
+  @UnpreemptibleNoWarn("Uncaught exception handling that may cause preemption")
+  private static void handleUncaughtException(Throwable exceptionObject) {
     Scheduler.getCurrentThread().handleUncaughtException(exceptionObject);
   }
 
-
   /**
    * Skip over all frames below currfp with saved code pointers outside of heap
    * (C frames), stopping at the native frame immediately preceding the glue
@@ -1030,6 +1037,7 @@
    *  invokers save/restore any nonvolatiles, so we're probably ok.
    *  --dave 6/29/01
    */
+  @Uninterruptible
   private static void unwindInvisibleStackFrame(Registers registers) {
     registers.unwindStackFrame();
   }

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Processor.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Processor.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Processor.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -22,6 +22,7 @@
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.pragma.Untraced;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
@@ -358,6 +359,7 @@
    * Note: This method is ONLY intended for use by Thread.
    * @param timerTick timer interrupted if true
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public abstract void dispatch(boolean timerTick);
 
   /**

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/RVMThread.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/RVMThread.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/RVMThread.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -38,11 +38,12 @@
 import org.vmmagic.pragma.BaselineSaveLSRegisters;
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Interruptible;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.NoOptCompile;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.pragma.Untraced;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
@@ -556,8 +557,8 @@
    * @param oldState the previous thread state
    * @param newState the new thread state
    */
-  @LogicallyUninterruptible
   @Entrypoint
+  @UnpreemptibleNoWarn("Change state of thread possibly context switching if generating exception")
   protected final void changeThreadState(State oldState, State newState) {
     if (trace) {
       VM.sysWrite("Thread.changeThreadState: thread=", threadSlot, name);
@@ -568,8 +569,15 @@
     if (state == oldState) {
       state = newState;
     } else {
-      throw new IllegalThreadStateException("Illegal thread state change from " +
-          oldState + " to " + newState + " when in state " + state + " in thread " + name);
+      throw new IllegalThreadStateException(
+          Services.stringConcatenator("Illegal thread state change from ",
+              java.lang.JikesRVMSupport.getEnumName(oldState),
+              " to ",
+              java.lang.JikesRVMSupport.getEnumName(newState),
+              " when in state ",
+              java.lang.JikesRVMSupport.getEnumName(state),
+              " in thread ",
+              name));
     }
   }
 
@@ -644,6 +652,7 @@
    * Update internal state of Thread and Scheduler to indicate that
    * a thread is about to start
    */
+  @Unpreemptible("Exceptions may possibly cause yields")
   public final void registerThread() {
     changeThreadState(State.NEW, State.RUNNABLE);
     registerThreadInternal();
@@ -801,6 +810,7 @@
   // OSR_BaselineExecStateExtractor.java, should then restore all non-volatiles before stack replacement
   //todo fix this -- related to SaveVolatile
   @Entrypoint
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yieldpointFromPrologue() {
     Address fp = Magic.getFramePointer();
     org.jikesrvm.scheduler.greenthreads.GreenThread.yieldpoint(PROLOGUE, fp);
@@ -816,6 +826,7 @@
   // OSR_BaselineExecStateExtractor.java, should then restore all non-volatiles before stack replacement
   // TODO fix this -- related to SaveVolatile
   @Entrypoint
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yieldpointFromBackedge() {
     Address fp = Magic.getFramePointer();
     org.jikesrvm.scheduler.greenthreads.GreenThread.yieldpoint(BACKEDGE, fp);
@@ -831,6 +842,7 @@
   // OSR_BaselineExecStateExtractor.java, should then restore all non-volatiles before stack replacement
   // TODO fix this -- related to SaveVolatile
   @Entrypoint
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yieldpointFromEpilogue() {
     Address fp = Magic.getFramePointer();
     org.jikesrvm.scheduler.greenthreads.GreenThread.yieldpoint(EPILOGUE, fp);
@@ -849,7 +861,7 @@
    * Suspend execution of current thread until it is resumed.
    * Call only if caller has appropriate security clearance.
    */
-  @LogicallyUninterruptible
+  @Unpreemptible("Exceptions may possibly cause yields")
   public final void suspend() {
     Throwable rethrow = null;
     changeThreadState(State.RUNNABLE, State.SUSPENDED);
@@ -967,8 +979,7 @@
    * @param o the object synchronized on
    * @param millis the number of milliseconds to wait for notification
    */
-  @LogicallyUninterruptible
-  /* only loses control at expected points -- I think -dave */
+  @Interruptible
   public static void wait(Object o, long millis) {
     if (STATS) timedWaitOperations++;
     RVMThread t = Scheduler.getCurrentThread();
@@ -992,15 +1003,16 @@
    */
   protected abstract void notifyAllInternal(Object o, Lock l);
 
-  @LogicallyUninterruptible
-  private static void raiseIllegalMonitorStateException(String msg, Object o) {
-    throw new IllegalMonitorStateException(msg + o);
+  @UnpreemptibleNoWarn("Possible context when generating exception")
+  public static void raiseIllegalMonitorStateException(String msg, Object o) {
+    throw new IllegalMonitorStateException(Services.stringConcatenate(msg, o.toString()));
   }
   /**
    * Support for Java {@link java.lang.Object#notify()} synchronization primitive.
    *
    * @param o the object synchronized on
    */
+  @Interruptible
   public static void notify(Object o) {
     if (STATS) notifyOperations++;
     Lock l = ObjectModel.getHeavyLock(o, false);
@@ -1018,6 +1030,7 @@
    * @param o the object synchronized on
    * @see java.lang.Object#notifyAll
    */
+  @Interruptible
   public static void notifyAll(Object o) {
     if (STATS) notifyAllOperations++;
     Scheduler.LockModel l = (Scheduler.LockModel)ObjectModel.getHeavyLock(o, false);
@@ -1041,7 +1054,6 @@
   /**
    * Deliver the throwable stopping/interrupting this thread
    */
-  @LogicallyUninterruptible
   public void kill(Throwable cause, boolean throwImmediately) {
     // yield() will notice the following and take appropriate action
     this.causeOfThreadDeath = cause;
@@ -1141,7 +1153,6 @@
   /**
    * Get this thread's index in {@link Scheduler#threads}[].
    */
-  @LogicallyUninterruptible
   public final int getIndex() {
     if (VM.VerifyAssertions) VM._assert((state == State.TERMINATED) || Scheduler.threads[threadSlot] == this);
     return threadSlot;
@@ -1163,7 +1174,7 @@
    * @param exceptionRegisters register state at which stack overflow trap
    * was encountered (null --> normal method call, not a trap)
    */
-  @Interruptible
+  @Unpreemptible
   public static void resizeCurrentStack(int newSize, Registers exceptionRegisters) {
     if (traceAdjustments) VM.sysWrite("Thread: resizeCurrentStack\n");
     if (MemoryManager.gcInProgress()) {
@@ -1560,18 +1571,22 @@
   /**
    * Throw the external interrupt associated with the thread now it is running
    */
-  @LogicallyUninterruptible
+  @Unpreemptible("Exceptions may possibly cause yields")
   protected final void postExternalInterrupt() {
     throwInterruptWhenScheduled = false;
     Throwable t = causeOfThreadDeath;
     causeOfThreadDeath = null;
     if (t instanceof InterruptedException  && t != proxyInterruptException) {
-      t.fillInStackTrace();
+      fillInStackTrace(t);
     }
     state = State.RUNNABLE;
     RuntimeEntrypoints.athrow(t);
   }
 
+  @UnpreemptibleNoWarn("Call out to API possibly losing control")
+  private static void fillInStackTrace(Throwable t) {
+    t.fillInStackTrace();
+  }
   /**
    * Was this thread interrupted?
    * @return whether the thread has been interrupted

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Scheduler.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Scheduler.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/Scheduler.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -32,9 +32,10 @@
 import org.jikesrvm.scheduler.greenthreads.GreenScheduler;
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Interruptible;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.UninterruptibleNoWarn;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
@@ -151,16 +152,9 @@
    * <b>Assumption:</b> call is guarded by threadCreationMutex.
    * @return the thread slot assigned this thread
    */
-  @LogicallyUninterruptible
   static int assignThreadSlot(RVMThread thread) {
     if (!VM.runningVM) {
-      // create primordial thread (in boot image)
-      int threadSlot = Scheduler.PRIMORDIAL_THREAD_INDEX;
-      Scheduler.threads[threadSlot] = (ThreadModel)thread;
-      // note that Scheduler.threadAllocationIndex (search hint)
-      // is out of date
-      Scheduler.numActiveThreads ++;
-      return PRIMORDIAL_THREAD_INDEX;
+      return bootImageAssignThreadSlot(thread);
     } else {
       Scheduler.threadCreationMutex.lock("thread creation mutex");
       for (int cnt = threads.length; --cnt >= 1;) {
@@ -197,6 +191,16 @@
     }
   }
 
+  @UninterruptibleNoWarn("Only called when writing the boot image")
+  private static int bootImageAssignThreadSlot(RVMThread thread) {
+    // create primordial thread (in boot image)
+    int threadSlot = Scheduler.PRIMORDIAL_THREAD_INDEX;
+    Scheduler.threads[threadSlot] = (ThreadModel)thread;
+    // note that Scheduler.threadAllocationIndex (search hint)
+    // is out of date
+    Scheduler.numActiveThreads ++;
+    return PRIMORDIAL_THREAD_INDEX;
+  }
     /**
      * Release this thread's threads[] slot.
      * Assumption: call is guarded by threadCreationMutex.
@@ -265,11 +269,13 @@
   /**
    * Schedule another thread
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected abstract void yieldInternal();
 
   /**
    * Schedule another thread
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yield() {
     getScheduler().yieldInternal();
   }
@@ -318,11 +324,9 @@
     getScheduler().bootInternal();
   }
   /** Scheduler specific sysExit shutdown */
-  @Interruptible
   protected abstract void sysExitInternal();
 
   /** Scheduler specific sysExit shutdown */
-  @Interruptible
   public static void sysExit() {
     getScheduler().sysExitInternal();
   }
@@ -657,19 +661,22 @@
   /**
    * Dump stack of calling thread, starting at callers frame
    */
-  @LogicallyUninterruptible
   public static void dumpStack() {
     if (VM.runningVM) {
       dumpStack(Magic.getFramePointer());
     } else {
-      StackTraceElement[] elements =
-        (new Throwable("--traceback from Jikes RVM's Scheduler class--")).getStackTrace();
-      for (StackTraceElement element: elements) {
-        System.err.println(element.toString());
-      }
+      bootImageDumpStack();
     }
   }
 
+  @UninterruptibleNoWarn("Only called when writing the boot image")
+  private static void bootImageDumpStack() {
+    StackTraceElement[] elements =
+      (new Throwable("--traceback from Jikes RVM's Scheduler class--")).getStackTrace();
+    for (StackTraceElement element: elements) {
+      System.err.println(element.toString());
+    }
+  }
   /**
    * Dump state of a (stopped) thread's stack.
    * @param fp address of starting frame. first frame output

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/ThinLock.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/ThinLock.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/ThinLock.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -20,9 +20,9 @@
 import org.jikesrvm.runtime.Magic;
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Inline;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
@@ -74,6 +74,7 @@
    */
   @Inline
   @Entrypoint
+  @Unpreemptible("Become another thread when lock is contended, don't preempt in other cases")
   static void inlineLock(Object o, Offset lockOffset) {
     Word old = Magic.prepareWord(o, lockOffset);
     if (old.rshl(TL_THREAD_ID_SHIFT).isZero()) {
@@ -100,6 +101,7 @@
    */
   @Inline
   @Entrypoint
+  @Unpreemptible("No preemption normally, but may raise exceptions")
   static void inlineUnlock(Object o, Offset lockOffset) {
     Word old = Magic.prepareWord(o, lockOffset);
     Word threadId = Word.fromIntZeroExtend(Processor.getCurrentProcessor().threadId);
@@ -121,6 +123,7 @@
    * @param lockOffset the offset of the thin lock word in the object.
    */
   @NoInline
+  @Unpreemptible("Become another thread when lock is contended, don't preempt in other cases")
   public static void lock(Object o, Offset lockOffset) {
     major:
     while (true) { // repeat only if attempt to lock a promoted lock fails
@@ -197,6 +200,7 @@
    * @param lockOffset the offset of the thin lock word in the object.
    */
   @NoInline
+  @Unpreemptible("No preemption normally, but may raise exceptions")
   public static void unlock(Object o, Offset lockOffset) {
     Magic.sync(); // prevents stale data from being seen by next owner of the lock
     while (true) { // spurious contention detected
@@ -212,7 +216,7 @@
         Scheduler.trace("Lock", "unlock error: thin lock word = ", old.toAddress());
         Scheduler.trace("Lock", "unlock error: thin lock word = ", Magic.objectAsAddress(o));
         // Scheduler.trace("Lock", Thread.getCurrentThread().toString(), 0);
-        raiseIllegalMonitorStateException("thin unlocking", o);
+        RVMThread.raiseIllegalMonitorStateException("thin unlocking", o);
       }
       if (old.and(TL_LOCK_COUNT_MASK).isZero()) { // get count, 0 is the last lock
         Word changed = old.and(TL_UNLOCK_MASK);
@@ -230,11 +234,6 @@
     }
   }
 
-  @LogicallyUninterruptible
-  private static void raiseIllegalMonitorStateException(String msg, Object o) {
-    throw new IllegalMonitorStateException(msg + o);
-  }
-
   ////////////////////////////////////////////////////////////////
   /// Support for inflating (and deflating) heavy-weight locks ///
   ////////////////////////////////////////////////////////////////

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenLock.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenLock.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenLock.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -19,8 +19,8 @@
 import org.jikesrvm.scheduler.Scheduler;
 import org.jikesrvm.scheduler.ThinLock;
 import org.jikesrvm.scheduler.RVMThread;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 @Uninterruptible
@@ -56,6 +56,7 @@
    * @return true, if the lock succeeds; false, otherwise
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public final boolean lockHeavy(Object o) {
     if (tentativeMicrolocking) {
       if (!mutex.tryLock()) {
@@ -103,7 +104,7 @@
     Processor mine = Processor.getCurrentProcessor();
     if (ownerId != mine.threadId) {
       mutex.unlock(); // thread-switching benign
-      raiseIllegalMonitorStateException("heavy unlocking", o);
+      RVMThread.raiseIllegalMonitorStateException("heavy unlocking", o);
     }
     recursionCount--;
     if (0 < recursionCount) {
@@ -149,11 +150,6 @@
     free(this);
   }
 
-  @LogicallyUninterruptible
-  private static void raiseIllegalMonitorStateException(String msg, Object o) {
-    throw new IllegalMonitorStateException(msg + o);
-  }
-
   /**
    * Is this lock blocking thread t?
    */

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -24,16 +24,16 @@
 import org.jikesrvm.scheduler.ProcessorLock;
 import org.jikesrvm.scheduler.Scheduler;
 import org.vmmagic.pragma.Inline;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Offset;
 
 /**
  * Multiplex execution of large number of Threads on small
  * number of o/s kernel threads.
  */
-@Uninterruptible
+@Uninterruptible("Default to uninterruptibility avoid unforeseen yieldpoints")
 @NonMoving
 public final class GreenProcessor extends Processor {
 
@@ -283,6 +283,7 @@
    * @param timerTick   timer interrupted if true
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public void dispatch(boolean timerTick) {
     // no processor locks should be held across a thread switch
     if (VM.VerifyAssertions) checkLockCount(0);
@@ -327,6 +328,7 @@
   /**
    * Handle a request from the garbage collector to flush the mutator context.
    */
+  @Unpreemptible("Explicitly schedule other threads, don't preempt at the same time")
   private void processMutatorFlushRequest() {
     GreenScheduler.flushMutatorContextsMutex.lock("handling flush request");
     /* One context per processor under green threads */
@@ -575,8 +577,7 @@
     return true;
   }
 
-  @LogicallyUninterruptible
-  /* GACK --dave */
+  @Unpreemptible
   public void dumpProcessorState() {
     VM.sysWrite("Processor ");
     VM.sysWriteInt(id);

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -36,6 +36,7 @@
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.UninterruptibleNoWarn;
+import org.vmmagic.pragma.Unpreemptible;
 
 /**
  * Global variables used to implement virtual machine thread scheduler.
@@ -386,6 +387,7 @@
    * @see org.jikesrvm.mm.mmtk.Collection
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected void requestMutatorFlushInternal() {
     flushMutatorContextsMutex.lock("requesting mutator flush");
     flushedMutatorCount = 0;
@@ -449,6 +451,7 @@
    * Dump state of virtual machine.
    */
   @Override
+  @Unpreemptible
   public void dumpVirtualMachineInternal() {
     GreenProcessor processor;
     VM.sysWrite("\n-- Processors --\n");
@@ -515,7 +518,7 @@
 
   /** Scheduler specific sysExit shutdown */
   @Override
-  @Interruptible
+  @Uninterruptible
   protected void sysExitInternal() {
     Wait.disableIoWait(); // we can't depend on thread switching being enabled
   }
@@ -620,11 +623,13 @@
    * Schedule another thread
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected void yieldInternal() {
     GreenThread.yield();
   }
 
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected void suspendDebuggerThreadInternal() {
     debugRequested = false;
     debuggerMutex.lock("debugger queue mutex");
@@ -635,6 +640,7 @@
    * Suspend a concurrent worker: it will resume when the garbage collector notifies.
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected void suspendConcurrentCollectorThreadInternal() {
     concurrentCollectorMutex.lock("suspend concurrent collector thread mutex");
     GreenScheduler.getCurrentThread().yield(concurrentCollectorQueue, concurrentCollectorMutex);
@@ -645,6 +651,7 @@
    * places objects on the finalizer queue and notifies.
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected void suspendFinalizerThreadInternal() {
     finalizerMutex.lock("suspend finalizer mutex");
     GreenScheduler.getCurrentThread().yield(finalizerQueue, finalizerMutex);
@@ -655,6 +662,7 @@
    * @param lock the lock to allow other thread chance to acquire
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected void yieldToOtherThreadWaitingOnLockInternal(Lock lock) {
     GreenLock l = (GreenLock)lock;
     GreenScheduler.getCurrentThread().yield(l.entering, l.mutex); // thread-switching benign

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -30,17 +30,17 @@
 import org.jikesrvm.scheduler.Synchronization;
 import org.jikesrvm.scheduler.RVMThread;
 import org.vmmagic.pragma.Interruptible;
-import org.vmmagic.pragma.LogicallyUninterruptible;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 
 /**
  * A green thread's Java execution context
  */
-@Uninterruptible
+@Uninterruptible("Default to uninterruptibility avoid unforeseen yieldpoints")
 @NonMoving
 public class GreenThread extends RVMThread {
   /** Offset of the lock field controlling the suspending of a thread */
@@ -167,6 +167,7 @@
    * Precondition: If the queue is global, caller must have the appropriate mutex.
    * @param q the ThreadQueue on which to enqueue this thread.
    */
+  @Interruptible
   public final void start(GreenThreadQueue q) {
     registerThread();
     q.enqueue(this);
@@ -179,6 +180,7 @@
    * Thread is blocked on a heavyweight lock
    * @see Lock#lockHeavy(Object)
    */
+  @Unpreemptible("Exceptions may possibly cause yields")
   public final void block(ThreadQueue entering, ProcessorLock mutex) {
     yield(entering, mutex);
   }
@@ -196,6 +198,7 @@
    * May result in threadswitch, depending on state of various control
    * flags on the processor object.
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yieldpoint(int whereFrom, Address yieldpointServiceMethodFP) {
     boolean threadSwitch = false;
     boolean cbsOverrun = false;
@@ -374,6 +377,7 @@
    *
    * @param whereFrom  backedge, prologue, epilogue?
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void timerTickYield(int whereFrom) {
     GreenThread myThread = GreenScheduler.getCurrentThread();
     // thread switch
@@ -387,6 +391,7 @@
    * Suspend execution of current thread, in favor of some other thread.
    */
   @NoInline
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yield() {
     GreenThread myThread = GreenScheduler.getCurrentThread();
     myThread.beingDispatched = true;
@@ -400,6 +405,7 @@
    * @param l lock guarding that queue (currently locked)
    */
   @NoInline
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public final void yield(AbstractThreadQueue q, ProcessorLock l) {
     if (VM.VerifyAssertions) VM._assert(this == GreenScheduler.getCurrentThread());
     if (state == State.RUNNABLE)
@@ -417,6 +423,7 @@
    * @param newState state to change to
    */
   @NoInline
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public final void yield(ProcessorLock l, State newState) {
     changeThreadState(State.RUNNABLE, newState);
     beingDispatched = true;
@@ -436,6 +443,7 @@
    * @param l2 the {@link ProcessorLock} guarding <code>q2</code> (currently locked)
    */
   @NoInline
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   private static void yield(ThreadProxyWaitingQueue q1, ProcessorLock l1,
       ThreadProxyWakeupQueue q2, ProcessorLock l2) {
     GreenThread myThread = GreenScheduler.getCurrentThread();
@@ -447,6 +455,7 @@
     morph(false);
   }
 
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   static void morph() {
     morph(false);
   }
@@ -455,7 +464,7 @@
    * Current thread has been placed onto some queue. Become another thread.
    * @param timerTick   timer interrupted if true
    */
-  @LogicallyUninterruptible
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   static void morph(boolean timerTick) {
     Magic.sync();  // to ensure beingDispatched flag written out to memory
     if (trace) Scheduler.trace("GreenThread", "morph ");
@@ -480,6 +489,7 @@
    * not guarded with a lock)
    */
   @NoInline
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void yield(AbstractThreadQueue q) {
     GreenThread myThread = GreenScheduler.getCurrentThread();
     myThread.beingDispatched = true;
@@ -507,6 +517,7 @@
    * Uninterruptible portion of going to sleep
    * @return were we interrupted prior to going to sleep
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   private boolean sleepImpl(ThreadProxy proxy) {
     if (isInterrupted()) {
       // we were interrupted before putting this thread to sleep
@@ -575,8 +586,9 @@
     return t;
   }
   /**
-   * Uninterruptible portion of waiting
+   * Unpreemptible portion of waiting
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   private Throwable waitImpl(Object o, GreenLock l, boolean hasTimeout, long millis, ThreadProxy proxy) {
     // Check thread isn't already in interrupted state
     if (isInterrupted()) {
@@ -688,6 +700,7 @@
    * @param waitData the wait data specifying the file descriptor(s)
    * to wait for.
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void ioWaitImpl(ThreadIOWaitData waitData) {
     GreenThread myThread = GreenScheduler.getCurrentThread();
     myThread.waitData = waitData;
@@ -702,6 +715,7 @@
    * @param process the <code>Process</code> object associated
    *    with the process
    */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public static void processWaitImpl(ThreadProcessWaitData waitData, VMProcess process) {
     GreenThread myThread = GreenScheduler.getCurrentThread();
     myThread.waitData = waitData;
@@ -725,6 +739,7 @@
    * Thread model dependent part of stopping/interrupting a thread
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected final void killInternal() {
     // remove this thread from wakeup and/or waiting queue
     ThreadProxy p = threadProxy;
@@ -747,6 +762,7 @@
    * Thread model dependent part of thread suspension
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   protected final void suspendInternal() {
     if(Synchronization.tryCompareAndSwap(this, suspendPendingOffset, 0, 1)) {
       // successful change from no suspend pending to suspend pending
@@ -755,6 +771,7 @@
     }
     if (this == GreenScheduler.getCurrentThread()) yield();
   }
+
   /**
    * Thread model dependent part of thread resumption
    */
@@ -791,6 +808,7 @@
    * Park the thread for OSR.
    */
   @Override
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public void osrPark() {
     osrParkLock.lock("locking in osrPark");
     if (osrParkingPermit) {
@@ -805,6 +823,7 @@
    * Unpark the thread from OSR.
    */
   @Override
+  @Unpreemptible("No preemption normally, but may raise exceptions")
   public void osrUnpark() {
     boolean schedule=false;
     osrParkLock.lock("locking in osrUnpark");

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadEventWaitQueue.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadEventWaitQueue.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadEventWaitQueue.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -17,6 +17,7 @@
 import org.jikesrvm.scheduler.RVMThread;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 
 /**
  * Queue of threads waiting for a specific kind of event to occur.
@@ -204,7 +205,7 @@
   /**
    * Dump state for debugging.
    */
-  @Interruptible
+  @Unpreemptible
   void dump() {
     dump(" ");
   }
@@ -212,7 +213,7 @@
   /**
    * Dump state for debugging.
    */
-  @Interruptible
+  @Unpreemptible
   void dump(String prefix) {
     VM.sysWrite(prefix);
     for (GreenThread t = head; t != null; t = t.getNext()) {
@@ -226,7 +227,7 @@
    * Dump description of what given thread is waiting for.
    * For debugging.
    */
-  @Interruptible
+  @Unpreemptible
   abstract void dumpWaitDescription(GreenThread thread);
 
   /**

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -17,6 +17,7 @@
 import org.jikesrvm.scheduler.ProcessorLock;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 
 /**
  * A list of threads waiting for i/o data to become available.
@@ -35,12 +36,6 @@
 public final class ThreadIOQueue extends ThreadEventWaitQueue
     implements ThreadEventConstants, ThreadIOConstants {
 
-  // Note: this class was modified by David Hovemeyer
-  // for Extreme Blue 2002 to implement it as a subclass of
-  // ThreadEventWaitQueue, as part of making a more general
-  // interface for event notification.  It also now supports
-  // waiting on sets of file descriptors.
-
   /**
    * Class to safely downcast from <code>ThreadEventWaitData</code>
    * to <code>ThreadIOWaitData</code>.
@@ -49,7 +44,7 @@
    * code.
    */
   @Uninterruptible
-  private static class WaitDataDowncaster extends ThreadEventWaitDataVisitor {
+  private static final class WaitDataDowncaster extends ThreadEventWaitDataVisitor {
 
     private ThreadIOWaitData waitData;
 
@@ -297,11 +292,14 @@
     }
   }
 
+  /** Downcaster for dumping */
+  private static final WaitDataDowncaster downcaster = new WaitDataDowncaster();
+
   /**
    * Dump text description of what given thread is waiting for.
    * For debugging.
    */
-  @Interruptible
+  @Unpreemptible
   @Override
   void dumpWaitDescription(GreenThread thread) {
     // Safe downcast from ThreadEventWaitData to ThreadIOWaitData.
@@ -309,9 +307,11 @@
     // locking (and thus execute concurrently with other methods), do NOT
     // use the queue's private downcaster object.  Instead, create one
     // from scratch.
-    WaitDataDowncaster downcaster = new WaitDataDowncaster();
-    thread.waitData.accept(downcaster);
-    ThreadIOWaitData waitData = downcaster.waitData;
+    ThreadIOWaitData waitData;
+    synchronized(downcaster) {
+      thread.waitData.accept(downcaster);
+      waitData = downcaster.waitData;
+    }
     if (VM.VerifyAssertions) VM._assert(waitData == thread.waitData);
 
     VM.sysWrite("(R");

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -18,6 +18,7 @@
 import org.jikesrvm.scheduler.ProcessorLock;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
 
 /**
  * A wait queue for threads that are waiting for a process
@@ -61,7 +62,7 @@
    * code.
    */
   @Uninterruptible
-  private static class WaitDataDowncaster extends ThreadEventWaitDataVisitor {
+  private static final class WaitDataDowncaster extends ThreadEventWaitDataVisitor {
 
     public ThreadProcessWaitData waitData;
 
@@ -229,11 +230,14 @@
     return ready;
   }
 
+  /** Downcaster for dumping */
+  private static final WaitDataDowncaster downcaster = new WaitDataDowncaster();
+
   /**
    * Dump text description of what given thread is waiting for.
    * For debugging.
    */
-  @Interruptible
+  @Unpreemptible
   @Override
   void dumpWaitDescription(GreenThread thread) {
     // Safe downcast from ThreadEventWaitData to ThreadProcessWaitData.
@@ -241,9 +245,11 @@
     // locking (and thus execute concurrently with other methods), do NOT
     // use the queue's private downcaster object.  Instead, create one
     // from scratch.
-    WaitDataDowncaster downcaster = new WaitDataDowncaster();
-    thread.waitData.accept(downcaster);
-    ThreadProcessWaitData waitData = downcaster.waitData;
+    ThreadProcessWaitData waitData;
+    synchronized(downcaster) {
+      thread.waitData.accept(downcaster);
+      waitData = downcaster.waitData;
+    }
     if (VM.VerifyAssertions) VM._assert(waitData == thread.waitData);
 
     VM.sysWrite("pid=", waitData.pid);

Modified: rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/Wait.java
===================================================================
--- rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/Wait.java 2008-07-24 20:20:47 UTC (rev 14790)
+++ rvmroot/trunk/rvm/src/org/jikesrvm/scheduler/greenthreads/Wait.java 2008-07-24 20:24:53 UTC (rev 14791)
@@ -15,6 +15,7 @@
 import org.jikesrvm.runtime.Time;
 import org.jikesrvm.scheduler.Processor;
 import org.jikesrvm.scheduler.Scheduler;
+import org.vmmagic.pragma.Uninterruptible;
 
 /**
  * A collection of static methods for waiting on some type of event.
@@ -31,6 +32,7 @@
    * The reason is that we can't be sure that thread switching
    * is possible during shutdown.
    */
+  @Uninterruptible
   public static void disableIoWait() {
     noIoWait = true;
   }


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Jikesrvm-commits mailing list
Jikesrvm-commits@...
https://lists.sourceforge.net/lists/listinfo/jikesrvm-commits