+2019-06-20 Bruno Haible <bruno@clisp.org>
+
+ 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 <bruno@clisp.org>
cond: Make glthread_cond_timedwait more reliable on Windows.
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);
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);
+ }
}
{
/* 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;
/* 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
/* 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. */
/* 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 ();
}
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