As per http://lxr.free-electrons.com/source/arch/arm/include/asm/atomic.h#L31
static inline void atomic_add(int i, atomic_t *v)
41 {
42 unsigned long tmp;
43 int result;
44
45 prefetchw(&v->counter);
46 __asm__ __volatile__("@ atomic_add\n"
47 "1: ldrex %0, [%3]\n"
48 " add %0, %0, %4\n"
49 " strex %1, %0, [%3]\n"
50 " teq %1, #0\n"
51 " bne 1b"
52 : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
53 : "r" (&v->counter), "Ir" (i)
54 : "cc");
55 }
How can it be called "atomic" when it can be preempted?
You seem to be totally misunderstanding what an atomic operation is.
It should be obviously that if you look at a value x, see the value is 13, then call an atomic_add function that increases it by 5, the new result could be anything, because another thread could have changed the value before atomic_add was called. Likewise, if you check the result, it could again be anything because another thread could change the result between the atomic_add and your checking.
An atomic_add function guarantees to leave the value increased by that amount. And that's what it does. How this is achieved doesn't matter. If hundred threads call atomic_add (5, &x), then x will end up increased by 500. That's what matters.
That's the typical method how atomic operations are performed on processors like ARM and PowerPC that have an instruction that reserves a memory location and a store instruction checking that a reservation still exists.