diff options
author | tegge <tegge@FreeBSD.org> | 2006-01-24 08:56:27 +0800 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 2006-01-24 08:56:27 +0800 |
commit | 345697ad62b4840e906fae98667612b9aea50a9d (patch) | |
tree | e59e043bf6780fad52dfcb242be4f70dc868c131 /devel | |
parent | 0a183b8dcaff16ef1ecf1ee29dde95c5034b0dbf (diff) | |
download | freebsd-ports-gnome-345697ad62b4840e906fae98667612b9aea50a9d.tar.gz freebsd-ports-gnome-345697ad62b4840e906fae98667612b9aea50a9d.tar.zst freebsd-ports-gnome-345697ad62b4840e906fae98667612b9aea50a9d.zip |
Fix timeout/cond signal race causing extra restart signal to be generated
but not consumed.
Diffstat (limited to 'devel')
-rw-r--r-- | devel/linuxthreads/files/condwait-patch | 155 |
1 files changed, 109 insertions, 46 deletions
diff --git a/devel/linuxthreads/files/condwait-patch b/devel/linuxthreads/files/condwait-patch index cbd6cefb81c9..5e9c45a2392a 100644 --- a/devel/linuxthreads/files/condwait-patch +++ b/devel/linuxthreads/files/condwait-patch @@ -1,16 +1,19 @@ -diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c ---- ../../work.orig/linuxthreads-2.2.3_1/condvar.c Thu Apr 12 21:02:02 2001 -+++ ./condvar.c Wed Jul 18 13:30:47 2001 -@@ -55,6 +55,8 @@ +diff -ru ../../work.nc/linuxthreads-2.2.3_19/condvar.c ./condvar.c +--- ../../work.nc/linuxthreads-2.2.3_19/condvar.c Thu Apr 12 23:02:02 2001 ++++ ./condvar.c Tue Jan 10 18:14:20 2006 +@@ -55,6 +55,11 @@ return did_remove; } +extern int __pthread_mutex_condwait_completelock(pthread_mutex_t *mutex); + ++#define CVA_AVAIL 1 ++#define CVA_EXTRA_RESTART 2 ++ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { volatile pthread_descr self = thread_self(); -@@ -74,6 +76,7 @@ +@@ -74,6 +79,7 @@ /* Register extrication interface */ THREAD_SETMEM(self, p_condvar_avail, 0); @@ -18,13 +21,30 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c __pthread_set_own_extricate_if(self, &extr); /* Atomically enqueue thread for waiting, but only if it is not -@@ -121,15 +124,35 @@ +@@ -102,10 +108,15 @@ + while (1) + { + suspend(self); +- if (THREAD_GETMEM(self, p_condvar_avail) == 0 ++ if ((THREAD_GETMEM(self, p_condvar_avail) & CVA_AVAIL) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { ++ if ((THREAD_GETMEM(self, p_condvar_avail) & ++ CVA_EXTRA_RESTART) == 0 && ++ !__compare_and_swap(&self->p_condvar_avail, ++ 0, CVA_EXTRA_RESTART)) ++ break; /* CVA_AVAIL set by other thread */ + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; +@@ -121,15 +132,35 @@ if (THREAD_GETMEM(self, p_woken_by_cancel) && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { THREAD_SETMEM(self, p_woken_by_cancel, 0); - pthread_mutex_lock(mutex); + if (THREAD_GETMEM(self, p_condwait_mutex) == NULL) { -+ if (THREAD_GETMEM(self, p_condwait_extra_restart) != 0) { ++ if ((THREAD_GETMEM(self, p_condvar_avail) & CVA_EXTRA_RESTART) != 0) { + if (spurious_wakeup_count > 0) + spurious_wakeup_count--; + else @@ -37,7 +57,7 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c } + if (THREAD_GETMEM(self, p_condwait_mutex) == NULL && -+ THREAD_GETMEM(self, p_condwait_extra_restart) != 0) { ++ (THREAD_GETMEM(self, p_condvar_avail) & CVA_EXTRA_RESTART) != 0) { + if (spurious_wakeup_count > 0) + spurious_wakeup_count--; + else @@ -56,7 +76,7 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c return 0; } -@@ -155,6 +178,7 @@ +@@ -155,6 +186,7 @@ /* Register extrication interface */ THREAD_SETMEM(self, p_condvar_avail, 0); @@ -64,13 +84,30 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c __pthread_set_own_extricate_if(self, &extr); /* Enqueue to wait on the condition and check for cancellation. */ -@@ -215,15 +239,35 @@ +@@ -196,10 +228,15 @@ + suspend(self); + } + +- if (THREAD_GETMEM(self, p_condvar_avail) == 0 ++ if ((THREAD_GETMEM(self, p_condvar_avail) & CVA_AVAIL) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { ++ if ((THREAD_GETMEM(self, p_condvar_avail) & ++ CVA_EXTRA_RESTART) == 0 && ++ !__compare_and_swap(&self->p_condvar_avail, ++ 0, CVA_EXTRA_RESTART)) ++ break; /* CVA_AVAIL set by other thread */ + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; +@@ -215,15 +252,35 @@ if (THREAD_GETMEM(self, p_woken_by_cancel) && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { THREAD_SETMEM(self, p_woken_by_cancel, 0); - pthread_mutex_lock(mutex); + if (THREAD_GETMEM(self, p_condwait_mutex) == NULL) { -+ if (THREAD_GETMEM(self, p_condwait_extra_restart) != 0) { ++ if ((THREAD_GETMEM(self, p_condvar_avail) & CVA_EXTRA_RESTART) != 0) { + if (spurious_wakeup_count > 0) + spurious_wakeup_count--; + else @@ -83,7 +120,7 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c } + if (THREAD_GETMEM(self, p_condwait_mutex) == NULL && -+ THREAD_GETMEM(self, p_condwait_extra_restart) != 0) { ++ (THREAD_GETMEM(self, p_condvar_avail) & CVA_EXTRA_RESTART) != 0) { + if (spurious_wakeup_count > 0) + spurious_wakeup_count--; + else @@ -102,7 +139,13 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c return 0; } -@@ -242,9 +286,27 @@ +@@ -237,14 +294,34 @@ + int pthread_cond_signal(pthread_cond_t *cond) + { + pthread_descr th; ++ long oldcva; + + __pthread_lock(&cond->__c_lock, NULL); th = dequeue(&cond->__c_waiting); __pthread_unlock(&cond->__c_lock); if (th != NULL) { @@ -110,30 +153,39 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c - WRITE_MEMORY_BARRIER(); - restart(th); + pthread_mutex_t *mutex = th->p_condwait_mutex; -+ if (th->p_condvar_avail == 0 && ++ if ((th->p_condvar_avail & CVA_AVAIL) == 0 && + mutex != NULL && + (mutex->__m_kind == PTHREAD_MUTEX_ERRORCHECK_NP || + mutex->__m_kind == PTHREAD_MUTEX_TIMED_NP) && + __pthread_alt_condwait_queuelock(&mutex->__m_lock, th) == 0) { + th->p_condwait_mutex = NULL; -+ th->p_condwait_extra_restart = 0; + WRITE_MEMORY_BARRIER(); -+ th->p_condvar_avail = 1; ++ do { ++ READ_MEMORY_BARRIER(); ++ oldcva = th->p_condvar_avail; ++ } while (!__compare_and_swap(&th->p_condvar_avail, ++ oldcva, ++ oldcva | CVA_AVAIL)); + WRITE_MEMORY_BARRIER(); -+ if (th->p_condwait_waitnode.abandoned) { -+ th->p_condwait_extra_restart = 1; -+ WRITE_MEMORY_BARRIER(); ++ if ((th->p_condvar_avail & CVA_EXTRA_RESTART) != 0) + restart(th); -+ } + } else { -+ th->p_condvar_avail = 1; ++ th->p_condvar_avail = CVA_AVAIL; + WRITE_MEMORY_BARRIER(); + restart(th); + } } return 0; } -@@ -260,9 +322,27 @@ +@@ -252,6 +329,7 @@ + int pthread_cond_broadcast(pthread_cond_t *cond) + { + pthread_descr tosignal, th; ++ long oldcva; + + __pthread_lock(&cond->__c_lock, NULL); + /* Copy the current state of the waiting queue and empty it */ +@@ -260,9 +338,28 @@ __pthread_unlock(&cond->__c_lock); /* Now signal each process in the queue */ while ((th = dequeue(&tosignal)) != NULL) { @@ -141,32 +193,34 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c - WRITE_MEMORY_BARRIER(); - restart(th); + pthread_mutex_t *mutex = th->p_condwait_mutex; -+ if (th->p_condvar_avail == 0 && ++ if ((th->p_condvar_avail & CVA_AVAIL) == 0 && + mutex != NULL && + (mutex->__m_kind == PTHREAD_MUTEX_ERRORCHECK_NP || + mutex->__m_kind == PTHREAD_MUTEX_TIMED_NP) && + __pthread_alt_condwait_queuelock(&mutex->__m_lock, th) == 0) { + th->p_condwait_mutex = NULL; -+ th->p_condwait_extra_restart = 0; + WRITE_MEMORY_BARRIER(); -+ th->p_condvar_avail = 1; ++ do { ++ READ_MEMORY_BARRIER(); ++ oldcva = th->p_condvar_avail; ++ } while (!__compare_and_swap(&th->p_condvar_avail, ++ oldcva, ++ oldcva | CVA_AVAIL)); + WRITE_MEMORY_BARRIER(); -+ if (th->p_condwait_waitnode.abandoned) { -+ th->p_condwait_extra_restart = 1; -+ WRITE_MEMORY_BARRIER(); ++ if ((th->p_condvar_avail & CVA_EXTRA_RESTART) != 0) + restart(th); -+ } + } else { -+ th->p_condvar_avail = 1; ++ th->p_condvar_avail = CVA_AVAIL; + WRITE_MEMORY_BARRIER(); + restart(th); + } } return 0; } -diff -ru ../../work.orig/linuxthreads-2.2.3_1/internals.h ./internals.h ---- ../../work.orig/linuxthreads-2.2.3_1/internals.h Wed Jul 18 07:25:04 2001 -+++ ./internals.h Wed Jul 18 10:55:57 2001 +Only in .: condvar.c~ +diff -ru ../../work.nc/linuxthreads-2.2.3_19/internals.h ./internals.h +--- ../../work.nc/linuxthreads-2.2.3_19/internals.h Tue Jan 10 17:13:14 2006 ++++ ./internals.h Tue Jan 10 17:33:30 2006 @@ -125,6 +125,13 @@ int pr_lock_count; } pthread_readlock_info; @@ -181,19 +235,28 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/internals.h ./internals.h struct _pthread_descr_struct { union { struct { -@@ -189,6 +196,9 @@ +@@ -176,7 +183,7 @@ + struct pthread_atomic p_resume_count; /* number of times restart() was + called on thread */ + char p_woken_by_cancel; /* cancellation performed wakeup */ +- char p_condvar_avail; /* flag if conditional variable became avail */ ++ long 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 */ +@@ -189,6 +196,8 @@ hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */ #endif /* New elements must be added at the end. */ + pthread_mutex_t *p_condwait_mutex; + struct wait_node p_condwait_waitnode; -+ char p_condwait_extra_restart; } __attribute__ ((aligned(32))); /* We need to align the structure so that doubles are aligned properly. This is 8 bytes on MIPS and 16 bytes on MIPS64. -diff -ru ../../work.orig/linuxthreads-2.2.3_1/mutex.c ./mutex.c ---- ../../work.orig/linuxthreads-2.2.3_1/mutex.c Sun Jan 7 04:35:20 2001 -+++ ./mutex.c Wed Jul 18 09:09:13 2001 +Only in .: internals.h~ +diff -ru ../../work.nc/linuxthreads-2.2.3_19/mutex.c ./mutex.c +--- ../../work.nc/linuxthreads-2.2.3_19/mutex.c Sun Jan 7 05:35:20 2001 ++++ ./mutex.c Tue Jan 10 17:13:46 2006 @@ -92,6 +92,24 @@ } strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) @@ -219,10 +282,10 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/mutex.c ./mutex.c int __pthread_mutex_lock(pthread_mutex_t * mutex) { pthread_descr self; -diff -ru ../../work.orig/linuxthreads-2.2.3_1/spinlock.c ./spinlock.c ---- ../../work.orig/linuxthreads-2.2.3_1/spinlock.c Wed Jul 18 07:25:04 2001 -+++ ./spinlock.c Wed Jul 18 10:56:34 2001 -@@ -232,12 +232,6 @@ +diff -ru ../../work.nc/linuxthreads-2.2.3_19/spinlock.c ./spinlock.c +--- ../../work.nc/linuxthreads-2.2.3_19/spinlock.c Tue Jan 10 17:13:14 2006 ++++ ./spinlock.c Tue Jan 10 17:13:46 2006 +@@ -231,12 +231,6 @@ */ @@ -235,7 +298,7 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/spinlock.c ./spinlock.c static long wait_node_free_list; #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP static int wait_node_free_list_spinlock; -@@ -360,6 +354,55 @@ +@@ -359,6 +353,55 @@ } #endif @@ -291,9 +354,9 @@ diff -ru ../../work.orig/linuxthreads-2.2.3_1/spinlock.c ./spinlock.c void __pthread_alt_lock(struct _pthread_fastlock * lock, pthread_descr self) -diff -ru ../../work.orig/linuxthreads-2.2.3_1/spinlock.h ./spinlock.h ---- ../../work.orig/linuxthreads-2.2.3_1/spinlock.h Wed Jul 18 07:25:04 2001 -+++ ./spinlock.h Wed Jul 18 09:14:58 2001 +diff -ru ../../work.nc/linuxthreads-2.2.3_19/spinlock.h ./spinlock.h +--- ../../work.nc/linuxthreads-2.2.3_19/spinlock.h Tue Jan 10 17:13:14 2006 ++++ ./spinlock.h Tue Jan 10 17:13:46 2006 @@ -130,6 +130,9 @@ timed-out waits. Warning: do not mix these operations with the above ones over the same lock object! */ |