From 75dbc100bf903f908c4e5e90783307cf445b19db Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 27 Sep 2000 00:14:27 +0000 Subject: Update. 2000-09-26 Ulrich Drepper * sysdeps/unix/sysv/linux/i386/bits/time.h: Remove CLOCK_MONOTONIC. --- linuxthreads/spinlock.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'linuxthreads/spinlock.h') diff --git a/linuxthreads/spinlock.h b/linuxthreads/spinlock.h index c194d79..2d3e9bf 100644 --- a/linuxthreads/spinlock.h +++ b/linuxthreads/spinlock.h @@ -212,11 +212,22 @@ static inline long atomic_decrement(struct pthread_atomic *pa) static inline void -__pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif) +__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) { - /* The locks here are not ensuring an atomic update of the p_extricate - pointer. They protect users of the pointer from using stale memory. */ - __pthread_lock(THREAD_GETMEM(self, p_lock), self); - THREAD_SETMEM(self, p_extricate, peif); - __pthread_unlock(THREAD_GETMEM (self, p_lock)); + /* Only store a non-null peif if the thread has cancellation enabled. + Otherwise pthread_cancel will unconditionally call the extricate handler, + and restart the thread giving rise to forbidden spurious wakeups. */ + if (peif == NULL + || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + { + /* If we are removing the extricate interface, we need to synchronize + against pthread_cancel so that it does not continue with a pointer + to a deallocated pthread_extricate_if struct! The thread lock + is (ab)used for this synchronization purpose. */ + if (peif == NULL) + __pthread_lock (THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_extricate, peif); + if (peif == NULL) + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + } } -- cgit v1.1