diff options
author | Bruno Haible <bruno@clisp.org> | 2019-06-20 04:04:08 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2019-06-20 04:04:08 +0200 |
commit | 7078fef393b8d06c522c690c1fe7017596b12734 (patch) | |
tree | 0b3016f166d386bf1827487e7ff9811fac749600 /lib/glthread | |
parent | d4c0a04b4dadf31e4c7c4bab46887528e4157f2b (diff) | |
download | gnulib-7078fef393b8d06c522c690c1fe7017596b12734.tar.gz |
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.
Diffstat (limited to 'lib/glthread')
-rw-r--r-- | lib/glthread/cond.c | 24 | ||||
-rw-r--r-- | lib/glthread/lock.c | 50 |
2 files changed, 49 insertions, 25 deletions
diff --git a/lib/glthread/cond.c b/lib/glthread/cond.c index b0304bc991..6df6780ac8 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 2af4f2680d..4774573675 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 |