Update.
authorUlrich Drepper <drepper@redhat.com>
Wed, 26 Jul 2000 02:18:41 +0000 (02:18 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 26 Jul 2000 02:18:41 +0000 (02:18 +0000)
* internals.h (strict __pthread_descr_struct): Add p_sem_avail.
* semaphore.c: Handle spurious wakeups.

* sysdeps/pthread/pthread.h: Add back PTHREAD_MUTX_FAST_NP as an alias
for PTHREAD_MUTEX_ADAPTIVE_NP for source code compatibility.

* pthread.c (__pthread_set_own_extricate): Use THREAD_GETMEM.
(__pthread_wait_for_restart): Likewise.

* condvar.c (pthread_cond_wait): Also check whether thread is
cancelable before aborting loop.
(pthread_cond_timedwait): Likewise.

linuxthreads/ChangeLog
linuxthreads/condvar.c
linuxthreads/internals.h
linuxthreads/pthread.c
linuxthreads/semaphore.c
linuxthreads/sysdeps/pthread/pthread.h

index 880de6a0b99ce14dcb7ce40480607e8f682ad588..b0ae0eea25c1bd409264ad648c2523b292e1f0fa 100644 (file)
@@ -1,5 +1,18 @@
 2000-07-25  Ulrich Drepper  <drepper@redhat.com>
 
+       * internals.h (strict __pthread_descr_struct): Add p_sem_avail.
+       * semaphore.c: Handle spurious wakeups.
+
+       * sysdeps/pthread/pthread.h: Add back PTHREAD_MUTX_FAST_NP as an alias
+       for PTHREAD_MUTEX_ADAPTIVE_NP for source code compatibility.
+
+       * pthread.c (__pthread_set_own_extricate): Use THREAD_GETMEM.
+       (__pthread_wait_for_restart): Likewise.
+
+       * condvar.c (pthread_cond_wait): Also check whether thread is
+       cancelable before aborting loop.
+       (pthread_cond_timedwait): Likewise.
+
        * signals.c (pthread_sighandler): Remove special code to restrore
        %gs on x86.
        (pthread_sighandler_t): Likewise.
index ae1cef1ea9bf8e75678bb2baf79022409c52c25e..f9c46a33168ea54f955feb549ff041e4540792ce 100644 (file)
@@ -103,7 +103,8 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
     {
       suspend(self);
       if (THREAD_GETMEM(self, p_condvar_avail) == 0
-         && THREAD_GETMEM(self, p_woken_by_cancel) == 0)
+         && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+             || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
        {
          /* Count resumes that don't belong to us. */
          spurious_wakeup_count++;
@@ -196,7 +197,8 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond,
       }
 
       if (THREAD_GETMEM(self, p_condvar_avail) == 0
-         && THREAD_GETMEM(self, p_woken_by_cancel) == 0)
+         && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+             || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
        {
          /* Count resumes that don't belong to us. */
          spurious_wakeup_count++;
index 2ed49295eeeff901f7b6749ed85b4e6b4b4ce831..93ec93620c062e8c72424d0b5bd7129e86435f8c 100644 (file)
@@ -168,6 +168,7 @@ struct _pthread_descr_struct {
                                           called on thread */
   char p_woken_by_cancel;       /* cancellation performed wakeup */
   char p_condvar_avail;                /* flag if conditional variable became avail */
+  char p_sem_avail;             /* flag if semaphore became available */
   pthread_extricate_if *p_extricate; /* See above */
   pthread_readlock_info *p_readlock_list;  /* List of readlock info structs */
   pthread_readlock_info *p_readlock_free;  /* Free list of structs */
index 3a669c8decd95645291b0745f3466f31b4636538..7195b2dedc9d95a30e7ec3251e7b35563cac2b94 100644 (file)
@@ -868,9 +868,9 @@ weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
 
 void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif)
 {
-  __pthread_lock(self->p_lock, self);
+  __pthread_lock(THREAD_GETMEM(self, p_lock), self);
   THREAD_SETMEM(self, p_extricate, peif);
-  __pthread_unlock(self->p_lock);
+  __pthread_unlock(THREAD_GETMEM (self, p_lock));
 }
 
 /* Primitives for controlling thread execution */
@@ -881,10 +881,10 @@ void __pthread_wait_for_restart_signal(pthread_descr self)
 
   sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
   sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
+  THREAD_SETMEM(self, p_signal, 0);
   do {
-    self->p_signal = 0;
     sigsuspend(&mask);                   /* Wait for signal */
-  } while (self->p_signal !=__pthread_sig_restart );
+  } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
 }
 
 #if !__ASSUME_REALTIME_SIGNALS
index a772ea5091d4639e8bf9d5d920e7a9bc9a3b1386..e5afce43eb52b081c61d8d023d101bc16822e500 100644 (file)
@@ -60,6 +60,7 @@ int __new_sem_wait(sem_t * sem)
   volatile pthread_descr self = thread_self();
   pthread_extricate_if extr;
   int already_canceled = 0;
+  int spurious_wakeup_count;
 
   /* Set up extrication interface */
   extr.pu_object = sem;
@@ -72,6 +73,7 @@ int __new_sem_wait(sem_t * sem)
     return 0;
   }
   /* Register extrication interface */
