Question

I'm writing a toy operating system (so I cannot use any library, including the standard one), compiled with gcc, and I want to use atomics for some of the synchronization code. After some search, I found that gcc has two sets of builtins for atomic operations, __sync_* and __atomic_*, but there is no information as to the difference between the two.

What is the difference between these two besides the latter has a parameter for memory ordering? Is the __sync_ version equivalent to __atomic_ version with the sequential ordering? Is the __sync_ version deprecated in favor of the __atomic_ one?

Was it helpful?

Solution

Disclaimer: I have not used these primitives before. The following answer is based on my reading of the documentation and previous experience with concurrency.

Is the __sync_ version deprecated in favor of the __atomic_ one?

Yes, you should use __atomic and let the compiler fall back to __sync when necessary.

Is the __sync_ version equivalent to __atomic_ version with the sequential ordering?

No, the exact ordering guarantees are specified in the documentation for __sync. If you use __atomic, and the compiler chooses to fall back to __sync, then it will add code to meet the requested ordering guarantees.

From the documentation for __atomic:

Target architectures are encouraged to provide their own patterns for each of these built-in functions. If no target is provided, the original non-memory model set of ‘__sync’ atomic built-in functions are utilized, along with any required synchronization fences surrounding it in order to achieve the proper behavior. Execution in this case is subject to the same restrictions as those built-in functions.

A final word of caution: not all the __sync or __atomic operations can be implemented inline. The compiler may implement them as a call to an external function that is (presumably) implemented in the standard library. If you don't have access to the standard library, then you'll have to implement the missing functions yourself. Here is the relevant quote from the documentation:

If there is no pattern or mechanism to provide a lock free instruction sequence, a call is made to an external routine with the same parameters to be resolved at run time.

These primitives are a low-level mechanism, and you should understand what the compiler can and cannot do.

For an example of what code the compiler generates inline, see the related question: Atomic operations and code generation for gcc

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top