This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch for Showstopper for 2.1.3


Okay, here is the fix which puts back the recalculation of the relative
time by calling getttimeofday.

In the meanwhile, I'm going to investigate that kernel issue; it still
needs to be resolved. I mean, nanosleep() should not return a time value
that is higher than what was passed into it!

I hope that nobody objects that I took the liberty to move the initial
reltime calculation calculation down into the loop, to cut down on
repeated code. So now if the functions are called with an abstime that is
in the past, this case won't be detected right away; the thread will
be put through the queue and all.

Index: linuxthreads/condvar.c
diff -u linuxthreads/condvar.c:1.2.2.1 linuxthreads/condvar.c:1.2.2.2
--- linuxthreads/condvar.c:1.2.2.1	Tue Feb  1 09:41:04 2000
+++ linuxthreads/condvar.c	Sun Feb 13 16:47:27 2000
@@ -137,20 +137,7 @@
   int already_canceled = 0, was_signalled = 0;
   sigjmp_buf jmpbuf;
   pthread_extricate_if extr;
-  struct timeval now;
-  struct timespec reltime;
 
-  /* Compute a time offset relative to now.  */
-  __gettimeofday (&now, NULL);
-  reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
-  reltime.tv_sec = abstime->tv_sec - now.tv_sec;
-  if (reltime.tv_nsec < 0) {
-    reltime.tv_nsec += 1000000000;
-    reltime.tv_sec -= 1;
-  }
-  if (reltime.tv_sec < 0)
-    return ETIMEDOUT;
-
   /* Set up extrication interface */
   extr.pu_object = cond;
   extr.pu_extricate_func = cond_extricate_func;
@@ -185,10 +172,26 @@
       sigemptyset(&unblock);
       sigaddset(&unblock, __pthread_sig_restart);
       sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-      /* Sleep for the required duration. If woken by a signal, resume waiting
-	 as required by Single Unix Specification.  */
-      while (__libc_nanosleep(&reltime, &reltime) != 0)
-	;
+
+      for (;;) {
+	struct timeval now;
+	struct timespec reltime;
+
+	/* Compute a time offset relative to now.  */
+	__gettimeofday (&now, NULL);
+	reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
+	reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+	if (reltime.tv_nsec < 0) {
+	  reltime.tv_nsec += 1000000000;
+	  reltime.tv_sec -= 1;
+	}
+
+	/* Sleep for the required duration. If woken by a signal, resume waiting
+	   as required by Single Unix Specification.  */
+	if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
+	  break;
+      }
+
       /* Block the restart signal again */
       sigprocmask(SIG_SETMASK, &initial_mask, NULL);
       was_signalled = 0;
@@ -260,23 +263,7 @@
   int already_canceled = 0, was_signalled = 0;
   sigjmp_buf jmpbuf;
   pthread_extricate_if extr;
-  struct timeval now;
-  struct timespec reltime;
-
-  /* Compute a time offset relative to now.  */
-  __gettimeofday (&now, NULL);
-  reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
-  reltime.tv_sec = abstime->tv_sec - now.tv_sec;
-  if (reltime.tv_nsec < 0) {
-    reltime.tv_nsec += 1000000000;
-    reltime.tv_sec -= 1;
-  }
-  if (reltime.tv_sec < 0)
-    return ETIMEDOUT;
 
-  already_canceled = 0;
-  was_signalled = 0;
-
   /* Set up extrication interface */
   extr.pu_object = cond;
   extr.pu_extricate_func = cond_extricate_func;
@@ -310,10 +297,27 @@
     sigemptyset(&unblock);
     sigaddset(&unblock, __pthread_sig_restart);
     sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-    /* Sleep for the required duration. If woken by a signal, resume waiting
-       as required by Single Unix Specification.  */
-    while (__libc_nanosleep(&reltime, &reltime) != 0)
-      ;
+
+    for (;;) {
+      struct timeval now;
+      struct timespec reltime;
+
+      /* Compute a time offset relative to now.  */
+      __gettimeofday (&now, NULL);
+      reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
+      reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+
+      if (reltime.tv_nsec < 0) {
+	reltime.tv_nsec += 1000000000;
+	reltime.tv_sec -= 1;
+      }
+
+      /* Sleep for the required duration. If woken by a signal, resume waiting
+	 as required by Single Unix Specification.  */
+      if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
+	break;
+    }
+
     /* Block the restart signal again */
     sigprocmask(SIG_SETMASK, &initial_mask, NULL);
     was_signalled = 0;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]