2010-04-09 Gonzalo Paniagua Javier <gonzalo@novell.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 9 Apr 2010 04:36:39 +0000 (04:36 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 9 Apr 2010 04:36:39 +0000 (04:36 -0000)
* mono-semaphore.c: account for the time already spent in wait if
interrupted.

svn path=/trunk/mono/; revision=155121

mono/utils/ChangeLog
mono/utils/mono-semaphore.c

index 7f2c4a93fdb93893bb61749d9b58c13c7614f4b6..72f1abb737188b4a0e177d0897139e34c6eee990 100644 (file)
@@ -1,3 +1,8 @@
+2010-04-09 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+       * mono-semaphore.c: account for the time already spent in wait if
+       interrupted.
+
 2010-04-09  Zoltan Varga  <vargaz@gmail.com>
 
        * mono-time.c (get_boot_time): Applied more openbsd changes from Robert Nagy
index 58c4fc9f9e63544070fa6bfc88048a6eb7fda6fc..755166b00551eb9b4210cc668cca68b9da7d1f94 100644 (file)
@@ -30,6 +30,7 @@
 #    define WAIT_BLOCK(a,b) sem_timedwait (a, b)
 #  endif
 
+#define NSEC_PER_SEC 1000000000
 int
 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
 {
@@ -50,8 +51,8 @@ mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
        gettimeofday (&t, NULL);
        ts.tv_sec = timeout_ms / 1000 + t.tv_sec;
        ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000;
-       while (ts.tv_nsec > 1000000000) {
-               ts.tv_nsec -= 1000000000;
+       while (ts.tv_nsec > NSEC_PER_SEC) {
+               ts.tv_nsec -= NSEC_PER_SEC;
                ts.tv_sec++;
        }
 #if defined(__OpenBSD__)
@@ -69,9 +70,25 @@ mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
 #else
        copy = ts;
        while ((res = WAIT_BLOCK (sem, &ts) == -1) && errno == EINTR) {
+               struct timeval current;
                if (alertable)
                        return -1;
+               gettimeofday (&current, NULL);
                ts = copy;
+               ts.tv_sec -= (current.tv_sec - t.tv_sec);
+               ts.tv_nsec -= (current.tv_usec - t.tv_usec) * 1000;
+               if (ts.tv_nsec < 0) {
+                       if (ts.tv_sec <= 0) {
+                               ts.tv_nsec = 0;
+                       } else {
+                               ts.tv_sec--;
+                               ts.tv_nsec += NSEC_PER_SEC;
+                       }
+               }
+               if (ts.tv_sec < 0) {
+                       ts.tv_sec = 0;
+                       ts.tv_nsec = 0;
+               }
        }
 #endif
        return res;