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]

LinuxThreads timed condition wait patch.



This is a patch to simplify the handling of signal interruptions
of a timed condition variable wait. It is necessary to remain sleeping
while handling signals until the condition is signaled or the time
specified in the pthread_cond_timedwait call passes.

This logic has been recently the subject of some problem reports,
and refinements were done to the big loop around the body of the
logic.

In fact, an obvious (to me now) as well as elegant and efficient solution
has been missed, which is to simply put a tight loop around the call to
__libc_nanosleep().

Patch...

Index: linuxthreads/ChangeLog
diff -u linuxthreads/ChangeLog:1.2 linuxthreads/ChangeLog:1.2.2.1
--- linuxthreads/ChangeLog:1.2	Tue Feb  1 08:37:32 2000
+++ linuxthreads/ChangeLog	Tue Feb  1 09:41:04 2000
@@ -1,3 +1,9 @@
+2000-02-01  Kaz Kylheku  <kaz@ashi.footprints.net>
+	* condvar.c (pthread_cond_timedwait_relative_old): Do tight
+	loop around nanosleep calls instead of around most of the function
+	(pthread_cond_timedwait_relative_new): Likewise.
+	body.  Got rid of backwards goto and one local.
+
 2000-01-31  Ulrich Drepper  <drepper@redhat.com>
 
 	* condvar.c (pthread_cond_timedwait_relative_old): Recompute time
Index: linuxthreads/condvar.c
diff -u linuxthreads/condvar.c:1.2 linuxthreads/condvar.c:1.2.2.1
--- linuxthreads/condvar.c:1.2	Tue Feb  1 08:37:32 2000
+++ linuxthreads/condvar.c	Tue Feb  1 09:41:04 2000
@@ -134,14 +134,12 @@
 {
   volatile pthread_descr self = thread_self();
   sigset_t unblock, initial_mask;
-  int retsleep, already_canceled, was_signalled;
+  int already_canceled = 0, was_signalled = 0;
   sigjmp_buf jmpbuf;
   pthread_extricate_if extr;
   struct timeval now;
   struct timespec reltime;
 
-requeue_and_wait_again:
-
   /* Compute a time offset relative to now.  */
   __gettimeofday (&now, NULL);
   reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
@@ -153,10 +151,6 @@
   if (reltime.tv_sec < 0)
     return ETIMEDOUT;
 
-  retsleep = 0;
-  already_canceled = 0;
-  was_signalled = 0;
-
   /* Set up extrication interface */
   extr.pu_object = cond;
   extr.pu_extricate_func = cond_extricate_func;
@@ -191,13 +185,14 @@
       sigemptyset(&unblock);
       sigaddset(&unblock, __pthread_sig_restart);
       sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-      /* Sleep for the required duration */
-      retsleep = __libc_nanosleep(&reltime, NULL);
+      /* Sleep for the required duration. If woken by a signal, resume waiting
+	 as required by Single Unix Specification.  */
+      while (__libc_nanosleep(&reltime, &reltime) != 0)
+	;
       /* Block the restart signal again */
       sigprocmask(SIG_SETMASK, &initial_mask, NULL);
       was_signalled = 0;
     } else {
-      retsleep = -1;
       was_signalled = 1;
     }
     THREAD_SETMEM(self, p_signal_jmp, NULL);
@@ -229,12 +224,7 @@
       if (was_on_queue) {
 	__pthread_set_own_extricate_if(self, 0);
 	pthread_mutex_lock(mutex);
-
-	if (retsleep == 0)
-	  return ETIMEDOUT;
-	/* Woken by a signal: resume waiting as required by Single Unix
-	   Specification.  */
-	goto requeue_and_wait_again;
+	return ETIMEDOUT;
       }
 
       suspend(self);
@@ -267,14 +257,12 @@
 {
   volatile pthread_descr self = thread_self();
   sigset_t unblock, initial_mask;
-  int retsleep, already_canceled, was_signalled;
+  int already_canceled = 0, was_signalled = 0;
   sigjmp_buf jmpbuf;
   pthread_extricate_if extr;
   struct timeval now;
   struct timespec reltime;
 
- requeue_and_wait_again:
-
   /* Compute a time offset relative to now.  */
   __gettimeofday (&now, NULL);
   reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
@@ -286,7 +274,6 @@
   if (reltime.tv_sec < 0)
     return ETIMEDOUT;
 
-  retsleep = 0;
   already_canceled = 0;
   was_signalled = 0;
 
@@ -323,13 +310,14 @@
     sigemptyset(&unblock);
     sigaddset(&unblock, __pthread_sig_restart);
     sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-    /* Sleep for the required duration */
-    retsleep = __libc_nanosleep(&reltime, NULL);
+    /* Sleep for the required duration. If woken by a signal, resume waiting
+       as required by Single Unix Specification.  */
+    while (__libc_nanosleep(&reltime, &reltime) != 0)
+      ;
     /* Block the restart signal again */
     sigprocmask(SIG_SETMASK, &initial_mask, NULL);
     was_signalled = 0;
   } else {
-    retsleep = -1;
     was_signalled = 1;
   }
   THREAD_SETMEM(self, p_signal_jmp, NULL);
@@ -358,12 +346,7 @@
     if (was_on_queue) {
       __pthread_set_own_extricate_if(self, 0);
       pthread_mutex_lock(mutex);
-
-      if (retsleep == 0)
-	return ETIMEDOUT;
-      /* Woken by a signal: resume waiting as required by Single Unix
-	 Specification.  */
-      goto requeue_and_wait_again;
+      return ETIMEDOUT;
     }
 
     /* Eat the outstanding restart() from the signaller */





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