I made a change in the blogger configuration to ease the later work when blogging. It is possible that older entries are not correctly formatted.

Tuesday, 2 September 2008

Kernel Locking mechanisms

An important aspect of programming in an environment with threads and processes is to prevent the different processes to interfer with the functionalities of other processes at the wrong time.

In linux, a number of methods are used to ensure that the data or code section of processes is not disturbed by others. These methods are:

  • atomic operations
  • spinlocks
  • semaphore
  • reader writer locks

These locks and mechanisms are in the kernel space. Other methods or locking mechanisms are used in the user space.

atomic operations

The idea behind atomic operations is to perform very basic changes on variable but which cannot be interfered by other processes, because they are so small. For this, special data type is used called: atomic_t.

On this data type, a number of atomic operations can be performed:

functiondescription
atomic_read(atomic_t *v) read the variable
atomic_set(atomic_t *v, int i) set the variable to i
atomic_add(int i, atomic_t *v)add i to the variable
atomic_sub(int i, atomic_t *v) substract i to the variable
atomic_sub_and_test(int i, atomic_t *v) substract i to the variable, return true value if 0 else return false
atomic_inc(atomic_t *v) increment the variable
atomic_inc_and_test(atomic_t *v)increment the variable, return true value if 0 else return false
atomic_dec(atomic_t *v) decrement the variable
atomic_dec_and_test(atomic_t *v)decrement the variable, return true value if 0 else return false
atomic_add_negative(int i, atomic_t *v)add i to the variable, and return true if its value is negative else false

Note that I discussed in another post the local variables for CPUs.

spinlocks

This kind of locking is used the most, above all to protect sections for short periods from access of other processes.

The kernel checks continuously whether a lock can be taken on the data. This is an example of busy waiting.

spinlocks are used in the following way:

spinlock_t lock = SPIN_LOCK_UNLOCKED;
...
spin_lock(&lock);
/** critical operations */
spin_unlock(&lock);

Due to the busy waiting, if the lock is not released... the computer may freeze, therefore spinlocks should not be used for long times.

semaphores

Unlike linux spinlocks, the kernel sleeps while waiting for the release of the semaphore. Contrary to spinlocks, this kind of structure should only be used for locks which have a certain length, while for short locks using linux spinlocks is recommended.
DECLARE_MUTEX(mutex);
....
down(&mutex);
/** critical section*/
up(&mutex);

The waiting processes then sleep in an uninterruptable state to wait for the release of the lock. The process cannot be woken up using signals during his sleep.

There are other alternatives to the down(&mutex) operation:
  • down_interruptible(&mutex) : the process can be woken up using signals
  • down_trylock(&mutex): if the lock was successful then the process goes on and does not sleep

For the user space, there are also futexes.... But this is another story.

reader writer locks

Using this kind of locks, processors can read the locked data structure but when the structure is to be written the structure can only be manipulated by one processor at a time.