Online Linux Driver Verification Service (alpha)

0039

RULE_ERROR

Usage of spin lock and unlock functions

Summary

It’s not allowed to acquire spin_lock twice. It’s not allowed to release not acquired spin_lock. At the end all spin_lock should be released. It’s not allowed to re-release a lock by spin_unlock/spin_unlock_irqrestore functions.

Description

Unlike other operating systems spin-locks in Linux are not recursive. So if a thread tries to acquire a lock it has already acquired then this thread begins a periodical check and waits till it releases the lock. This leads to a deadlocks. The situation is not often in its explicit form, but it is widely spread in an implicit form when some function (external function usually) tries to acquire a lock that has already been acquired by the module.

It’s not allowed to acquire spin_lock twice. It’s not allowed to release not acquired spin_lock. At the end all spin_lock should be released. It’s not allowed to re-release a lock by spin_unlock/spin_unlock_irqrestore functions.

Links:

bugfix example

Example

Incorrect example (2.6.24 -> 2.6.25, drivers/char/specialix.c):

@@ 2109
sx_out(bp, CD186x_CAR, port_No(port));
/* releasing a lock */
spin_unlock_irqrestore(&bp->lock, flags); 
if (I_IXOFF(tty)) {
    /* in some cases double call is possible */
    spin_unlock_irqrestore(&bp->lock, flags);
    sx_wait_CCR(bp);
    spin_lock_irqsave(&bp->lock, flags);
    sx_out(bp, CD186x_CCR, CCR_SSCH2);

Notes

It's required to accumulate information about the usage of the locks inside external functions:

  • statistic data for a number of low-level functions it's required to explicitly enumerate locks they are using
  • dynamically-generated data it's required to analyze source-code of the called functions to make a list of acquired locks