Lines 23-41
Link Here
|
23 |
|
23 |
|
24 |
unsigned long int __fork_generation attribute_hidden; |
24 |
unsigned long int __fork_generation attribute_hidden; |
25 |
|
25 |
|
|
|
26 |
struct CleanupInfo { |
27 |
pthread_once_t *once; |
28 |
}; |
26 |
|
29 |
|
27 |
static void |
30 |
static void |
28 |
clear_once_control (void *arg) |
31 |
cleanup_maybe_clear_once_control (struct CleanupInfo *pinfo) |
29 |
{ |
32 |
{ |
30 |
pthread_once_t *once_control = (pthread_once_t *) arg; |
33 |
if (pinfo->once) { |
31 |
|
34 |
|
32 |
/* Reset to the uninitialized state here. We don't need a stronger memory |
35 |
/* Reset the once control variable to the uninitialized state here. |
33 |
order because we do not need to make any other of our writes visible to |
36 |
We don't need a stronger memory order because we do not need to |
34 |
other threads that see this value: This function will be called if we |
37 |
make any other of our writes visible to other threads that see |
35 |
get interrupted (see __pthread_once), so all we need to relay to other |
38 |
this value: This function will be called if we get interrupted |
36 |
threads is the state being reset again. */ |
39 |
(see __pthread_once), so all we need to relay to other threads |
37 |
atomic_store_relaxed (once_control, 0); |
40 |
is the state being reset again. */ |
38 |
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); |
41 |
atomic_store_relaxed (pinfo->once, 0); |
|
|
42 |
lll_futex_wake (pinfo->once, INT_MAX, LLL_PRIVATE); |
43 |
} |
39 |
} |
44 |
} |
40 |
|
45 |
|
41 |
|
46 |
|
Lines 107-120
__pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void))
Link Here
|
107 |
} |
112 |
} |
108 |
|
113 |
|
109 |
/* This thread is the first here. Do the initialization. |
114 |
/* This thread is the first here. Do the initialization. |
110 |
Register a cleanup handler so that in case the thread gets |
115 |
Register a cleanup handler so that in case the thread gets |
111 |
interrupted the initialization can be restarted. */ |
116 |
interrupted or the initialization routine exits by throwing |
112 |
pthread_cleanup_push (clear_once_control, once_control); |
117 |
an exception the initialization can be restarted. */ |
113 |
|
118 |
|
114 |
init_routine (); |
119 |
struct CleanupInfo |
|
|
120 |
cleanupobj __attribute__ ((cleanup (cleanup_maybe_clear_once_control))) |
121 |
= { .once = once_control }; |
115 |
|
122 |
|
116 |
pthread_cleanup_pop (0); |
123 |
init_routine (); |
117 |
|
124 |
|
|
|
125 |
/* Reset the once control variable to disable cleanup. */ |
126 |
cleanupobj.once = 0; |
118 |
|
127 |
|
119 |
/* Mark *once_control as having finished the initialization. We need |
128 |
/* Mark *once_control as having finished the initialization. We need |
120 |
release memory order here because we need to synchronize with other |
129 |
release memory order here because we need to synchronize with other |