> You can do it all with library functions that just take regular int* (and so on).
It's not just about atomics, but you might still find Hans Boehm's 2005 paper "Threads Cannot Be Implemented As a Library" [0] interesting. It describes (among other things) correctness and performance issues that can arise if the compiler and/or language don't know about thread/atomic semantics.
[0]: https://web.stanford.edu/class/archive/cs/cs240/cs240.1236/o...
Yeah, it's all fun and games until you realize that you compiler may invent writes in order to eliminate a branch. Which is rather nonsensical, when you stop to think about it — surely an additional store to global can't be faster than a mispredicted branch?