Live data from Hacker News

There's No Such Thing as “Implicitly Atomic”

belkadan.com

41–47 of 47 posts

Re: There's No Such Thing as “Implicitly Atomic”

#41
post #36

Earlier quoted context omitted.

I wanted to avoid unsafe. Because unsafe introduces conceptual complications and it seemed to be simpler to avoid that in an example.

Well you can't have a memory race without unsafe. The goal of the example was to show undefined behaviour.

Ah, you wanted to show an example in Rust with unsafe where atomicity was not guaranteed.

Re: There's No Such Thing as “Implicitly Atomic”

#42
post #4

The FreeBSD kernel only runs on platforms where 32-bit sized and aligned ordinary loads and stores are atomic; this is a requirement that it demands of the hardware. This may not be (extremely) portable, or may not work for Swift, or userspace under some very weird runtime environments, but it is true of the vast majority of CPU hardware out there.

This. Even Java guarantees this. The only practical places this is can be a problem are maybe 8/16bit microcontrollers. What the hell is TFA talking about?

Re: There's No Such Thing as “Implicitly Atomic”

#43
post #13

Earlier quoted context omitted.

Go's memory model is more constrained than C, C++, and Swift and this case is specifically addressed: https://go.dev/ref/mem#restrictions . "...each read of a single-word-sized or sub-word-sized memory location must observe a value actually written to that location"

Yeah, but there is no guarantee that a write of one goroutine will eventually become visible to other goroutines. So in practice the runtime expects stronger guarantees.

Memory models don't usually explicitly guarantee that writes "eventually become visible". They're usually written as ordering guarantees for when a write becomes visible, such as happens-before relationships. Obviously, for multithreaded programs to be useful, the writes have to eventually become visible to other threads/groroutines just like you want all sorts of other operations to happen in finite time that are not explicitly guaranteed by standards (like whether a thread/goroutine eventually starts.)

Re: There's No Such Thing as “Implicitly Atomic”

#44
post #42
post #4

The FreeBSD kernel only runs on platforms where 32-bit sized and aligned ordinary loads and stores are atomic; this is a requirement that it demands of the hardware. This may not be (extremely) portable, or may not work for Swift, or userspace under some very weird runtime environments, but it is true of the vast majority of CPU hardware out there.

This. Even Java guarantees this. The only practical places this is can be a problem are maybe 8/16bit microcontrollers. What the hell is TFA talking about?

It's not guaranteed in C and C++. The author pointed out an example where an arm64 compiler split a word-size write into 2 store instructions because it resulted in smaller code size.

Re: There's No Such Thing as “Implicitly Atomic”

#45
post #13

Earlier quoted context omitted.

Yeah, but there is no guarantee that a write of one goroutine will eventually become visible to other goroutines. So in practice the runtime expects stronger guarantees.

Memory models don't usually explicitly guarantee that writes "eventually become visible". They're usually written as ordering guarantees for when a write becomes visible, such as happens-before relationships. Obviously, for multithreaded programs to be useful, the writes have to eventually become visible to other threads/groroutines just like you want all sorts of other operations to happen in finite time that are no…

Well said. But how much finite time are we talking about (for writes to become visible)? Does it differ between architectures? Can there be extreme edge cases?

Re: There's No Such Thing as “Implicitly Atomic”

#46
post #23

Earlier quoted context omitted.

The linked thread doesn't say exactly how, but I can construct some way in my head: Final 32-bit store effectively stores two 16-bit values or'ed together as high-16 and low-16. You can get this without any shifting and simple addition and the proper values. If these two sixteen bit values are calculated along two very different paths which have different lengths, the compiler might opt to spill one of them early, on…

Or if I understood it correctly, there are platforms like CHERI which have metadata about memory, for example to detect invalid access. This metadata might race with the data itself.

The hardware must, and does, ensure that the metadata (both addressable - bounds, permissions, etc - and non-addressable - the tag) is kept atomic with the address portion of the capability, as otherwise you would be able to forge capabilities via such races. That is, you will never see a torn capability write, and the tag is updated atomically with every write, capability or not. This is easy to do since capabilities are always within a single cache line.

Re: There's No Such Thing as “Implicitly Atomic”

#47
post #38
post #9

Earlier quoted context omitted.

So FreeBSD can run only on simple single 32-bit CPUs with no cache (or no registers)? I would argue that outside of a few select embedded controllers there's almost no hardware out there that meets that requirement.

No, you’re making an unstated bogus assumption somewhere but I’m not sure which one.

It's the assumption that the hardware operation is the same as the C abstract machine operation.

Hint: they're not, and that causes all kinds of subtle problem when programmers assume they are, especially when it comes to atomicity. The compiler caches a value in a register and two threads synchronize on that value? Boom. Or maybe no boom when one was expected.

Post reply on HN