--- /home/cpdev/src/classpath/java/lang/Thread.java	2005-07-02 21:03:34.000000000 +0000
+++ java/lang/Thread.java	2005-06-30 05:34:39.000000000 +0000
@@ -1,5 +1,5 @@
 /* Thread -- an independent thread of executable code
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation
 
 This file is part of GNU Classpath.
@@ -36,10 +36,11 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
+
 package java.lang;
 
-import java.util.Map;
-import java.util.WeakHashMap;
+import gnu.gcj.RawData;
+import gnu.gcj.RawDataManaged;
 
 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
  * "The Java Language Specification", ISBN 0-201-63451-1
@@ -99,44 +100,36 @@
   /** The maximum priority for a Thread. */
   public static final int MAX_PRIORITY = 10;
 
-  /** The underlying VM thread, only set when the thread is actually running.
-   */
-  volatile VMThread vmThread;
-
   /**
    * The group this thread belongs to. This is set to null by
    * ThreadGroup.removeThread when the thread dies.
    */
-  volatile ThreadGroup group;
+  ThreadGroup group;
 
   /** The object to run(), null if this is the target. */
-  final Runnable runnable;
+  private Runnable runnable;
 
   /** The thread name, non-null. */
-  volatile String name;
+  String name;
 
   /** Whether the thread is a daemon. */
-  volatile boolean daemon;
+  private boolean daemon;
 
   /** The thread priority, 1 to 10. */
-  volatile int priority;
-
-  /** Native thread stack size. 0 = use default */
-  private long stacksize;
+  private int priority;
 
-  /** Was the thread stopped before it was started? */
-  Throwable stillborn;
+  boolean interrupt_flag;
+  private boolean alive_flag;
+  private boolean startable_flag;
 
   /** The context classloader for this Thread. */
   private ClassLoader contextClassLoader;
 
-  /** The next thread number to use. */
-  private static int numAnonymousThreadsCreated;
+  // This describes the top-most interpreter frame for this thread.
+  RawData interp_frame;
 
-  /** Thread local storage. Package accessible for use by
-    * InheritableThreadLocal.
-    */
-  WeakHashMap locals;
+  // Our native data - points to an instance of struct natThread.
+  private RawDataManaged data;
 
   /**
    * Allocates a new <code>Thread</code> object. This constructor has
@@ -187,7 +180,7 @@
    */
   public Thread()
   {
-    this(null, (Runnable) null);
+    this(null, null, gen_name());
   }
 
   /**
@@ -203,7 +196,7 @@
    */
   public Thread(Runnable target)
   {
-    this(null, target);
+    this(null, target, gen_name());
   }
 
   /**
@@ -216,7 +209,7 @@
    */
   public Thread(String name)
   {
-    this(null, null, name, 0);
+    this(null, null, name);
   }
 
   /**
@@ -234,7 +227,7 @@
    */
   public Thread(ThreadGroup group, Runnable target)
   {
-    this(group, target, "Thread-" + ++numAnonymousThreadsCreated, 0);
+    this(group, target, gen_name());
   }
 
   /**
@@ -250,7 +243,7 @@
    */
   public Thread(ThreadGroup group, String name)
   {
-    this(group, null, name, 0);
+    this(group, null, name);
   }
 
   /**
@@ -264,7 +257,7 @@
    */
   public Thread(Runnable target, String name)
   {
-    this(null, target, name, 0);
+    this(null, target, name);
   }
 
   /**
@@ -298,7 +291,7 @@
    */
   public Thread(ThreadGroup group, Runnable target, String name)
   {
-    this(group, target, name, 0);
+    this(currentThread(), group, target, name);
   }
 
   /**
@@ -323,53 +316,59 @@
    */
   public Thread(ThreadGroup group, Runnable target, String name, long size)
   {
-    // Bypass System.getSecurityManager, for bootstrap efficiency.
-    SecurityManager sm = SecurityManager.current;
-    Thread current = currentThread();
-    if (group == null)
+    // Just ignore stackSize for now.
+    this(currentThread(), group, target, name);
+  }
+
+  private Thread (Thread current, ThreadGroup g, Runnable r, String n)
+  {
+    // Make sure the current thread may create a new thread.
+    checkAccess();
+    
+    // The Class Libraries book says ``threadName cannot be null''.  I
+    // take this to mean NullPointerException.
+    if (n == null)
+      throw new NullPointerException ();
+      
+    if (g == null)
       {
-	if (sm != null)
-	    group = sm.getThreadGroup();
-	if (group == null)
-	    group = current.group;
+	// If CURRENT is null, then we are bootstrapping the first thread. 
+	// Use ThreadGroup.root, the main threadgroup.
+	if (current == null)
+	  group = ThreadGroup.root;
+	else
+	  group = current.getThreadGroup();
       }
-    else if (sm != null)
-	sm.checkAccess(group);
+    else
+      group = g;
+      
+    data = null;
+    interrupt_flag = false;
+    alive_flag = false;
+    startable_flag = true;
 
-    this.group = group;
-    // Use toString hack to detect null.
-    this.name = name.toString();
-    this.runnable = target;
-    this.stacksize = size;
-
-    priority = current.priority;
-    daemon = current.daemon;
-    contextClassLoader = current.contextClassLoader;
+    if (current != null)
+      {
+	group.checkAccess();
 
+	daemon = current.isDaemon();
+        int gmax = group.getMaxPriority();
+	int pri = current.getPriority();
+	priority = (gmax < pri ? gmax : pri);
+	contextClassLoader = current.contextClassLoader;
+	InheritableThreadLocal.newChildThread(this);
+      }
+    else
+      {
+	daemon = false;
+	priority = NORM_PRIORITY;
+      }
+
+    name = n;
     group.addThread(this);
-    InheritableThreadLocal.newChildThread(this);
-  }
+    runnable = r;
 
