svn commit: r287556 - head/lib/libthr/thread
Konstantin Belousov
kib at FreeBSD.org
Tue Sep 8 08:41:08 UTC 2015
Author: kib
Date: Tue Sep 8 08:41:07 2015
New Revision: 287556
URL: https://svnweb.freebsd.org/changeset/base/287556
Log:
In the pthread_once(), if the initializer has already run, then the
calling thread is supposed to see accesses issued by the initializer.
This means that the read of the once_control->state variable should
have an acquire semantic. Use atomic_thread_fence_acq() when the
value read is ONCE_DONE, instead of straightforward atomic_load_acq(),
to only put a barrier when needed (*).
On the other hand, the updates of the once_control->state with the
intermediate progress state do not need to synchronize with other
state accesses, remove _acq suffix.
Reviewed by: alc (previous version)
Suggested by: alc (*)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Modified:
head/lib/libthr/thread/thr_once.c
Modified: head/lib/libthr/thread/thr_once.c
==============================================================================
--- head/lib/libthr/thread/thr_once.c Tue Sep 8 08:06:20 2015 (r287555)
+++ head/lib/libthr/thread/thr_once.c Tue Sep 8 08:41:07 2015 (r287556)
@@ -68,13 +68,15 @@ _pthread_once(pthread_once_t *once_contr
for (;;) {
state = once_control->state;
- if (state == ONCE_DONE)
+ if (state == ONCE_DONE) {
+ atomic_thread_fence_acq();
return (0);
+ }
if (state == ONCE_NEVER_DONE) {
- if (atomic_cmpset_acq_int(&once_control->state, state, ONCE_IN_PROGRESS))
+ if (atomic_cmpset_int(&once_control->state, state, ONCE_IN_PROGRESS))
break;
} else if (state == ONCE_IN_PROGRESS) {
- if (atomic_cmpset_acq_int(&once_control->state, state, ONCE_WAIT))
+ if (atomic_cmpset_int(&once_control->state, state, ONCE_WAIT))
_thr_umtx_wait_uint(&once_control->state, ONCE_WAIT, NULL, 0);
} else if (state == ONCE_WAIT) {
_thr_umtx_wait_uint(&once_control->state, state, NULL, 0);
More information about the svn-src-head
mailing list