summaryrefslogtreecommitdiff
path: root/lib/glthread
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-06-20 04:04:08 +0200
committerBruno Haible <bruno@clisp.org>2019-06-20 04:04:08 +0200
commit7078fef393b8d06c522c690c1fe7017596b12734 (patch)
tree0b3016f166d386bf1827487e7ff9811fac749600 /lib/glthread
parentd4c0a04b4dadf31e4c7c4bab46887528e4157f2b (diff)
downloadgnulib-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.c24
-rw-r--r--lib/glthread/lock.c50
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