Is changing a pointer considered an atomic action in C?

三世轮回 提交于 2019-11-27 04:45:14
Michael

As others have mentioned, there is nothing in the C language that guarantees this, and it is dependent on your platform.

On most contemporary desktop platforms, the read/write to a word-sized, aligned location will be atomic. But that really doesn't solve your problem, due to processor and compiler re-ordering of reads and writes.

For example, the following code is broken:

Thread A:

DoWork();
workDone = 1;

Thread B:

while(workDone != 0);

ReceiveResultsOfWork();

Although the write to workDone is atomic, on many systems there is no guarantee by the processor that the write to workDone will be visible to other processors before writes done via DoWork() are visible. The compiler may also be free to re-order the write to workDone to before the call to DoWork(). In both cases, ReceiveResultsOfWork() might start working on incomplete data.

Depending on your platform, you may need to insert memory fences and so on to ensure proper ordering. This can be very tricky to get right.

Or just use locks. Much simpler, much easier to verify as correct, and in most cases more than performant enough.

Dan Breslau

The C language says nothing about whether any operations are atomic. I've worked on microcontrollers with 8 bit buses and 16-bit pointers; any pointer operation on these systems would potentially be non-atomic. I think I remember Intel 386s (some of which had 16-bit buses) raising similar concerns. Likewise, I can imagine systems that have 64-bit CPUs, but 32-bit data buses, which might then entail similar concerns about non-atomic pointer operations. (I haven't checked to see whether any such systems actually exist.)

EDIT: Michael's answer is well worth reading. Bus size vs. pointer size is hardly the only consideration regarding atomicity; it was simply the first counterexample that came to mind for me.

You didn't mention a platform. So I think a slightly more accurate question would be

Are pointer changes guaranteed to be atomic?

The distinction is necessary because different C/C++ implementations may vary in this behavior. It's possible for a particular platform to guarantee atomic assignments and still be within the standard.

As to whether or not this is guaranteed overall in C/C++, the answer is No. The C standard makes no such guarantees. The only way to guarantee a pointer assignment is atomic is to use a platform specific mechanism to guarantee the atomicity of the assignment. For instance the Interlocked methods in Win32 will provide this guarantee.

Which platform are you working on?

The cop-out answer is that the C spec does not require a pointer assignment to be atomic, so you can't count on it being atomic.

The actual answer would be that it probably depends on your platform, compiler, and possibly the alignment of the stars on the day you wrote the program.

'normal' pointer modification isn't guaranteed to be atomic.

check 'Compare and Swap' (CAS) and other atomic operations, not a C standard, but most compilers have some access to the processor primitives. in the GNU gcc case, there are several built-in functions

The only thing guaranteed by the standard is the sig_atomic_t type.

As you've seen from the other answers, it is likely to be OK when targeting generic x86 architecture, but very risky with more "specialty" hardware.

If you're really desperate to know, you can compare sizeof(sig_atomic_t) to sizeof(int*) and see what they are you your target system.

Leonard

It turns out to be quite a complex question. I asked a similar question and read everything I got pointed to. I learned a lot about how caching works in modern architectures, and didn't find anything that was definitive. As others have said, if the bus width is smaller than the pointer bit-width, you might be in trouble. Specifically if the data falls across a cache-line boundary.

A prudent architecture will use a lock.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!