Locking Mechanism

Table of Contents

1 Kernel locking mechanism

The kernel provides several locking mechanisms. The most important are:

  • Semaphore
  • Mutex
  • Spinlock

2 Mutex

The required header is include/linux/mutex.h

2.1 Mutex API

2.1.1 Declare

  • Statically:
    DEFINE_MUTE(my_mutex);
  • Dynamically:
    struct mutex my_mutex;
    mutex_init(&my_mutex);

2.1.2 Acquire and release

  • Lock:
    void mutex_lock(struct mutex *lock);
    int __must_check mutex_lock_interruptible(struct mutex *lock);
    int __must_check mutex_lock_killable(struct mutex *lock);
  • Unlock:
    void mutex_unlock(struct mutex *lock);

You can use mutex_is_locked() to check whether a mutex is locked or not:
bool mutex_is_locked(struct mutex *lock);

There is also mutex_trylock(), that acquires the mutex if it is not already locked, and return1; otherwise, it returns 0:
int mutex_trylock(struct mutex *lock);

Here is an example of a muex implementation:

struct mutex my_mutex;
mutex_init(&my_mutex);

/* inside a work or a thread */
mutex_lock(&my_mutex);
access_shared_memory();
mutex_unlock(&my_mutex);

3 Spinelock

spin_lock() and spin_lock_irqsave() are used to acquire a spinlock, all of them will disable the preemption on the process, Since spin_lock_irqsave also disable the interrupts on the CPU. If you do not know in advance what system you will write the driver for, it is recommended you acquire a spinlock using spin_lock_irqsave(), which disables interrupts on the current process before the spinlock. spin_lock_irqsave() internally calls local_irq_save().

The following is an example:

#include <linux/spinlock.h>

/* some where */
spinlock_t my_spinlock;
spin_lock_init(&my_spinlock);

static irqreturn_t my_irq_handler(int irq, void *data)
{
	unsigned long status, flags;

	spin_lock_irqsave(&my_spinlock, flags);
	status = access_shared_resources();
	spin_unlock_irqrestore(&my_spinlock, flags);

	return IRQ_HANDLED;
}

4 Spinlock versus mutexes

Uesd for concurrency in the kernel, spinlocks and mutexes each have their own objectives.

  • Mutexes protect the process's critical resource, whereas spinlock protects the IRQ handler's critical sections.
  • Mutexes put contenders to sleep until the lock is acquired, whereas spinlocks infinitely spin in a loop(consuming CPU) until the lock is acquired.
  • Because of the previous poing, you can't hold spinlock for a long time, since waiters will waste CPU time waiting for the lock, whereas a mutex can be held as long as the resource needs to be protected, since contenders are put to sleep in a wait queue.

Author: Yanqing Li

Created: 2019-04-20 六 22:11

Validate