posix.cc (_Jv_platform_nanotime): Return nanoseconds, not microseconds; use gettimeof...
authorGeoffrey Keating <geoffk@apple.com>
Thu, 14 Sep 2006 01:17:31 +0000 (01:17 +0000)
committerGeoffrey Keating <geoffk@gcc.gnu.org>
Thu, 14 Sep 2006 01:17:31 +0000 (01:17 +0000)
* 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.

From-SVN: r116941

libjava/ChangeLog
libjava/posix-threads.cc
libjava/posix.cc
libjava/testsuite/libjava.lang/Thread_Sleep_2.java [new file with mode: 0644]
libjava/testsuite/libjava.lang/Thread_Sleep_2.out [new file with mode: 0644]
libjava/testsuite/libjava.lang/Thread_Sleep_2.xfail [new file with mode: 0644]

index da8704f72dc342431df005b382b87f26525dffbb..3c7ee13f1954a46301479656e8af8c148cef208f 100644 (file)
@@ -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:
index 48501628ad01ca397e5408d036e5c00ee788c651..41937db6c52aa0e259f40238201841c928b54cae 100644 (file)
@@ -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 ();
index d191d8ea7a1c8303d66c98feae45a4faf7b4cb7b..df798b88a2b4a0d18b42b9ee5ad4a2286ee390bd 100644 (file)
@@ -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 (file)
index 0000000..37c0d3b
--- /dev/null
@@ -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 (file)
index 0000000..9766475
--- /dev/null
@@ -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 (file)
index 0000000..3f95317
--- /dev/null
@@ -0,0 +1 @@
+need-threads