Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Sep 2015 08:41:07 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r287556 - head/lib/libthr/thread
Message-ID:  <201509080841.t888f76o082185@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509080841.t888f76o082185>