-  /**
-   * Used by the VM to create thread objects for threads started outside
-   * of Java. Note: caller is responsible for adding the thread to
-   * a group and InheritableThreadLocal.
-   *
-   * @param vmThread the native thread
-   * @param name the thread name or null to use the default naming scheme
-   * @param priority current priority
-   * @param daemon is the thread a background thread?
-   */
-  Thread(VMThread vmThread, String name, int priority, boolean daemon)
-  {
-    this.vmThread = vmThread;
-    this.runnable = null;
-    if (name == null)
-	name = "Thread-" + ++numAnonymousThreadsCreated;
-    this.name = name;
-    this.priority = priority;
-    this.daemon = daemon;
-    this.contextClassLoader = ClassLoader.getSystemClassLoader();
+    initialize_native ();
   }
 
   /**
@@ -394,8 +393,7 @@
    */
   public final void checkAccess()
   {
-    // Bypass System.getSecurityManager, for bootstrap efficiency.
-    SecurityManager sm = SecurityManager.current;
+    SecurityManager sm = System.getSecurityManager();
     if (sm != null)
       sm.checkAccess(this);
   }
@@ -408,27 +406,14 @@
    * @throws IllegalThreadStateException if this Thread is not suspended
    * @deprecated pointless, since suspend is deprecated
    */
-  public int countStackFrames()
-  {
-    VMThread t = vmThread;
-    if (t == null || group == null)
-	throw new IllegalThreadStateException();
-
-    return t.countStackFrames();
-  }
+  public native int countStackFrames();
 
   /**
-   * Get the currently executing Thread. In the situation that the
-   * currently running thread was created by native code and doesn't
-   * have an associated Thread object yet, a new Thread object is
-   * constructed and associated with the native thread.
+   * Get the currently executing Thread.
    *
    * @return the currently executing Thread
    */
-  public static Thread currentThread()
-  {
-    return VMThread.currentThread();
-  }
+  public static native Thread currentThread();
 
   /**
    * Originally intended to destroy this thread, this method was never
@@ -447,7 +432,7 @@
    */
   public static void dumpStack()
   {
-    new Throwable().printStackTrace();
+    (new Exception("Stack trace")).printStackTrace();
   }
 
   /**
@@ -476,8 +461,7 @@
    */
   public final String getName()
   {
-    VMThread t = vmThread;
-    return t == null ? name : t.getName();
+    return name;
   }
 
   /**
@@ -485,10 +469,9 @@
    *
    * @return the Thread's priority
    */
-  public final synchronized int getPriority()
+  public final int getPriority()
   {
-    VMThread t = vmThread;
-    return t == null ? priority : t.getPriority();
+    return priority;
   }
 
   /**
@@ -511,10 +494,7 @@
    * @throws NullPointerException if obj is null
    * @since 1.4
    */
