| OLD | NEW |
| 1 #include "pthread_impl.h" | 1 #include "pthread_impl.h" |
| 2 | 2 |
| 3 static void undo(void *control) | 3 static void undo(void* control) { |
| 4 { | 4 /* Wake all waiters, since the waiter status is lost when |
| 5 » /* Wake all waiters, since the waiter status is lost when | 5 * resetting control to the initial state. */ |
| 6 » * resetting control to the initial state. */ | 6 if (a_swap(control, 0) == 3) |
| 7 » if (a_swap(control, 0) == 3) | 7 __wake(control, -1, 1); |
| 8 » » __wake(control, -1, 1); | |
| 9 } | 8 } |
| 10 | 9 |
| 11 int __pthread_once_full(pthread_once_t *control, void (*init)(void)) | 10 int __pthread_once_full(pthread_once_t* control, void (*init)(void)) { |
| 12 { | 11 /* Try to enter initializing state. Four possibilities: |
| 13 » /* Try to enter initializing state. Four possibilities: | 12 * 0 - we're the first or the other cancelled; run init |
| 14 » * 0 - we're the first or the other cancelled; run init | 13 * 1 - another thread is running init; wait |
| 15 » * 1 - another thread is running init; wait | 14 * 2 - another thread finished running init; just return |
| 16 » * 2 - another thread finished running init; just return | 15 * 3 - another thread is running init, waiters present; wait */ |
| 17 » * 3 - another thread is running init, waiters present; wait */ | |
| 18 | 16 |
| 19 » for (;;) switch (a_cas(control, 0, 1)) { | 17 for (;;) |
| 20 » case 0: | 18 switch (a_cas(control, 0, 1)) { |
| 21 » » pthread_cleanup_push(undo, control); | 19 case 0: |
| 22 » » init(); | 20 pthread_cleanup_push(undo, control); |
| 23 » » pthread_cleanup_pop(0); | 21 init(); |
| 22 pthread_cleanup_pop(0); |
| 24 | 23 |
| 25 » » if (a_swap(control, 2) == 3) | 24 if (a_swap(control, 2) == 3) |
| 26 » » » __wake(control, -1, 1); | 25 __wake(control, -1, 1); |
| 27 » » return 0; | 26 return 0; |
| 28 » case 1: | 27 case 1: |
| 29 » » /* If this fails, so will __wait. */ | 28 /* If this fails, so will __wait. */ |
| 30 » » a_cas(control, 1, 3); | 29 a_cas(control, 1, 3); |
| 31 » case 3: | 30 case 3: |
| 32 » » __wait(control, 0, 3, 1); | 31 __wait(control, 0, 3, 1); |
| 33 » » continue; | 32 continue; |
| 34 » case 2: | 33 case 2: |
| 35 » » return 0; | 34 return 0; |
| 36 » } | 35 } |
| 37 } | 36 } |
| 38 | 37 |
| 39 int __pthread_once(pthread_once_t *control, void (*init)(void)) | 38 int __pthread_once(pthread_once_t* control, void (*init)(void)) { |
| 40 { | 39 /* Return immediately if init finished before, but ensure that |
| 41 » /* Return immediately if init finished before, but ensure that | 40 * effects of the init routine are visible to the caller. */ |
| 42 » * effects of the init routine are visible to the caller. */ | 41 if (*(volatile int*)control == 2) { |
| 43 » if (*(volatile int *)control == 2) { | 42 a_barrier(); |
| 44 » » a_barrier(); | 43 return 0; |
| 45 » » return 0; | 44 } |
| 46 » } | 45 return __pthread_once_full(control, init); |
| 47 » return __pthread_once_full(control, init); | |
| 48 } | 46 } |
| 49 | 47 |
| 50 weak_alias(__pthread_once, pthread_once); | 48 weak_alias(__pthread_once, pthread_once); |
| OLD | NEW |