diff options
| author | Corey Minyard <minyard@acm.org> | 2006-05-08 09:17:22 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-08 12:34:56 -0400 |
| commit | cdc60a4c8e71c4bcf67e83fac6c0cabd0ff19bfe (patch) | |
| tree | 204e3ab2ccaa9828d0ea71b43891729b216db7bf | |
| parent | 5192d84e4c32cd335fd572e5ff0712041f45f7e7 (diff) | |
[PATCH] x86_64: fix die_lock nesting
I noticed this when poking around in this area.
The oops_begin() function in x86_64 would only conditionally claim
the die_lock if the call is nested, but oops_end() would always
release the spinlock. This patch adds a nest count for the die lock
so that the release of the lock is only done on the final oops_end().
Signed-off-by: Corey Minyard <minyard@acm.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/x86_64/kernel/traps.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 2700b1375c1f..0ebb281aa178 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
| @@ -385,6 +385,7 @@ void out_of_line_bug(void) | |||
| 385 | 385 | ||
| 386 | static DEFINE_SPINLOCK(die_lock); | 386 | static DEFINE_SPINLOCK(die_lock); |
| 387 | static int die_owner = -1; | 387 | static int die_owner = -1; |
| 388 | static unsigned int die_nest_count; | ||
| 388 | 389 | ||
| 389 | unsigned __kprobes long oops_begin(void) | 390 | unsigned __kprobes long oops_begin(void) |
| 390 | { | 391 | { |
| @@ -399,6 +400,7 @@ unsigned __kprobes long oops_begin(void) | |||
| 399 | else | 400 | else |
| 400 | spin_lock(&die_lock); | 401 | spin_lock(&die_lock); |
| 401 | } | 402 | } |
| 403 | die_nest_count++; | ||
| 402 | die_owner = cpu; | 404 | die_owner = cpu; |
| 403 | console_verbose(); | 405 | console_verbose(); |
| 404 | bust_spinlocks(1); | 406 | bust_spinlocks(1); |
| @@ -409,7 +411,13 @@ void __kprobes oops_end(unsigned long flags) | |||
| 409 | { | 411 | { |
| 410 | die_owner = -1; | 412 | die_owner = -1; |
| 411 | bust_spinlocks(0); | 413 | bust_spinlocks(0); |
| 412 | spin_unlock_irqrestore(&die_lock, flags); | 414 | die_nest_count--; |
| 415 | if (die_nest_count) | ||
| 416 | /* We still own the lock */ | ||
| 417 | local_irq_restore(flags); | ||
| 418 | else | ||
| 419 | /* Nest count reaches zero, release the lock. */ | ||
| 420 | spin_unlock_irqrestore(&die_lock, flags); | ||
| 413 | if (panic_on_oops) | 421 | if (panic_on_oops) |
| 414 | panic("Oops"); | 422 | panic("Oops"); |
| 415 | } | 423 | } |
