(ongoing) Linux死锁检测-Lockdep分析

lock class

lockdep 跟踪基本单元并不是每个锁的实例,而是锁类(lock class),在 Runtime locking correctness validator 这篇文章中 lockdep 作者 Ingo Molnar 解释了什么是锁类:

A class of locks is a group of locks that are logically the same with respect to locking rules, even if the locks may have multiple (possibly tens of thousands of) instantiations. For example a lock in the inode struct is one class, while each inode has its own instantiation of that lock class.

毫无疑问这种说法是准确的(毕竟是 Ingo 大佬),但是对于我这种小白来说未免过于抽象 :)。查阅代码后才理解了锁类的准确含义,以 spinlock 为例,在锁的初始化时定义了一个静态变量 __key,因此如果多个锁实例使用的 __key是同一个,那么它们就是同一个锁类,并采用哈希表来存储。

1
2
3
4
5
6
# define raw_spin_lock_init(lock)                   \
do { \
static struct lock_class_key __key; \
\
__raw_spin_lock_init((lock), #lock, &__key, LD_WAIT_SPIN); \
} while (0)

以如下代码片段为例,如果打开lockdep功能后:

  • xxx_function1()执行时 lockdep 会打印警告:[ INFO: possible recursive locking detected ] ,当然,这显然是一个误报,并不是真的会死锁。由于__key是静态定义的,因此只要锁初始化时的代码位置相同(正如 xxx_function1 中的st1.lock 和 st2.lock),它们就是一个锁类。
  • xxx_function2() 则不会打印任何警告,因为 st1.lock 和 st2.lock 对应不同的 __key。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
struct st {
spinlock_t lock;
int some_var;
}

xxx_function1() {
struct st st1, st2;

xxx_init(&st1);
xxx_init(&st2);

recursive_locking(&st1.lock, &st2.lock);
}

xxx_function2() {
struct st st1, st2;

spin_lock_init(&st1.lock);
spin_lock_init(&st2.lock);

recursive_locking(&st1.lock, &st2.lock);

}

xxx_init(struct st *a)
{
spin_lock_init(&a->lock);
}

void recursive_locking(spinlock_t *a1, spinlock_t *a2)
{
spin_lock(a1);
spin_lock(a2);

spin_unlock(a2);
spin_unlock(a1);
}

lock usage state

待完善

lockdep 检查规则

待完善

lockdep 代码分析

待完善


(ongoing) Linux死锁检测-Lockdep分析
https://yuliao0214.github.io/2022/09/07/lockdep-design/
Author
Yu Liao
Posted on
September 7, 2022
Licensed under