]> Savannah Git Hosting - gnulib.git/commitdiff
pthread-once: Simplify Cygwin workaround implementation.
authorBruno Haible <bruno@clisp.org>
Thu, 30 May 2024 23:56:49 +0000 (01:56 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 31 May 2024 07:11:57 +0000 (09:11 +0200)
* lib/pthread-once.c (pthread_once): Use _Atomic instead of __sync_*
gcc primitives.

ChangeLog
lib/pthread-once.c

index a30f610ac10466c6e9d37891a4c431779f75b4a4..583735a33e200fe6ae488973e5e1118b1a99175d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2024-05-31  Bruno Haible  <bruno@clisp.org>
+
+       pthread-once: Simplify Cygwin workaround implementation.
+       * lib/pthread-once.c (pthread_once): Use _Atomic instead of __sync_*
+       gcc primitives.
+
 2024-05-30  Bruno Haible  <bruno@clisp.org>
 
        assert-h, verify: Fix compilation error with g++ (4.8.5) -std=gnu++11.
index 069e77e3f3fc2a6e6564f73ba1a3f86ddf9ba531..0f009c0ec5a694290fb0b72f06f6d514c35a3a7d 100644 (file)
@@ -77,52 +77,31 @@ pthread_once (pthread_once_t *once_control, void (*initfunction) (void))
      In other words:
        state = { unsigned int num_threads : 31; unsigned int done : 1; }
    */
+  _Atomic unsigned int *state_p = (_Atomic unsigned int *) &once_control->state;
   /* Test the 'done' bit.  */
-  if ((* (unsigned int volatile *) &once_control->state & 1) == 0)
+  if ((*state_p & 1) == 0)
     {
       /* The 'done' bit is still zero.  Increment num_threads (atomically).  */
-      for (;;)
-        {
-          unsigned int prev = * (unsigned int volatile *) &once_control->state;
-          if (__sync_bool_compare_and_swap ((unsigned int *) &once_control->state,
-                                            prev, prev + 2))
-            break;
-        }
+      *state_p += 2;
       /* We have incremented num_threads.  Now take the lock.  */
       pthread_mutex_lock (&once_control->mutex);
       /* Test the 'done' bit again.  */
-      if ((* (unsigned int volatile *) &once_control->state & 1) == 0)
+      if ((*state_p & 1) == 0)
         {
           /* Execute the initfunction.  */
           (*initfunction) ();
           /* Set the 'done' bit to 1 (atomically).  */
-          for (;;)
-            {
-              unsigned int prev = * (unsigned int volatile *) &once_control->state;
-              if (__sync_bool_compare_and_swap ((unsigned int *) &once_control->state,
-                                                prev, prev | 1))
-                break;
-            }
+          *state_p |= 1;
         }
       /* Now the 'done' bit is 1.  Release the lock.  */
       pthread_mutex_unlock (&once_control->mutex);
       /* Decrement num_threads (atomically).  */
-      for (;;)
-        {
-          unsigned int prev = * (unsigned int volatile *) &once_control->state;
-          if (prev < 2)
-            abort ();
-          if (__sync_bool_compare_and_swap ((unsigned int *) &once_control->state,
-                                            prev, prev - 2))
-            {
-              if (prev - 2 == 1)
-                /* 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.  */
-                pthread_mutex_destroy (&once_control->mutex);
-              break;
-            }
-        }
+      unsigned int new_state = (*state_p -= 2);
+      if (new_state == 1)
+        /* 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.  */
+        pthread_mutex_destroy (&once_control->mutex);
     }
 #  endif
   return 0;