diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index da8704f72dc342431df005b382b87f26525dffbb..3c7ee13f1954a46301479656e8af8c148cef208f 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,13 @@
+2006-09-13  Geoffrey Keating  <geoffk@apple.com>
+
+	* posix.cc (_Jv_platform_nanotime): Return nanoseconds, not
+	microseconds; use gettimeofday when available.
+	* posix-threads.cc (_Jv_CondWait): Improve accuracy and range of
+	timeout calculation.
+	* testsuite/libjava.lang/Thread_Sleep_2.java: New.
+	* testsuite/libjava.lang/Thread_Sleep_2.out: New.
+	* testsuite/libjava.lang/Thread_Sleep_2.xfail: New.
+
 2006-09-12  Tom Tromey  <tromey@redhat.com>
 
 	PR java/29013:
diff --git a/libjava/posix-threads.cc b/libjava/posix-threads.cc
index 48501628ad01ca397e5408d036e5c00ee788c651..41937db6c52aa0e259f40238201841c928b54cae 100644
--- a/libjava/posix-threads.cc
+++ b/libjava/posix-threads.cc
@@ -96,16 +96,29 @@ _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
   if (millis > 0 || nanos > 0)
     {
       // Calculate the abstime corresponding to the timeout.
-      // Everything is in milliseconds.
-      //
-      // We use `unsigned long long' rather than jlong because our
-      // caller may pass up to Long.MAX_VALUE millis.  This would
-      // overflow the range of a jlong when added to the current time.
-      
-      unsigned long long startTime 
-	= (unsigned long long)java::lang::System::currentTimeMillis();
-      unsigned long long m = (unsigned long long)millis + startTime;
-      unsigned long long seconds = m / 1000; 
+      unsigned long long seconds;
+      unsigned long usec;
+
+      // For better accuracy, should use pthread_condattr_setclock
+      // and clock_gettime.
+#ifdef HAVE_GETTIMEOFDAY
+      timeval tv;
+      gettimeofday (&tv, NULL);
+      usec = tv.tv_usec;
+      seconds = tv.tv_sec;
+#else
+      unsigned long long startTime = java::lang::System::currentTimeMillis();
+      seconds = startTime / 1000;
+      /* Assume we're about half-way through this millisecond.  */
+      usec = (startTime % 1000) * 1000 + 500;
+#endif
+      /* These next two statements cannot overflow.  */
+      usec += nanos / 1000;
+      usec += (millis % 1000) * 1000;
+      /* These two statements could overflow only if tv.tv_sec was
+	 insanely large.  */
+      seconds += millis / 1000;
+      seconds += usec / 1000000;
 
       ts.tv_sec = seconds;
       if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds)
@@ -115,10 +128,8 @@ _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
           millis = nanos = 0;
         }
       else
-        {
-          m %= 1000;
-          ts.tv_nsec = m * 1000000 + (unsigned long long)nanos;
-        }
+	/* This next statement also cannot overflow.  */
+	ts.tv_nsec = (usec % 1000000) * 1000 + (nanos % 1000);
     }
 
   _Jv_Thread_t *current = _Jv_ThreadCurrentData ();
diff --git a/libjava/posix.cc b/libjava/posix.cc
index d191d8ea7a1c8303d66c98feae45a4faf7b4cb7b..df798b88a2b4a0d18b42b9ee5ad4a2286ee390bd 100644
--- a/libjava/posix.cc
+++ b/libjava/posix.cc
@@ -87,12 +87,20 @@ _Jv_platform_nanotime ()
   if (clock_gettime (id, &now) == 0)
     {
       jlong result = (jlong) now.tv_sec;
-      result = result * 1000 * 1000 + now.tv_nsec;
+      result = result * 1000000000LL + now.tv_nsec;
       return result;
     }
   // clock_gettime failed, but we can fall through.
 #endif // HAVE_CLOCK_GETTIME
-  return _Jv_platform_gettimeofday () * 1000LL;
+#if defined (HAVE_GETTIMEOFDAY)
+ {
+   timeval tv;
+   gettimeofday (&tv, NULL);
+   return (tv.tv_sec * 1000000000LL) + tv.tv_usec * 1000LL;
+ }
+#else
+  return _Jv_platform_gettimeofday () * 1000000LL;
+#endif
 }
 
 // Platform-specific VM initialization.
diff --git a/libjava/testsuite/libjava.lang/Thread_Sleep_2.java b/libjava/testsuite/libjava.lang/Thread_Sleep_2.java
new file mode 100644
index 0000000000000000000000000000000000000000..37c0d3bb6650c58c4dbf092b78ad9352952ec7ce
--- /dev/null
+++ b/libjava/testsuite/libjava.lang/Thread_Sleep_2.java
@@ -0,0 +1,34 @@
+// Test that Thread.sleep() is accurate
+// and that nanoTime actually measures in nanoseconds.
+
+public class Thread_Sleep_2
+{
+  public static void main(String args[])
+  {
+    try
+    {
+      boolean ok = true;
+      for (int i = 0; i < 100; i++)
+	{
+	  long start = System.nanoTime();
+	  Thread.sleep(10);
+	  long end = System.nanoTime();
+	  if ((end - start) < 10000000)
+	    {
+	      System.out.print ("failed, iteration ");
+	      System.out.print (i);
+	      System.out.print (", time ");
+	      System.out.print (end - start);
+	      System.out.println ("ns");
+	      ok = false;
+	    }
+	}
+      if (ok)
+	System.out.println ("ok");
+    }
+    catch (InterruptedException x)
+    {
+      System.out.println("error: Thread interrupted.");
+    }
+  }
+}
diff --git a/libjava/testsuite/libjava.lang/Thread_Sleep_2.out b/libjava/testsuite/libjava.lang/Thread_Sleep_2.out
new file mode 100644
index 0000000000000000000000000000000000000000..9766475a4185a151dc9d56d614ffb9aaea3bfd42
--- /dev/null
+++ b/libjava/testsuite/libjava.lang/Thread_Sleep_2.out
@@ -0,0 +1 @@
+ok
diff --git a/libjava/testsuite/libjava.lang/Thread_Sleep_2.xfail b/libjava/testsuite/libjava.lang/Thread_Sleep_2.xfail
new file mode 100644
index 0000000000000000000000000000000000000000..3f95317a45002fabbf1795b806f82f076eeb5760
--- /dev/null
+++ b/libjava/testsuite/libjava.lang/Thread_Sleep_2.xfail
@@ -0,0 +1 @@
+need-threads