manually "shrink wrap" fast path in pthread_once
authorRich Felker <dalias@aerifal.cx>
Mon, 20 Oct 2014 04:22:51 +0000 (00:22 -0400)
committerRich Felker <dalias@aerifal.cx>
Mon, 20 Oct 2014 04:22:51 +0000 (00:22 -0400)
this change is a workaround for the inability of current compilers to
perform "shrink wrapping" optimizations. in casual testing, it roughly
doubled the performance of pthread_once when called on an
already-finished once control object.

src/thread/pthread_once.c

index 7c47385ccc8fe70e24df960e97aa520c30146bd6..df655ef9a4c8850594e9fbbfe4b0d34ff1821890 100644 (file)
@@ -8,15 +8,8 @@ static void undo(void *control)
                __wake(control, -1, 1);
 }
 
-int __pthread_once(pthread_once_t *control, void (*init)(void))
+int __pthread_once_full(pthread_once_t *control, void (*init)(void))
 {
-       /* Return immediately if init finished before, but ensure that
-        * effects of the init routine are visible to the caller. */
-       if (*control == 2) {
-               a_barrier();
-               return 0;
-       }
-
        /* Try to enter initializing state. Four possibilities:
         *  0 - we're the first or the other cancelled; run init
         *  1 - another thread is running init; wait
@@ -43,4 +36,15 @@ int __pthread_once(pthread_once_t *control, void (*init)(void))
        }
 }
 
+int __pthread_once(pthread_once_t *control, void (*init)(void))
+{
+       /* Return immediately if init finished before, but ensure that
+        * effects of the init routine are visible to the caller. */
+       if (*control == 2) {
+               a_barrier();
+               return 0;
+       }
+       return __pthread_once_full(control, init);
+}
+
 weak_alias(__pthread_once, pthread_once);