+  THREAD_SETMEM(self, p_sem_avail, 0);
   __pthread_set_own_extricate_if(self, &extr);
   /* Enqueue only if not already cancelled. */
   if (!(THREAD_GETMEM(self, p_canceled)
@@ -87,7 +89,20 @@ int __new_sem_wait(sem_t * sem)
   }
 
   /* Wait for sem_post or cancellation, or fall through if already canceled */
-  suspend(self);
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      suspend(self);
+      if (THREAD_GETMEM(self, p_sem_avail) == 0
+         && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+             || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+       {
+         /* Count resumes that don't belong to us. */
+         spurious_wakeup_count++;
+         continue;
+       }
+      break;
+    }
   __pthread_set_own_extricate_if(self, 0);
 
   /* Terminate only if the wakeup came from cancellation. */
@@ -138,6 +153,8 @@ int __new_sem_post(sem_t * sem)
     } else {
       th = dequeue(&sem->__sem_waiting);
       __pthread_unlock((struct _pthread_fastlock *) &sem->__sem_lock);
+      th->p_sem_avail = 1;
+      WRITE_MEMORY_BARRIER();
       restart(th);
     }
   } else {
@@ -195,6 +212,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime)
   pthread_descr self = thread_self();
   pthread_extricate_if extr;
   int already_canceled = 0;
+  int spurious_wakeup_count;
 
   __pthread_lock((struct _pthread_fastlock *) &sem->__sem_lock, self);
   if (sem->__sem_value > 0) {
@@ -215,6 +233,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime)
   extr.pu_extricate_func = new_sem_extricate_func;
 
   /* Register extrication interface */
+  THREAD_SETMEM(self, p_sem_avail, 0);
   __pthread_set_own_extricate_if(self, &extr);
   /* Enqueue only if not already cancelled. */
   if (!(THREAD_GETMEM(self, p_canceled)
@@ -229,24 +248,39 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime)
     pthread_exit(PTHREAD_CANCELED);
   }
 
-  if (timedsuspend(self, abstime) == 0) {
-    int was_on_queue;
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      if (timedsuspend(self, abstime) == 0) {
+       int was_on_queue;
+
+       /* __pthread_lock will queue back any spurious restarts that
+          may happen to it. */
 
-    /* __pthread_lock will queue back any spurious restarts that
-       may happen to it. */
+       __pthread_lock((struct _pthread_fastlock *)&sem->__sem_lock, self);
+       was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
+       __pthread_unlock((struct _pthread_fastlock *)&sem->__sem_lock);
 
-    __pthread_lock((struct _pthread_fastlock *)&sem->__sem_lock, self);
-    was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
-    __pthread_unlock((struct _pthread_fastlock *)&sem->__sem_lock);
+       if (was_on_queue) {
+         __pthread_set_own_extricate_if(self, 0);
+         return ETIMEDOUT;
+       }
 
-    if (was_on_queue) {
-      __pthread_set_own_extricate_if(self, 0);
-      return ETIMEDOUT;
+       /* Eat the outstanding restart() from the signaller */
+       suspend(self);
+      }
+
+      if (THREAD_GETMEM(self, p_sem_avail) == 0
+         && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+             || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+       {
+         /* Count resumes that don't belong to us. */
+         spurious_wakeup_count++;
+         continue;
+       }
+      break;
     }
 
-    /* Eat the outstanding restart() from the signaller */
-    suspend(self);
-  }
  __pthread_set_own_extricate_if(self, 0);
 
   /* Terminate only if the wakeup came from cancellation. */
index dd27ae06788935b2377d112b9640955053f70cd3..b017007f805cad3850644adfb01eff9c41791e03 100644 (file)
@@ -88,6 +88,10 @@ enum
   PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
   PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
 #endif
+#ifdef __USE_GNU
+  /* For compatibility.  */
+  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP
+#endif
 };
 
 enum