Linux provides atomic operation for synchronization. Kernel provides atomic operation on integer and on individual bits.
These all atomic operation works on a specific data type atomic_t instead of int. There are couple of reason for using atomic_t instead of int. This special data type hides some architectural implementation and also to avoid any optimization done by the compiler.
The following are basic atomic integer operation on atomic data type.
atomic_t counter; //Declaration
atomic_t counter = ATOMIC_INIT(0); //Initialization
atomic_set(&counter, 10); //set operation
atomic_add(4, &counter); //add operation
atomic_inc(&counter); //increment operation
atomic_read(&counter); // read operation
In addition to above simple operation, linux provide additional function to be performed as atomic operation like..
atomic_dec_and_test(&counter); //decrement if result is 0 return true else false.
atomic_inc_and_test(&counter); //increment by 1 if result is 0 return true else false.
word size read are always atomic. Using atomic operation incur less overhead and less cache-line thrashing than complex synchronization method provide by linux.
Atomic bitwise operates on generic memory address that's why there is no equivalent like atomic_t used atomic integer operation.
unsigned long counter = 0;
set_bit(0, &counter); // set bit zero atomically.
set_bit(1, &counter); //set bit one atomically.
If your linux device driver code is already protect by larger locks or by other means and you want to leverage existing functionality of atomic operation there exists non_atomic_operation like
__set_bit
__chage_bit
__test_bit
These variants are faster, so be aware to use it wherever necessary.
Atomic operation is achieved with the help of processor instruction by adding LOCK_PREFIX to the instruction. Not all instruction can have LOCK_PREFIX, instruction such as ADD, INC, NOT, OR .... can have LOCK_PREFIX.
An example from linux
static inline void atomic_inc(atomic_t *v)
{
asm volatile(LOCK_PREFIX "incl %0" : "+m" (v->counter));
}
LOCK_PREFIX causes cache line lock on new generation processor and bus lock on old generation processor. Cache line locking performs better than bus lock.
Refer to atomic64_xx_ variant of function as well.
These all atomic operation works on a specific data type atomic_t instead of int. There are couple of reason for using atomic_t instead of int. This special data type hides some architectural implementation and also to avoid any optimization done by the compiler.
The following are basic atomic integer operation on atomic data type.
atomic_t counter; //Declaration
atomic_t counter = ATOMIC_INIT(0); //Initialization
atomic_set(&counter, 10); //set operation
atomic_add(4, &counter); //add operation
atomic_inc(&counter); //increment operation
atomic_read(&counter); // read operation
In addition to above simple operation, linux provide additional function to be performed as atomic operation like..
atomic_dec_and_test(&counter); //decrement if result is 0 return true else false.
atomic_inc_and_test(&counter); //increment by 1 if result is 0 return true else false.
word size read are always atomic. Using atomic operation incur less overhead and less cache-line thrashing than complex synchronization method provide by linux.
Atomic bitwise operates on generic memory address that's why there is no equivalent like atomic_t used atomic integer operation.
unsigned long counter = 0;
set_bit(0, &counter); // set bit zero atomically.
set_bit(1, &counter); //set bit one atomically.
If your linux device driver code is already protect by larger locks or by other means and you want to leverage existing functionality of atomic operation there exists non_atomic_operation like
__set_bit
__chage_bit
__test_bit
These variants are faster, so be aware to use it wherever necessary.
Atomic operation is achieved with the help of processor instruction by adding LOCK_PREFIX to the instruction. Not all instruction can have LOCK_PREFIX, instruction such as ADD, INC, NOT, OR .... can have LOCK_PREFIX.
An example from linux
static inline void atomic_inc(atomic_t *v)
{
asm volatile(LOCK_PREFIX "incl %0" : "+m" (v->counter));
}
LOCK_PREFIX causes cache line lock on new generation processor and bus lock on old generation processor. Cache line locking performs better than bus lock.
Refer to atomic64_xx_ variant of function as well.