Atomic reads in C

2020-05-23 18:43发布

According to Are C++ Reads and Writes of an int Atomic?, due to issues of processor caching, reads of ints (and thusly pointers--or so I assume) are not atomic in C. So, my question is is there some assembly that I could use to make the read atomic, or do I need to use a lock? I looked at several sets of libraries of atomic operations, and, as of yet, I am unable to find a function for an atomic read.

EDIT: Compiler: Clang 2.9 EDIT: Platform: x86 (64-bit)

Thanks.

2条回答
迷人小祖宗
2楼-- · 2020-05-23 19:23

In general, a simple atomic fetch isn't provided by atomic operations libraries because it's rarely used; you read the value and then do something with it, and the lock needs to be held during that something so that you know that the value you read hasn't changed. So instead of an atomic read, there is an atomic test-and-set of some kind (e.g. gcc's __sync_fetch_and_add()) which performs the lock, then you perform normal unsynchronized reads while you hold the lock.

The exception is device drivers where you may have to actually lock the system bus to get atomicity with respect to other devices on the bus, or when implementing the locking primitives for atomic operations libraries; these are inherently machine-specific, and you'll have to delve into assembly language. On x86 processors, there are various atomic instructions, plus a lock prefix that can be applied to most operations that access memory and hold a bus lock for the duration of the operation; other platforms (SPARC, MIPS, etc.) have similar mechanisms, but often the fine details differ. You will have to know the CPU you're programming for and quite probably have to know something about the machine's bus architecture in this case. And libraries for this rarely make sense, because you can't hold bus or memory locks across function entry/exit, and even with a macro library one has to be careful because of the implication that one could intersperse normal operations between macro calls when in fact that could break locking. It's almost always better to just code the entire critical section in assembly language.

查看更多
Explosion°爆炸
3楼-- · 2020-05-23 19:30

gcc has a set of atomic builtin functions, but it does not have a plain atomic fetch, however you could do something like __sync_fetch_and_add(&<your variable here>, 0); to work around that

GCC docs are here and there's that blog post above

EDIT: Ah, clang, I know LLVM IR has atomics in it, but I don't know if clang exposes them in any way, but it might be worth a shot to see if it complains about using the gcc ones, it might support them. EDIT: hmm it seems to have something... clang docs doesn't do as much as gcc though, and the docs seem to suggest it may also do the gcc ones.

查看更多
登录 后发表回答