When implementing lock-free data structures and timing code it\'s often necessary to suppress the compiler\'s optimisations. Normally people do this using asm volatile
asm ("") does nothing (or at least, it's not supposed to do anything.
asm volatile ("") also does nothing.
asm ("" ::: "memory") is a simple compiler fence.
asm volatile ("" ::: "memory") AFAIK is the same as the previous. The volatile keyword tells the compiler that it's not allowed to move this assembly block. For example, it may be hoisted out of a loop if the compiler decides that the input values are the same in every invocation. I'm not really sure under what conditions the compiler will decide that it understands enough about the assembly to try to optimize its placement, but the volatile keyword suppresses that entirely. That said, I would be very surprised if the compiler attempted to move an asm statement that had no declared inputs or outputs.
Incidentally, volatile also prevents the compiler from deleting the expression if it decides that the output values are unused. This can only happen if there are output values though, so it doesn't apply to asm ("" ::: "memory").