Loading Documentation/lockdep-design.txt +17 −13 Original line number Diff line number Diff line Loading @@ -27,33 +27,37 @@ lock-class. State ----- The validator tracks lock-class usage history into 5 separate state bits: The validator tracks lock-class usage history into 4n + 1 separate state bits: - 'ever held in hardirq context' [ == hardirq-safe ] - 'ever held in softirq context' [ == softirq-safe ] - 'ever held with hardirqs enabled' [ == hardirq-unsafe ] - 'ever held with softirqs and hardirqs enabled' [ == softirq-unsafe ] - 'ever held in STATE context' - 'ever head as readlock in STATE context' - 'ever head with STATE enabled' - 'ever head as readlock with STATE enabled' Where STATE can be either one of (kernel/lockdep_states.h) - hardirq - softirq - reclaim_fs - 'ever used' [ == !unused ] When locking rules are violated, these 4 state bits are presented in the When locking rules are violated, these state bits are presented in the locking error messages, inside curlies. A contrived example: modprobe/2287 is trying to acquire lock: (&sio_locks[i].lock){--..}, at: [<c02867fd>] mutex_lock+0x21/0x24 (&sio_locks[i].lock){-.-...}, at: [<c02867fd>] mutex_lock+0x21/0x24 but task is already holding lock: (&sio_locks[i].lock){--..}, at: [<c02867fd>] mutex_lock+0x21/0x24 (&sio_locks[i].lock){-.-...}, at: [<c02867fd>] mutex_lock+0x21/0x24 The bit position indicates hardirq, softirq, hardirq-read, softirq-read respectively, and the character displayed in each indicates: The bit position indicates STATE, STATE-read, for each of the states listed above, and the character displayed in each indicates: '.' acquired while irqs disabled '+' acquired in irq context '-' acquired with irqs enabled '?' read acquired in irq context with irqs enabled. '?' acquired in irq context with irqs enabled. Unused mutexes cannot be part of the cause of an error. Loading kernel/lockdep.c +12 −12 Original line number Diff line number Diff line Loading @@ -487,25 +487,25 @@ static char get_usage_char(struct lock_class *class, enum lock_usage_bit bit) return c; } void get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4, char *c5, char *c6) void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]) { *c1 = get_usage_char(class, LOCK_USED_IN_HARDIRQ); *c2 = get_usage_char(class, LOCK_USED_IN_SOFTITQ); *c3 = get_usage_char(class, LOCK_USED_IN_HARDIRQ_READ); *c4 = get_usage_char(class, LOCK_USED_IN_SOFTITQ_READ); int i = 0; *c5 = get_usage_char(class, LOCK_USED_IN_RECLAIM_FS); *c6 = get_usage_char(class, LOCK_USED_IN_RECLAIM_FS_READ); #define LOCKDEP_STATE(__STATE) \ usage[i++] = get_usage_char(class, LOCK_USED_IN_##__STATE); \ usage[i++] = get_usage_char(class, LOCK_USED_IN_##__STATE##_READ); #include "lockdep_states.h" #undef LOCKDEP_STATE usage[i] = '\0'; } static void print_lock_name(struct lock_class *class) { char str[KSYM_NAME_LEN], c1, c2, c3, c4, c5, c6; char str[KSYM_NAME_LEN], usage[LOCK_USAGE_CHARS]; const char *name; get_usage_chars(class, &c1, &c2, &c3, &c4, &c5, &c6); get_usage_chars(class, usage); name = class->name; if (!name) { Loading @@ -518,7 +518,7 @@ static void print_lock_name(struct lock_class *class) if (class->subclass) printk("/%d", class->subclass); } printk("){%c%c%c%c%c%c}", c1, c2, c3, c4, c5, c6); printk("){%s}", usage); } static void print_lockdep_cache(struct lockdep_map *lock) Loading kernel/lockdep_internals.h +4 −3 Original line number Diff line number Diff line Loading @@ -70,9 +70,10 @@ enum { extern struct list_head all_lock_classes; extern struct lock_chain lock_chains[]; extern void get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4, char *c5, char *c6); #define LOCK_USAGE_CHARS (1+LOCK_USAGE_STATES/2) extern void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]); extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); Loading kernel/lockdep_proc.c +3 −3 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ static int l_show(struct seq_file *m, void *v) { struct lock_class *class = v; struct lock_list *entry; char c1, c2, c3, c4, c5, c6; char usage[LOCK_USAGE_CHARS]; if (v == SEQ_START_TOKEN) { seq_printf(m, "all lock classes:\n"); Loading @@ -100,8 +100,8 @@ static int l_show(struct seq_file *m, void *v) seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class)); #endif get_usage_chars(class, &c1, &c2, &c3, &c4, &c5, &c6); seq_printf(m, " %c%c%c%c%c%c", c1, c2, c3, c4, c5, c6); get_usage_chars(class, usage); seq_printf(m, " %s", usage); seq_printf(m, ": "); print_name(m, class); Loading Loading
Documentation/lockdep-design.txt +17 −13 Original line number Diff line number Diff line Loading @@ -27,33 +27,37 @@ lock-class. State ----- The validator tracks lock-class usage history into 5 separate state bits: The validator tracks lock-class usage history into 4n + 1 separate state bits: - 'ever held in hardirq context' [ == hardirq-safe ] - 'ever held in softirq context' [ == softirq-safe ] - 'ever held with hardirqs enabled' [ == hardirq-unsafe ] - 'ever held with softirqs and hardirqs enabled' [ == softirq-unsafe ] - 'ever held in STATE context' - 'ever head as readlock in STATE context' - 'ever head with STATE enabled' - 'ever head as readlock with STATE enabled' Where STATE can be either one of (kernel/lockdep_states.h) - hardirq - softirq - reclaim_fs - 'ever used' [ == !unused ] When locking rules are violated, these 4 state bits are presented in the When locking rules are violated, these state bits are presented in the locking error messages, inside curlies. A contrived example: modprobe/2287 is trying to acquire lock: (&sio_locks[i].lock){--..}, at: [<c02867fd>] mutex_lock+0x21/0x24 (&sio_locks[i].lock){-.-...}, at: [<c02867fd>] mutex_lock+0x21/0x24 but task is already holding lock: (&sio_locks[i].lock){--..}, at: [<c02867fd>] mutex_lock+0x21/0x24 (&sio_locks[i].lock){-.-...}, at: [<c02867fd>] mutex_lock+0x21/0x24 The bit position indicates hardirq, softirq, hardirq-read, softirq-read respectively, and the character displayed in each indicates: The bit position indicates STATE, STATE-read, for each of the states listed above, and the character displayed in each indicates: '.' acquired while irqs disabled '+' acquired in irq context '-' acquired with irqs enabled '?' read acquired in irq context with irqs enabled. '?' acquired in irq context with irqs enabled. Unused mutexes cannot be part of the cause of an error. Loading
kernel/lockdep.c +12 −12 Original line number Diff line number Diff line Loading @@ -487,25 +487,25 @@ static char get_usage_char(struct lock_class *class, enum lock_usage_bit bit) return c; } void get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4, char *c5, char *c6) void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]) { *c1 = get_usage_char(class, LOCK_USED_IN_HARDIRQ); *c2 = get_usage_char(class, LOCK_USED_IN_SOFTITQ); *c3 = get_usage_char(class, LOCK_USED_IN_HARDIRQ_READ); *c4 = get_usage_char(class, LOCK_USED_IN_SOFTITQ_READ); int i = 0; *c5 = get_usage_char(class, LOCK_USED_IN_RECLAIM_FS); *c6 = get_usage_char(class, LOCK_USED_IN_RECLAIM_FS_READ); #define LOCKDEP_STATE(__STATE) \ usage[i++] = get_usage_char(class, LOCK_USED_IN_##__STATE); \ usage[i++] = get_usage_char(class, LOCK_USED_IN_##__STATE##_READ); #include "lockdep_states.h" #undef LOCKDEP_STATE usage[i] = '\0'; } static void print_lock_name(struct lock_class *class) { char str[KSYM_NAME_LEN], c1, c2, c3, c4, c5, c6; char str[KSYM_NAME_LEN], usage[LOCK_USAGE_CHARS]; const char *name; get_usage_chars(class, &c1, &c2, &c3, &c4, &c5, &c6); get_usage_chars(class, usage); name = class->name; if (!name) { Loading @@ -518,7 +518,7 @@ static void print_lock_name(struct lock_class *class) if (class->subclass) printk("/%d", class->subclass); } printk("){%c%c%c%c%c%c}", c1, c2, c3, c4, c5, c6); printk("){%s}", usage); } static void print_lockdep_cache(struct lockdep_map *lock) Loading
kernel/lockdep_internals.h +4 −3 Original line number Diff line number Diff line Loading @@ -70,9 +70,10 @@ enum { extern struct list_head all_lock_classes; extern struct lock_chain lock_chains[]; extern void get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4, char *c5, char *c6); #define LOCK_USAGE_CHARS (1+LOCK_USAGE_STATES/2) extern void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]); extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); Loading
kernel/lockdep_proc.c +3 −3 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ static int l_show(struct seq_file *m, void *v) { struct lock_class *class = v; struct lock_list *entry; char c1, c2, c3, c4, c5, c6; char usage[LOCK_USAGE_CHARS]; if (v == SEQ_START_TOKEN) { seq_printf(m, "all lock classes:\n"); Loading @@ -100,8 +100,8 @@ static int l_show(struct seq_file *m, void *v) seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class)); #endif get_usage_chars(class, &c1, &c2, &c3, &c4, &c5, &c6); seq_printf(m, " %c%c%c%c%c%c", c1, c2, c3, c4, c5, c6); get_usage_chars(class, usage); seq_printf(m, " %s", usage); seq_printf(m, ": "); print_name(m, class); Loading