-  public static boolean holdsLock(Object obj)
-  {
-    return VMThread.holdsLock(obj);
-  }
+  public static native boolean holdsLock(Object obj);
 
   /**
    * Interrupt this Thread. First, there is a security check,
@@ -538,13 +518,7 @@
    *
    * @throws SecurityException if you cannot modify this Thread
    */
-  public synchronized void interrupt()
-  {
-    checkAccess();
-    VMThread t = vmThread;
-    if (t != null)
-	t.interrupt();
-  }
+  public native void interrupt();
 
   /**
    * Determine whether the current Thread has been interrupted, and clear
@@ -555,7 +529,7 @@
    */
   public static boolean interrupted()
   {
-    return VMThread.interrupted();
+    return currentThread().isInterrupted(true);
   }
 
   /**
@@ -567,8 +541,7 @@
    */
   public boolean isInterrupted()
   {
-    VMThread t = vmThread;
-    return t != null && t.isInterrupted();
+    return interrupt_flag;
   }
 
   /**
@@ -577,9 +550,9 @@
    *
    * @return whether this Thread is alive
    */
-  public final boolean isAlive()
+  public final synchronized boolean isAlive()
   {
-    return vmThread != null && group != null;
+    return alive_flag;
   }
 
   /**
@@ -590,8 +563,7 @@
    */
   public final boolean isDaemon()
   {
-    VMThread t = vmThread;
-    return t == null ? daemon : t.isDaemon();
+    return daemon;
   }
 
   /**
@@ -631,33 +603,41 @@
    * @throws InterruptedException if the Thread is interrupted; it's
    *         <i>interrupted status</i> will be cleared
    * @throws IllegalArgumentException if ns is invalid
+   * @XXX A ThreadListener would be nice, to make this efficient.
    */
-  public final void join(long ms, int ns) throws InterruptedException
-  {
-    if(ms < 0 || ns < 0 || ns > 999999)
-	throw new IllegalArgumentException();
-
-    VMThread t = vmThread;
-    if(t != null)
-        t.join(ms, ns);
-  }
+  public final native void join(long ms, int ns)
+    throws InterruptedException;
 
   /**
-   * Resume this Thread.  If the thread is not suspended, this method does
-   * nothing. To mirror suspend(), there may be a security check:
-   * <code>checkAccess</code>.
+   * Resume a suspended thread.
    *
    * @throws SecurityException if you cannot resume the Thread
    * @see #checkAccess()
    * @see #suspend()
    * @deprecated pointless, since suspend is deprecated
    */
-  public final synchronized void resume()
+  public final native void resume();
+
+  private final native void finish_();
+
+  /**
+   * Determine whether the given Thread has been interrupted, but leave
+   * the <i>interrupted status</i> alone in the process.
+   *
+   * @return whether the current Thread has been interrupted
+   * @see #interrupted()
+   */
+  private boolean isInterrupted(boolean clear_flag)
   {
-    checkAccess();
-    VMThread t = vmThread;
-    if (t != null)
-	t.resume();
+    boolean r = interrupt_flag;
+    if (clear_flag && r)
+      {
+	// Only clear the flag if we saw it as set. Otherwise this could 
+	// potentially cause us to miss an interrupt in a race condition, 
+	// because this method is not synchronized.
+	interrupt_flag = false;
+      }
+    return r;
   }
   
   /**
@@ -685,9 +665,9 @@
    * @see #isDaemon()
    * @see #checkAccess()
    */
