diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-04-05 19:41:22 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-04-05 19:41:22 -0400 |
| commit | 9efe21cb82b5dbe3b0b2ae4de4eccc64ecb94e95 (patch) | |
| tree | 7ff8833745d2f268f897f6fa4a27263b4a572245 /kernel/lockdep.c | |
| parent | de18836e447c2dc30120c0919b8db8ddc0401cc4 (diff) | |
| parent | 0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff) | |
Merge branch 'linus' into irq/threaded
Conflicts:
include/linux/irq.h
kernel/irq/handle.c
Diffstat (limited to 'kernel/lockdep.c')
| -rw-r--r-- | kernel/lockdep.c | 555 |
1 files changed, 290 insertions, 265 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 06b0c3568f0..81b5f33970b 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
| @@ -41,6 +41,8 @@ | |||
| 41 | #include <linux/utsname.h> | 41 | #include <linux/utsname.h> |
| 42 | #include <linux/hash.h> | 42 | #include <linux/hash.h> |
| 43 | #include <linux/ftrace.h> | 43 | #include <linux/ftrace.h> |
| 44 | #include <linux/stringify.h> | ||
| 45 | #include <trace/lockdep.h> | ||
| 44 | 46 | ||
| 45 | #include <asm/sections.h> | 47 | #include <asm/sections.h> |
| 46 | 48 | ||
| @@ -310,12 +312,14 @@ EXPORT_SYMBOL(lockdep_on); | |||
| 310 | #if VERBOSE | 312 | #if VERBOSE |
| 311 | # define HARDIRQ_VERBOSE 1 | 313 | # define HARDIRQ_VERBOSE 1 |
| 312 | # define SOFTIRQ_VERBOSE 1 | 314 | # define SOFTIRQ_VERBOSE 1 |
| 315 | # define RECLAIM_VERBOSE 1 | ||
| 313 | #else | 316 | #else |
| 314 | # define HARDIRQ_VERBOSE 0 | 317 | # define HARDIRQ_VERBOSE 0 |
| 315 | # define SOFTIRQ_VERBOSE 0 | 318 | # define SOFTIRQ_VERBOSE 0 |
| 319 | # define RECLAIM_VERBOSE 0 | ||
| 316 | #endif | 320 | #endif |
| 317 | 321 | ||
| 318 | #if VERBOSE || HARDIRQ_VERBOSE || SOFTIRQ_VERBOSE | 322 | #if VERBOSE || HARDIRQ_VERBOSE || SOFTIRQ_VERBOSE || RECLAIM_VERBOSE |
| 319 | /* | 323 | /* |
| 320 | * Quick filtering for interesting events: | 324 | * Quick filtering for interesting events: |
| 321 | */ | 325 | */ |
| @@ -430,30 +434,24 @@ atomic_t nr_find_usage_forwards_checks; | |||
| 430 | atomic_t nr_find_usage_forwards_recursions; | 434 | atomic_t nr_find_usage_forwards_recursions; |
| 431 | atomic_t nr_find_usage_backwards_checks; | 435 | atomic_t nr_find_usage_backwards_checks; |
| 432 | atomic_t nr_find_usage_backwards_recursions; | 436 | atomic_t nr_find_usage_backwards_recursions; |
| 433 | # define debug_atomic_inc(ptr) atomic_inc(ptr) | ||
| 434 | # define debug_atomic_dec(ptr) atomic_dec(ptr) | ||
| 435 | # define debug_atomic_read(ptr) atomic_read(ptr) | ||
| 436 | #else | ||
| 437 | # define debug_atomic_inc(ptr) do { } while (0) | ||
| 438 | # define debug_atomic_dec(ptr) do { } while (0) | ||
| 439 | # define debug_atomic_read(ptr) 0 | ||
| 440 | #endif | 437 | #endif |
| 441 | 438 | ||
| 442 | /* | 439 | /* |
| 443 | * Locking printouts: | 440 | * Locking printouts: |
| 444 | */ | 441 | */ |
| 445 | 442 | ||
| 443 | #define __USAGE(__STATE) \ | ||
| 444 | [LOCK_USED_IN_##__STATE] = "IN-"__stringify(__STATE)"-W", \ | ||
| 445 | [LOCK_ENABLED_##__STATE] = __stringify(__STATE)"-ON-W", \ | ||
| 446 | [LOCK_USED_IN_##__STATE##_READ] = "IN-"__stringify(__STATE)"-R",\ | ||
| 447 | [LOCK_ENABLED_##__STATE##_READ] = __stringify(__STATE)"-ON-R", | ||
| 448 | |||
| 446 | static const char *usage_str[] = | 449 | static const char *usage_str[] = |
| 447 | { | 450 | { |
| 448 | [LOCK_USED] = "initial-use ", | 451 | #define LOCKDEP_STATE(__STATE) __USAGE(__STATE) |
| 449 | [LOCK_USED_IN_HARDIRQ] = "in-hardirq-W", | 452 | #include "lockdep_states.h" |
| 450 | [LOCK_USED_IN_SOFTIRQ] = "in-softirq-W", | 453 | #undef LOCKDEP_STATE |
| 451 | [LOCK_ENABLED_SOFTIRQS] = "softirq-on-W", | 454 | [LOCK_USED] = "INITIAL USE", |
| 452 | [LOCK_ENABLED_HARDIRQS] = "hardirq-on-W", | ||
| 453 | [LOCK_USED_IN_HARDIRQ_READ] = "in-hardirq-R", | ||
| 454 | [LOCK_USED_IN_SOFTIRQ_READ] = "in-softirq-R", | ||
| 455 | [LOCK_ENABLED_SOFTIRQS_READ] = "softirq-on-R", | ||
| 456 | [LOCK_ENABLED_HARDIRQS_READ] = "hardirq-on-R", | ||
| 457 | }; | 455 | }; |
| 458 | 456 | ||
| 459 | const char * __get_key_name(struct lockdep_subclass_key *key, char *str) | 457 | const char * __get_key_name(struct lockdep_subclass_key *key, char *str) |
| @@ -461,46 +459,45 @@ const char * __get_key_name(struct lockdep_subclass_key *key, char *str) | |||
| 461 | return kallsyms_lookup((unsigned long)key, NULL, NULL, NULL, str); | 459 | return kallsyms_lookup((unsigned long)key, NULL, NULL, NULL, str); |
| 462 | } | 460 | } |
| 463 | 461 | ||
| 464 | void | 462 | static inline unsigned long lock_flag(enum lock_usage_bit bit) |
| 465 | get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4) | ||
| 466 | { | 463 | { |
| 467 | *c1 = '.', *c2 = '.', *c3 = '.', *c4 = '.'; | 464 | return 1UL << bit; |
| 468 | 465 | } | |
| 469 | if (class->usage_mask & LOCKF_USED_IN_HARDIRQ) | ||
| 470 | *c1 = '+'; | ||
| 471 | else | ||
| 472 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS) | ||
| 473 | *c1 = '-'; | ||
| 474 | 466 | ||
| 475 | if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ) | 467 | static char get_usage_char(struct lock_class *class, enum lock_usage_bit bit) |
| 476 | *c2 = '+'; | 468 | { |
| 477 | else | 469 | char c = '.'; |
| 478 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS) | ||
| 479 | *c2 = '-'; | ||
| 480 | 470 | ||
| 481 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) | 471 | if (class->usage_mask & lock_flag(bit + 2)) |
| 482 | *c3 = '-'; | 472 | c = '+'; |
| 483 | if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ) { | 473 | if (class->usage_mask & lock_flag(bit)) { |
| 484 | *c3 = '+'; | 474 | c = '-'; |
| 485 | if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) | 475 | if (class->usage_mask & lock_flag(bit + 2)) |
| 486 | *c3 = '?'; | 476 | c = '?'; |
| 487 | } | 477 | } |
| 488 | 478 | ||
| 489 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) | 479 | return c; |
| 490 | *c4 = '-'; | 480 | } |
| 491 | if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ) { | 481 | |
| 492 | *c4 = '+'; | 482 | void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]) |
| 493 | if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) | 483 | { |
| 494 | *c4 = '?'; | 484 | int i = 0; |
| 495 | } | 485 | |
| 486 | #define LOCKDEP_STATE(__STATE) \ | ||
| 487 | usage[i++] = get_usage_char(class, LOCK_USED_IN_##__STATE); \ | ||
| 488 | usage[i++] = get_usage_char(class, LOCK_USED_IN_##__STATE##_READ); | ||
| 489 | #include "lockdep_states.h" | ||
| 490 | #undef LOCKDEP_STATE | ||
| 491 | |||
| 492 | usage[i] = '\0'; | ||
| 496 | } | 493 | } |
| 497 | 494 | ||
| 498 | static void print_lock_name(struct lock_class *class) | 495 | static void print_lock_name(struct lock_class *class) |
| 499 | { | 496 | { |
| 500 | char str[KSYM_NAME_LEN], c1, c2, c3, c4; | 497 | char str[KSYM_NAME_LEN], usage[LOCK_USAGE_CHARS]; |
| 501 | const char *name; | 498 | const char *name; |
| 502 | 499 | ||
| 503 | get_usage_chars(class, &c1, &c2, &c3, &c4); | 500 | get_usage_chars(class, usage); |
| 504 | 501 | ||
| 505 | name = class->name; | 502 | name = class->name; |
| 506 | if (!name) { | 503 | if (!name) { |
| @@ -513,7 +510,7 @@ static void print_lock_name(struct lock_class *class) | |||
| 513 | if (class->subclass) | 510 | if (class->subclass) |
| 514 | printk("/%d", class->subclass); | 511 | printk("/%d", class->subclass); |
| 515 | } | 512 | } |
| 516 | printk("){%c%c%c%c}", c1, c2, c3, c4); | 513 | printk("){%s}", usage); |
| 517 | } | 514 | } |
| 518 | 515 | ||
| 519 | static void print_lockdep_cache(struct lockdep_map *lock) | 516 | static void print_lockdep_cache(struct lockdep_map *lock) |
| @@ -1263,9 +1260,49 @@ check_usage(struct task_struct *curr, struct held_lock *prev, | |||
| 1263 | bit_backwards, bit_forwards, irqclass); | 1260 | bit_backwards, bit_forwards, irqclass); |
| 1264 | } | 1261 | } |
| 1265 | 1262 | ||
| 1266 | static int | 1263 | static const char *state_names[] = { |
| 1267 | check_prev_add_irq(struct task_struct *curr, struct held_lock *prev, | 1264 | #define LOCKDEP_STATE(__STATE) \ |
| 1268 | struct held_lock *next) | 1265 | __stringify(__STATE), |
| 1266 | #include "lockdep_states.h" | ||
| 1267 | #undef LOCKDEP_STATE | ||
| 1268 | }; | ||
| 1269 | |||
| 1270 | static const char *state_rnames[] = { | ||
| 1271 | #define LOCKDEP_STATE(__STATE) \ | ||
| 1272 | __stringify(__STATE)"-READ", | ||
| 1273 | #include "lockdep_states.h" | ||
| 1274 | #undef LOCKDEP_STATE | ||
| 1275 | }; | ||
| 1276 | |||
| 1277 | static inline const char *state_name(enum lock_usage_bit bit) | ||
| 1278 | { | ||
| 1279 | return (bit & 1) ? state_rnames[bit >> 2] : state_names[bit >> 2]; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | static int exclusive_bit(int new_bit) | ||
| 1283 | { | ||
| 1284 | /* | ||
| 1285 | * USED_IN | ||
| 1286 | * USED_IN_READ | ||
| 1287 | * ENABLED | ||
| 1288 | * ENABLED_READ | ||
| 1289 | * | ||
| 1290 | * bit 0 - write/read | ||
| 1291 | * bit 1 - used_in/enabled | ||
| 1292 | * bit 2+ state | ||
| 1293 | */ | ||
| 1294 | |||
| 1295 | int state = new_bit & ~3; | ||
| 1296 | int dir = new_bit & 2; | ||
| 1297 | |||
| 1298 | /* | ||
| 1299 | * keep state, bit flip the direction and strip read. | ||
| 1300 | */ | ||
| 1301 | return state | (dir ^ 2); | ||
