You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
4.4 KiB
108 lines
4.4 KiB
commit 63668b7084ac26865136e59fdf17781f9f49bd99 |
|
Author: Torvald Riegel <triegel@redhat.com> |
|
Date: Fri Oct 11 18:58:04 2013 +0300 |
|
|
|
pthread_once: Clean up constants. |
|
|
|
[BZ #15215] This just gives a name to the integer constants being used. |
|
|
|
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h |
|
index dda1032d5aa95234..1a842e06bff82479 100644 |
|
--- a/nptl/pthreadP.h |
|
+++ b/nptl/pthreadP.h |
|
@@ -159,6 +159,12 @@ enum |
|
#define FUTEX_TID_MASK 0x3fffffff |
|
|
|
|
|
+/* pthread_once definitions. See __pthread_once for how these are used. */ |
|
+#define __PTHREAD_ONCE_INPROGRESS 1 |
|
+#define __PTHREAD_ONCE_DONE 2 |
|
+#define __PTHREAD_ONCE_FORK_GEN_INCR 4 |
|
+ |
|
+ |
|
/* Internal variables. */ |
|
|
|
|
|
diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c |
|
index 10c01d6023508e3c..595bd7e298003e00 100644 |
|
--- a/nptl/pthread_once.c |
|
+++ b/nptl/pthread_once.c |
|
@@ -40,8 +40,11 @@ clear_once_control (void *arg) |
|
|
|
|
|
/* This is similar to a lock implementation, but we distinguish between three |
|
- states: not yet initialized (0), initialization finished (2), and |
|
- initialization in progress (__fork_generation | 1). If in the first state, |
|
+ states: not yet initialized (0), initialization in progress |
|
+ (__fork_generation | __PTHREAD_ONCE_INPROGRESS), and initialization |
|
+ finished (__PTHREAD_ONCE_DONE); __fork_generation does not use the bits |
|
+ that are used for __PTHREAD_ONCE_INPROGRESS and __PTHREAD_ONCE_DONE (which |
|
+ is what __PTHREAD_ONCE_FORK_GEN_INCR is used for). If in the first state, |
|
threads will try to run the initialization by moving to the second state; |
|
the first thread to do so via a CAS on once_control runs init_routine, |
|
other threads block. |
|
@@ -66,14 +69,14 @@ __pthread_once (once_control, init_routine) |
|
int oldval, val, newval; |
|
|
|
/* We need acquire memory order for this load because if the value |
|
- signals that initialization has finished, we need to be see any |
|
+ signals that initialization has finished, we need to see any |
|
data modifications done during initialization. */ |
|
val = *once_control; |
|
atomic_read_barrier(); |
|
do |
|
{ |
|
/* Check if the initialization has already been done. */ |
|
- if (__glibc_likely ((val & 2) != 0)) |
|
+ if (__glibc_likely ((val & __PTHREAD_ONCE_DONE) != 0)) |
|
return 0; |
|
|
|
oldval = val; |
|
@@ -82,7 +85,7 @@ __pthread_once (once_control, init_routine) |
|
generation because it's immutable in a particular process, and |
|
forked child processes start with a single thread that modified |
|
the generation. */ |
|
- newval = __fork_generation | 1; |
|
+ newval = __fork_generation | __PTHREAD_ONCE_INPROGRESS; |
|
/* We need acquire memory order here for the same reason as for the |
|
load from once_control above. */ |
|
val = atomic_compare_and_exchange_val_acq (once_control, newval, |
|
@@ -91,11 +94,11 @@ __pthread_once (once_control, init_routine) |
|
while (__glibc_unlikely (val != oldval)); |
|
|
|
/* Check if another thread already runs the initializer. */ |
|
- if ((oldval & 1) != 0) |
|
+ if ((oldval & __PTHREAD_ONCE_INPROGRESS) != 0) |
|
{ |
|
/* Check whether the initializer execution was interrupted by a |
|
- fork. We know that for both values, bit 0 is set and bit 1 is |
|
- not. */ |
|
+ fork. We know that for both values, __PTHREAD_ONCE_INPROGRESS |
|
+ is set and __PTHREAD_ONCE_DONE is not. */ |
|
if (oldval == newval) |
|
{ |
|
/* Same generation, some other thread was faster. Wait. */ |
|
@@ -118,7 +121,7 @@ __pthread_once (once_control, init_routine) |
|
release memory order here because we need to synchronize with other |
|
threads that want to use the initialized data. */ |
|
atomic_write_barrier(); |
|
- *once_control = 2; |
|
+ *once_control = __PTHREAD_ONCE_DONE; |
|
|
|
/* Wake up all other threads. */ |
|
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); |
|
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c |
|
index 0635bfdb6cdf0aa8..8c197cb8e4347959 100644 |
|
--- a/nptl/sysdeps/unix/sysv/linux/fork.c |
|
+++ b/nptl/sysdeps/unix/sysv/linux/fork.c |
|
@@ -146,8 +146,9 @@ __libc_fork (void) |
|
|
|
assert (THREAD_GETMEM (self, tid) != ppid); |
|
|
|
+ /* See __pthread_once. */ |
|
if (__fork_generation_pointer != NULL) |
|
- *__fork_generation_pointer += 4; |
|
+ *__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR; |
|
|
|
/* Adjust the PID field for the new process. */ |
|
THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid));
|
|
|