]> Savannah Git Hosting - gnulib.git/commitdiff
lock, cond: Avoid possible counter wraparound on Windows.
authorBruno Haible <bruno@clisp.org>
Thu, 20 Jun 2019 02:04:08 +0000 (04:04 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 20 Jun 2019 02:04:08 +0000 (04:04 +0200)
* 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
lib/glthread/cond.c
lib/glthread/lock.c

index 527199744c2e0c058bad967648e027c9b9656ee7..ba91fdac96c5efea7a0f4df8051f14d136548fd6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+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.
index b0304bc99110fd7f1c5ec97722dacbcdf2fb01ae..6df6780ac8fdf5f170ce879d9039dc6fa2572d1e 100644 (file)
@@ -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);
+        }
     }
 
   {
index 2af4f2680dc019382a73683bd169008ff7f232e4..47745736750c823b1ba42f71ef2149b25b235075 100644 (file)
@@ -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