]> Savannah Git Hosting - gnulib.git/commitdiff
pthread-once: Simplify Cygwin workaround implementation.
authorBruno Haible <bruno@clisp.org>
Fri, 31 May 2024 09:19:28 +0000 (11:19 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 31 May 2024 09:23:14 +0000 (11:23 +0200)
* lib/pthread-once.c (pthread_once): Use separate 16-bit words to store
the parts of the state.

ChangeLog
lib/pthread-once.c

index 583735a33e200fe6ae488973e5e1118b1a99175d..e822cb74bd94f584f1b817262f14fae9da87f7f1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2024-05-31  Bruno Haible  <bruno@clisp.org>
 
+       pthread-once: Simplify Cygwin workaround implementation.
+       * lib/pthread-once.c (pthread_once): Use separate 16-bit words to store
+       the parts of the state.
+
        pthread-once: Simplify Cygwin workaround implementation.
        * lib/pthread-once.c (pthread_once): Use _Atomic instead of __sync_*
        gcc primitives.
index 0f009c0ec5a694290fb0b72f06f6d514c35a3a7d..ef583daed4996c6d9a38c5a6f5e7874b5940bda9 100644 (file)
@@ -73,31 +73,35 @@ pthread_once (pthread_once_t *once_control, void (*initfunction) (void))
        typedef struct { pthread_mutex_t mutex; int state; } pthread_once_t;
        #define PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 }
      while assigning the following meaning to the state:
-       state = 2 * <number of waiting threads> + <1 if done>
+       state = (<number of waiting threads> << 16) + <1 if done>
      In other words:
-       state = { unsigned int num_threads : 31; unsigned int done : 1; }
+       state = { unsigned int num_threads : 16; unsigned int done : 16; }
    */
-  _Atomic unsigned int *state_p = (_Atomic unsigned int *) &once_control->state;
+  struct actual_state
+    {
+      _Atomic unsigned short num_threads;
+      _Atomic unsigned short done;
+    };
+  struct actual_state *state_p = (struct actual_state *) &once_control->state;
   /* Test the 'done' bit.  */
-  if ((*state_p & 1) == 0)
+  if (state_p->done == 0)
     {
       /* The 'done' bit is still zero.  Increment num_threads (atomically).  */
-      *state_p += 2;
+      state_p->num_threads += 1;
       /* We have incremented num_threads.  Now take the lock.  */
       pthread_mutex_lock (&once_control->mutex);
       /* Test the 'done' bit again.  */
-      if ((*state_p & 1) == 0)
+      if (state_p->done == 0)
         {
           /* Execute the initfunction.  */
           (*initfunction) ();
           /* Set the 'done' bit to 1 (atomically).  */
-          *state_p |= 1;
+          state_p->done = 1;
         }
       /* Now the 'done' bit is 1.  Release the lock.  */
       pthread_mutex_unlock (&once_control->mutex);
       /* Decrement num_threads (atomically).  */
-      unsigned int new_state = (*state_p -= 2);
-      if (new_state == 1)
+      if ((state_p->num_threads -= 1) == 0)
         /* num_threads is now zero, and done is 1.
            No other thread will need to use the lock.
            We can therefore destroy the lock, to free resources.  */