Atomic ops are important because of the nature of the interruption - a context switch. What happens if you're in the middle of modifying something when another thread messes with your data? What if another thread tries reading something that you've made temporarily invalid?
When you're multiprogramming, an individual assembly instruction is atomic. The processor won't switch threads in the middle of an instruction. When you're multiprocessing, things are a little more difficult as two threads (on seperate processors) could access the same memory location simultaneously.
My situation is made a little more complicated by the fact that I'm targetting both Intel/AMD, and Mac G4/5 (PowerPC).
So what are we looking at exactly?
The X86 instruction set includes a few useful compound-operation instructions that can be performed atomically. The most useful of these is CMPXCHG; it compares the accumulator with the first argument, and then either copies the second argument to the first argument, or the first argument into the accumulator, depending on the result of the test. So, you can read a value into the accumulator, calculate some new value into another register, then store the new value if nothing else has changed the original value in the meantime. If the value's been changed, no store occurs, and you can respond accordingly (perhaps starting over with the new value). To be multiprocessor-safe, the LOCK prefix must be used. So it's not all /really/ lock-free, but locking a single instruction is going to be less damaging than locking a whole chunk of code with a mutex or something.
Under PPC, we don't have CMPXCHG as a single instruction; we do, however, have quite a nice mechanism using something called a 'reservation.' Basically, it becomes possible to stamp a memory address with the current thread/processor ID, saying "I'm using this." Stamping a memory address and loading the value from that address is an atomic operation (single instruction 'lwarx'). You can then do whatever you want to the value, taking as long as you need. When it's time to write the result back again, you use a special store instruction called 'stwcx,' which stores the value if the reservation is still present. If anyone else writes to that address, you lose your reservation.
So on both architectures the sequence goes something like this:
- Read the original value. (X86: make a copy, PPC: set reservation)
- Perform calculations on the value.
- Check that the (reservation|value) of the target is correct, and if so, write the value back.
- If the write failed, possibly repeat the process.