>From 7078fef393b8d06c522c690c1fe7017596b12734 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:04:08 +0200 Subject: [PATCH 07/26] lock, cond: Avoid possible counter wraparound on Windows. * lib/glthread/lock.c (glthread_lock_lock_func): Leave the 'started' field of the guard unchanged if it was already positive. (glthread_rwlock_rdlock_func): Likewise. (glthread_rwlock_wrlock_func): Likewise. (glthread_recursive_lock_lock_func): Likewise. * lib/glthread/cond.c (glthread_cond_wait_func): Likewise. (glthread_cond_timedwait_func): Likewise. --- ChangeLog | 11 +++++++++++ lib/glthread/cond.c | 24 ++++++++++++++++-------- lib/glthread/lock.c | 50 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5271997..ba91fda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2019-06-20 Bruno Haible + lock, cond: Avoid possible counter wraparound on Windows. + * lib/glthread/lock.c (glthread_lock_lock_func): Leave the 'started' + field of the guard unchanged if it was already positive. + (glthread_rwlock_rdlock_func): Likewise. + (glthread_rwlock_wrlock_func): Likewise. + (glthread_recursive_lock_lock_func): Likewise. + * lib/glthread/cond.c (glthread_cond_wait_func): Likewise. + (glthread_cond_timedwait_func): Likewise. + +2019-06-20 Bruno Haible + cond: Make glthread_cond_timedwait more reliable on Windows. * lib/glthread/cond.c (glthread_cond_timedwait_func): Initialize the condition variable before looking at the current time. diff --git a/lib/glthread/cond.c b/lib/glthread/cond.c index b0304bc..6df6780 100644 --- a/lib/glthread/cond.c +++ b/lib/glthread/cond.c @@ -229,10 +229,14 @@ glthread_cond_wait_func (gl_cond_t *cond, gl_lock_t *lock) Initialize it. */ glthread_cond_init (cond); else - /* Yield the CPU while waiting for another thread to finish - initializing this condition variable. */ - while (!cond->guard.done) - Sleep (0); + { + /* Don't let cond->guard.started grow and wrap around. */ + InterlockedDecrement (&cond->guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this condition variable. */ + while (!cond->guard.done) + Sleep (0); + } } EnterCriticalSection (&cond->lock); @@ -292,10 +296,14 @@ glthread_cond_timedwait_func (gl_cond_t *cond, gl_lock_t *lock, struct timespec Initialize it. */ glthread_cond_init (cond); else - /* Yield the CPU while waiting for another thread to finish - initializing this condition variable. */ - while (!cond->guard.done) - Sleep (0); + { + /* Don't let cond->guard.started grow and wrap around. */ + InterlockedDecrement (&cond->guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this condition variable. */ + while (!cond->guard.done) + Sleep (0); + } } { diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c index 2af4f26..4774573 100644 --- a/lib/glthread/lock.c +++ b/lib/glthread/lock.c @@ -811,10 +811,14 @@ glthread_lock_lock_func (gl_lock_t *lock) /* This thread is the first one to need this lock. Initialize it. */ glthread_lock_init (lock); else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); + { + /* Don't let lock->guard.started grow and wrap around. */ + InterlockedDecrement (&lock->guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } } EnterCriticalSection (&lock->lock); return 0; @@ -951,10 +955,14 @@ glthread_rwlock_rdlock_func (gl_rwlock_t *lock) /* This thread is the first one to need this lock. Initialize it. */ glthread_rwlock_init (lock); else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); + { + /* Don't let lock->guard.started grow and wrap around. */ + InterlockedDecrement (&lock->guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } } EnterCriticalSection (&lock->lock); /* Test whether only readers are currently running, and whether the runcount @@ -1007,10 +1015,14 @@ glthread_rwlock_wrlock_func (gl_rwlock_t *lock) /* This thread is the first one to need this lock. Initialize it. */ glthread_rwlock_init (lock); else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); + { + /* Don't let lock->guard.started grow and wrap around. */ + InterlockedDecrement (&lock->guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } } EnterCriticalSection (&lock->lock); /* Test whether no readers or writers are currently running. */ @@ -1131,10 +1143,14 @@ glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock) /* This thread is the first one to need this lock. Initialize it. */ glthread_recursive_lock_init (lock); else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); + { + /* Don't let lock->guard.started grow and wrap around. */ + InterlockedDecrement (&lock->guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } } { DWORD self = GetCurrentThreadId (); @@ -1196,7 +1212,7 @@ glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) } else { - /* Undo last operation. */ + /* Don't let once_control->started grow and wrap around. */ InterlockedDecrement (&once_control->started); /* Some other thread has already started the initialization. Yield the CPU while waiting for the other thread to finish -- 2.7.4