Opened 11 years ago

Closed 11 years ago

#345 closed defect (fixed)

THREADS:OBJECT-WAIT hangs for times less than or equal to 0.0001

Reported by: Mark Evenson Owned by:
Priority: major Milestone: 1.3.1
Component: interpreter Version: 1.3.0-dev
Keywords: threads has-test Cc:
Parent Tickets:

Description

[James Lawrence reports http://article.gmane.org/gmane.lisp.armedbear.devel/3077] that

(defun test ()
 (let ((object (cons nil nil)))
   (threads:synchronized-on object
     (threads:object-wait object 0.0001))))

For times between 0 and 0.0001 this appears to hang indefinitely. No
problem with times above 0.001.

The context is the new timeout option for bordeaux-threads:condition-wait,

https://github.com/sionescu/bordeaux-threads/blob/master/src/impl-abcl.lisp#L101

1.3.0-dev-svn-14623
Java_HotSpot(TM)_Server_VM-Oracle_Corporation-1.7.0_04-b20
i386-Linux-3.2.0-24-generic-pae

Change History (8)

comment:1 Changed 11 years ago by Mark Evenson

Erik suggests:

Index: LispThread.java
===================================================================
--- LispThread.java	(revision 14464)
+++ LispThread.java	(working copy)
@@ -1004,11 +1004,12 @@
     };
 
 
+  private static DoubleFloat factor1000 = new DoubleFloat(1000);
+
     public static final long javaSleepInterval(LispObject lispSleep)
-
     {
         double d =
-            checkDoubleFloat(lispSleep.multiplyBy(new DoubleFloat(1000))).getValue();
+            checkDoubleFloat(lispSleep.multiplyBy(factor1000)).getValue();
         if (d < 0)
             type_error(lispSleep, list(Symbol.REAL, Fixnum.ZERO));
 
@@ -1015,6 +1016,17 @@
         return (d < Long.MAX_VALUE ? (long) d : Long.MAX_VALUE);
     }
 
+    public static final int javaSleepNanos(LispObject lispSleep)
+    {
+        double d = // d contains millis
+            checkDoubleFloat(lispSleep.multiplyBy(factor1000)).getValue();
+        double n = d*1000000; // n contains nanos
+        d = 1.0e6*((long)d); // convert rounded millis to nanos
+        n = n - d; // retain nanos not in millis
+
+        return (n < Integer.MAX_VALUE ? (int) n : Integer.MAX_VALUE);
+    }
+
     @DocString(name="sleep", args="seconds",
     doc="Causes the invoking thread to sleep for SECONDS seconds.\n"+
         "SECONDS may be a value between 0 1and 1.")
@@ -1025,7 +1037,8 @@
         {
 
             try {
-                Thread.sleep(javaSleepInterval(arg));
+	      Thread.sleep(javaSleepInterval(arg),
+			   javaSleepNanos(arg));
             }
             catch (InterruptedException e) {
                 currentThread().processThreadInterrupts();
@@ -1208,7 +1221,8 @@
 
         {
             try {
-                object.lockableInstance().wait(javaSleepInterval(timeout));
+	      object.lockableInstance().wait(javaSleepInterval(timeout),
+					     javaSleepNanos(timeout));
             }
             catch (InterruptedException e) {
                 currentThread().processThreadInterrupts();

comment:2 Changed 11 years ago by Mark Evenson

The patch fixes time=0 and time=0.0001, but it still hangs with
time=0.000000001 and smaller positive values.

comment:3 Changed 11 years ago by Mark Evenson

Keywords: has-patch-partial added

comment:4 Changed 11 years ago by Mark Evenson

Keywords: has-patch-partial removed
Resolution: fixed
Status: newclosed

Resolved by r14632.

comment:5 Changed 11 years ago by Mark Evenson

Resolution: fixed
Status: closedreopened

comment:6 Changed 11 years ago by Mark Evenson

Resolution: fixed
Status: reopenedclosed

comment:7 Changed 11 years ago by Mark Evenson

Milestone: 1.3.01.3.1
Resolution: fixed
Status: closedreopened

Still problems of rounding sub-nano second intervals to zero.

Discussion onging on armedbear-devel@ about how best to fix with James Lawrence, currently leaning towards interpolating non-zero intervals of less than a nanosecond to mean a nanosecond.

comment:8 Changed 11 years ago by Mark Evenson

Resolution: fixed
Status: reopenedclosed
Note: See TracTickets for help on using tickets.