On Wed, Aug 1, 2018 at 10:29 AM, Scott Cotton <[email protected]> wrote: > Apologies, a delay in my mail client response to my input something made me > press send prematurely. > > Let me repeat the partial message and finish it correctly here. > >> More or less, but in C11 stdatomic terms atomic.CompareAndSwap is like >> atomic_compare_exchange_weak_explicit(p, &old, new, >> memory_order_acq_rel, memory_order_relaxed). It doesn't have the >> guarantees of atomic_compare_exchange_strong and it doesn't guarantee >> sequential consistency even when it succeeds. Care is required for >> portable code as on x86 there is no difference between >> compare_exchange_weak and compare_exchange_strong, and >> compare/exchange always gives you sequential consistency, but these >> statements are not true on some non-x86 platforms. > > > Thanks for your clarification. > > From the gcc docs I understand, on success, I do get sequential consitency > guarantee using > """ > atomic_compare_exchange_weak_explicit(p, &old, new, > memory_order_acq_rel, memory_order_relaxed) > """ > but only if at most "another" thread is involved, no sequential guarantees > if more than one other thread is doing the atomic CAS on the same address. > > (the docs read > """ > __ATOMIC_ACQ_RELFull barrier in both directions and synchronizes with > acquire loads and release stores in another thread. > __ATOMIC_SEQ_CSTFull barrier in both directions and synchronizes with > acquire loads and release stores in all threads.""" > > So now here's a question: Suppose that there is exactly one goroutine > calling atomic.CompareAndSwap > and exactly one C thread calling atomic_cas(...) on the same address. > > Can I assume sequential consistency (acquire and release) between the > goroutine and the thread? Or is the fact that the go scheduler may put the > goroutine on different threads over time going to pose a risk, thus (cringe) > inviting a fix with runtime.LockOSThread()?
I don't think the fact that goroutines can change threads is going to matter here. When a goroutine changes threads the new thread by definition sees all the memory writes done by the old thread. acquire-release is not the same as sequential consistency but I think in this case it doesn't matter. Ian > On 1 August 2018 at 19:23, Scott Cotton <[email protected]> wrote: >> >> Thanks for clarifying >> >> On 1 August 2018 at 18:47, Ian Lance Taylor <[email protected]> wrote: >>> >>> On Wed, Aug 1, 2018 at 8:21 AM, Scott Cotton <[email protected]> wrote: >>> > Thanks Ian, >>> > >>> > Nice article on volatile, even though I wasn't at all thinking of >>> > promoting >>> > "volatile" as a way to communicate between threads ;) or goroutines >>> > with >>> > cgo involved for that matter. May make sense for some application >>> > contexts >>> > though, such as mmap'd hardware memory or when real-time constraints >>> > present >>> > risk of failure in light of Go<->C calling overhead and/or full >>> > locks/channels. Definitely not part of the concurrency or threads 101 >>> > syllabus. >>> > >>> > So to summarise, there's no official Golang statement supporting >>> > inter-op of >>> > C11 atomic_ and Go sync/atomic, but it should work fine, and Go's >>> > sync/atomic is roughly equivalent to atomic_compare_exchange_strong >>> > from C11 >>> > stdatomic.h which is most safely translated to GCC >>> > __atomic_compare_exchange_n with the extra arguments you specify. >>> > For >>> > whatever reason, >>> > the question of preservation of the volatile qualifier in the Go view >>> > of the >>> > volatile C value via cgo doesn't spark concern. >>> > >>> > Sounds ok to me so long as I'm not relying on it for an airplane >>> > controller >>> > or automobile collision avoidance or the like, and so long as I'm darn >>> > sure >>> > the Go view of the C volatile is "the correct one". >>> >>> More or less, but in C11 stdatomic terms atomic.CompareAndSwap is like >>> atomic_compare_exchange_weak_explicit(p, &old, new, >>> memory_order_acq_rel, memory_order_relaxed). It doesn't have the >>> guarantees of atomic_compare_exchange_strong and it doesn't guarantee >>> sequential consistency even when it succeeds. Care is required for >>> portable code as on x86 there is no difference between >>> compare_exchange_weak and compare_exchange_strong, and >>> compare/exchange always gives you sequential consistency, but these >>> statements are not true on some non-x86 platforms. >> >> >> Thanks for your clarification. >> >> From the gcc docs I understand, on success, I do get sequential consitency >> guarantee using >> """ >> atomic_compare_exchange_weak_explicit(p, &old, new, >> memory_order_acq_rel, memory_order_relaxed) >> """ >> but only if at most "another" thread is involved, no sequential >> guarantees if more than one other thread is doing the atomic CAS on the same >> address. >> >> (the docs read >> """ >> __ATOMIC_ACQ_RELFull barrier in both directions and synchronizes with >> acquire loads and release stores in another thread. >> __ATOMIC_SEQ_CSTFull barrier in both directions and synchronizes with >> acquire loads and release stores in all threads.""" >> >> So now here's a question: Suppose that there is exactly one goroutine >> calling atomic.CompareAndSwap >> and exactly one C thread calling atomic_cas(...) on the same address. >> >> Can I assume sequential >> >> >>> >>> Ian >>> >>> >>> > >>> > On 1 August 2018 at 16:17, Ian Lance Taylor <[email protected]> wrote: >>> >> >>> >> On Wed, Aug 1, 2018 at 6:59 AM, Scott Cotton <[email protected]> wrote: >>> >> > >>> >> > I've got some questions about the interoperability guarantees of >>> >> > sync/atomic >>> >> > and cgo with stdatomic.h (C11 standard). >>> >> > >>> >> > So, the general question is: under what circumstances, if any, is >>> >> > using >>> >> > sync/atomic/CompareAndSwap >>> >> > safe with concurrent C stdatomic.h calls "on the same memory >>> >> > location". >>> >> > By >>> >> > "on the same memory location", I mean: the pointer representing the >>> >> > memory >>> >> > location is a "C" pointer (eg malloc'd), treated as a Go pointer in >>> >> > go >>> >> > by >>> >> > unsafe casting eg: >>> >> > >>> >> > C: uint32_t v; >>> >> > volatile uint32_t *p = (volatile uint32_t*)&v; >>> >> > >>> >> > Go: q := (*uint32)(unsafe.Pointer(C.p)) >>> >> > >>> >> > then some C thread calls intermittently >>> >> > atomic_compare_exchange_strong(p, expected, desired) >>> >> > >>> >> > and some goroutine calls intermittently >>> >> > atomic.CompareAndSwap(q, expected, desired) >>> >> > >>> >> > Then is the atomicity of the compare and swap preserved with the >>> >> > same >>> >> > guarantees as if it were all done in one of the two languages (C and >>> >> > Go)? >>> >> > >>> >> > I guess there's a "volatile" type qualifier with some questionable >>> >> > requirements in cgo environment: >>> >> > """ >>> >> > Any attempt to read or write to an object whose type is >>> >> > volatile-qualified >>> >> > through a non-volatile lvalue results in undefined behavior: >>> >> > """ >>> >> > (from https://en.cppreference.com/w/c/language/volatile) >>> >> > >>> >> > But I don't see how to preserve "volatile" in a cgo type referenced >>> >> > in >>> >> > Go >>> >> > code. Not sure if that makes a difference provided the memory >>> >> > location >>> >> > is >>> >> > the same, i.e. p is the same value as q above, since both sides (C >>> >> > and >>> >> > Go) >>> >> > would presumably use the respective atomic apis correctly. >>> >> >>> >> First I'll note that `volatile` in C is not useful for communicating >>> >> between separate threads. I wrote it about at >>> >> https://www.airs.com/blog/archives/154 and others have written similar >>> >> things. When thinking about communicating between multiple threads, >>> >> don't use the `volatile` qualifier. It doesn't help. >>> >> >>> >> That said, the exact semantics of the sync/atomic operations are not >>> >> written down (that is https://golang.org/issue/5045). But in general >>> >> you can treat Go's atomic.CompareAndSwapT(addr, old, new) as roughly >>> >> equivalent to C's __atomic_compare_exchange_n(addr, &old, new, false, >>> >> __ATOMIC_ACQ_REL, __ATOMIC_RELAXED). They should interoperate fine. >>> >> >>> >> Ian >>> > >>> > >>> > >>> > >>> > -- >>> > Scott Cotton >>> > President, IRI France SAS >>> > http://www.iri-labs.com >>> > >>> > >> >> >> >> >> -- >> Scott Cotton >> President, IRI France SAS >> http://www.iri-labs.com >> >> > > > > -- > Scott Cotton > President, IRI France SAS > http://www.iri-labs.com > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