-  public final synchronized void setDaemon(boolean daemon)
+  public final void setDaemon(boolean daemon)
   {
-    if (vmThread != null)
+    if (!startable_flag)
       throw new IllegalThreadStateException();
     checkAccess();
     this.daemon = daemon;
@@ -709,11 +689,27 @@
    */
   public synchronized ClassLoader getContextClassLoader()
   {
-    // Bypass System.getSecurityManager, for bootstrap efficiency.
-    SecurityManager sm = SecurityManager.current;
-    if (sm != null)
-      // XXX Don't check this if the caller's class loader is an ancestor.
-      sm.checkPermission(new RuntimePermission("getClassLoader"));
+    if (contextClassLoader == null)
+      contextClassLoader = ClassLoader.getSystemClassLoader();
+
+    SecurityManager sm = System.getSecurityManager();
+    // FIXME: we can't currently find the caller's class loader.
+    ClassLoader callers = null;
+    if (sm != null && callers != null)
+      {
+	// See if the caller's class loader is the same as or an
+	// ancestor of this thread's class loader.
+	while (callers != null && callers != contextClassLoader)
+	  {
+	    // FIXME: should use some internal version of getParent
+	    // that avoids security checks.
+	    callers = callers.getParent();
+	  }
+
+	if (callers != contextClassLoader)
+	  sm.checkPermission(new RuntimePermission("getClassLoader"));
+      }
+
     return contextClassLoader;
   }
 
@@ -731,7 +727,7 @@
    */
   public synchronized void setContextClassLoader(ClassLoader classloader)
   {
-    SecurityManager sm = SecurityManager.current;
+    SecurityManager sm = System.getSecurityManager();
     if (sm != null)
       sm.checkPermission(new RuntimePermission("setContextClassLoader"));
     this.contextClassLoader = classloader;
@@ -745,30 +741,21 @@
    * @throws NullPointerException if name is null
    * @throws SecurityException if you cannot modify this Thread
    */
-  public final synchronized void setName(String name)
+  public final void setName(String name)
   {
     checkAccess();
     // The Class Libraries book says ``threadName cannot be null''.  I
     // take this to mean NullPointerException.
     if (name == null)
       throw new NullPointerException();
-    VMThread t = vmThread;
-    if (t != null)
-	t.setName(name);
-    else
-	this.name = name;
+    this.name = name;
   }
 
   /**
-   * Yield to another thread. The Thread will not lose any locks it holds
-   * during this time. There are no guarantees which thread will be
-   * next to run, and it could even be this one, but most VMs will choose
-   * the highest priority thread that has been waiting longest.
+   * Causes the currently executing thread object to temporarily pause
+   * and allow other threads to execute.
    */
-  public static void yield()
-  {
-    VMThread.yield();
-  }
+  public static native void yield();
 
   /**
    * Suspend the current Thread's execution for the specified amount of
@@ -776,11 +763,11 @@
    * are no guarantees which thread will be next to run, but most VMs will
    * choose the highest priority thread that has been waiting longest.
    *
-   * @param ms the number of milliseconds to sleep.
-   * @throws InterruptedException if the Thread is (or was) interrupted;
-   *         it's <i>interrupted status</i> will be cleared
-   * @throws IllegalArgumentException if ms is negative
-   * @see #interrupt()
+   * @param ms the number of milliseconds to sleep, or 0 for forever
+   * @throws InterruptedException if the Thread is interrupted; it's
+   *         <i>interrupted status</i> will be cleared
+   * @see #notify()
+   * @see #wait(long)
    */
   public static void sleep(long ms) throws InterruptedException
   {
@@ -792,32 +779,23 @@
    * time. The Thread will not lose any locks it has during this time. There
    * are no guarantees which thread will be next to run, but most VMs will
    * choose the highest priority thread that has been waiting longest.
-   * <p>
-   * Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs
-   * do not offer that fine a grain of timing resolution. When ms is
-   * zero and ns is non-zero the Thread will sleep for at least one
-   * milli second. There is no guarantee that this thread can start up
-   * immediately when time expires, because some other thread may be
-   * active.  So don't expect real-time performance.
    *
-   * @param ms the number of milliseconds to sleep
+   * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
+   * not offer that fine a grain of timing resolution. Besides, there is
+   * no guarantee that this thread can start up immediately when time expires,
+   * because some other thread may be active.  So don't expect real-time
+   * performance.
+   *
+   * @param ms the number of milliseconds to sleep, or 0 for forever
    * @param ns the number of extra nanoseconds to sleep (0-999999)
-   * @throws InterruptedException if the Thread is (or was) interrupted;
-   *         it's <i>interrupted status</i> will be cleared
-   * @throws IllegalArgumentException if ms or ns is negative
-   *         or ns is larger than 999999.
-   * @see #interrupt()
+   * @throws InterruptedException if the Thread is interrupted; it's
+   *         <i>interrupted status</i> will be cleared
+   * @throws IllegalArgumentException if ns is invalid
+   * @see #notify()
+   * @see #wait(long, int)
    */
-  public static void sleep(long ms, int ns) throws InterruptedException
-  {
-
-    // Check parameters
-    if (ms < 0 || ns < 0 || ns > 999999)
-      throw new IllegalArgumentException();
-
-    // Really sleep
-    VMThread.sleep(ms, ns);
-  }
+  public static native void sleep(long timeout, int nanos)
+    throws InterruptedException;
 
   /**
    * Start this Thread, calling the run() method of the Runnable this Thread
@@ -829,14 +807,8 @@
    * @throws IllegalThreadStateException if the thread has already started
    * @see #run()
    */
-  public synchronized void start()
-  {
-    if (vmThread != null || group == null)
-	throw new IllegalThreadStateException();
+  public native void start();
 
-    VMThread.create(this, stacksize);
-  }
-  
   /**
    * Cause this Thread to stop abnormally because of the throw of a ThreadDeath
    * error. If you stop a Thread that has not yet started, it will stop
@@ -862,16 +834,17 @@
    */
   public final void stop()
   {
-    stop(new ThreadDeath());
+    // Argument doesn't matter, because this is no longer
+    // supported.
+    stop(null);
   }
 
   /**
    * Cause this Thread to stop abnormally and throw the specified exception.
-   * If you stop a Thread that has not yet started, the stop is ignored
-   * (contrary to what the JDK documentation says).
-   * <b>WARNING</b>This bypasses Java security, and can throw a checked
-   * exception which the call stack is unprepared to handle. Do not abuse
-   * this power.
+   * If you stop a Thread that has not yet started, it will stop immediately
+   * when it is actually started. <b>WARNING</b>This bypasses Java security,
+   * and can throw a checked exception which the call stack is unprepared to
+   * handle. Do not abuse this power.
    *
    * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
    * leave data in bad states.  Hence, there is a security check:
@@ -893,24 +866,7 @@
    * @see SecurityManager#checkPermission(Permission)
    * @deprecated unsafe operation, try not to use
    */
-  public final synchronized void stop(Throwable t)
-  {
-    if (t == null)
-      throw new NullPointerException();
-    // Bypass System.getSecurityManager, for bootstrap efficiency.
-    SecurityManager sm = SecurityManager.current;
-    if (sm != null)
-      {
-        sm.checkAccess(this);
-        if (this != currentThread())
-          sm.checkPermission(new RuntimePermission("stopThread"));
-      }
-    VMThread vt = vmThread;
-    if (vt != null)
-	vt.stop(t);
-    else
-	stillborn = t;
-  }
+  public final native void stop(Throwable t);
 
   /**
    * Suspend this Thread.  It will not come back, ever, unless it is resumed.
@@ -924,13 +880,7 @@
    * @see #resume()
    * @deprecated unsafe operation, try not to use
    */
-  public final synchronized void suspend()
-  {
-    checkAccess();
-    VMThread t = vmThread;
-    if (t != null)
-	t.suspend();
-  }
+  public final native void suspend();
 
   /**
    * Set this Thread's priority. There may be a security check,
@@ -947,19 +897,7 @@
    * @see #MIN_PRIORITY
    * @see #MAX_PRIORITY
    */
-  public final synchronized void setPriority(int priority)
-  {
-    checkAccess();
-    if (priority < MIN_PRIORITY || priority > MAX_PRIORITY)
-      throw new IllegalArgumentException("Invalid thread priority value "
-                                         + priority + ".");
-    priority = Math.min(priority, group.getMaxPriority());
-    VMThread t = vmThread;
-    if (t != null)
-	t.setPriority(priority);
-    else
-	this.priority = priority;
-  }
+  public final native void setPriority(int newPriority);
 
   /**
    * Returns a string representation of this thread, including the
@@ -973,27 +911,7 @@
 	    + (group == null ? "" : group.getName()) + "]");
   }
 
-  /**
-   * Clean up code, called by VMThread when thread dies.
-   */
-  synchronized void die()
-  {
-    group.removeThread(this);
-    vmThread = null;
-    locals = null;
-  }
+  private final native void initialize_native();
 
-  /**
-   * Returns the map used by ThreadLocal to store the thread local values.
-   */
-  static Map getThreadLocals()
-  {
-    Thread thread = currentThread();
-    Map locals = thread.locals;
-    if (locals == null)
-      {
-        locals = thread.locals = new WeakHashMap();
-      }
-    return locals;
-  }
+  private final native static String gen_name();
 }
