diff options
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/lockdep.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index a266d5165b63..18f9f434d17e 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c | |||
| @@ -3157,6 +3157,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
| 3157 | hlock->waittime_stamp = 0; | 3157 | hlock->waittime_stamp = 0; |
| 3158 | hlock->holdtime_stamp = lockstat_clock(); | 3158 | hlock->holdtime_stamp = lockstat_clock(); |
| 3159 | #endif | 3159 | #endif |
| 3160 | hlock->pin_count = 0; | ||
| 3160 | 3161 | ||
| 3161 | if (check && !mark_irqflags(curr, hlock)) | 3162 | if (check && !mark_irqflags(curr, hlock)) |
| 3162 | return 0; | 3163 | return 0; |
| @@ -3403,6 +3404,8 @@ found_it: | |||
| 3403 | if (hlock->instance == lock) | 3404 | if (hlock->instance == lock) |
| 3404 | lock_release_holdtime(hlock); | 3405 | lock_release_holdtime(hlock); |
| 3405 | 3406 | ||
| 3407 | WARN(hlock->pin_count, "releasing a pinned lock\n"); | ||
| 3408 | |||
| 3406 | if (hlock->references) { | 3409 | if (hlock->references) { |
| 3407 | hlock->references--; | 3410 | hlock->references--; |
| 3408 | if (hlock->references) { | 3411 | if (hlock->references) { |
| @@ -3459,6 +3462,49 @@ static int __lock_is_held(struct lockdep_map *lock) | |||
| 3459 | return 0; | 3462 | return 0; |
| 3460 | } | 3463 | } |
| 3461 | 3464 | ||
| 3465 | static void __lock_pin_lock(struct lockdep_map *lock) | ||
| 3466 | { | ||
| 3467 | struct task_struct *curr = current; | ||
| 3468 | int i; | ||
| 3469 | |||
| 3470 | if (unlikely(!debug_locks)) | ||
| 3471 | return; | ||
| 3472 | |||
| 3473 | for (i = 0; i < curr->lockdep_depth; i++) { | ||
| 3474 | struct held_lock *hlock = curr->held_locks + i; | ||
| 3475 | |||
| 3476 | if (match_held_lock(hlock, lock)) { | ||
| 3477 | hlock->pin_count++; | ||
| 3478 | return; | ||
| 3479 | } | ||
| 3480 | } | ||
| 3481 | |||
| 3482 | WARN(1, "pinning an unheld lock\n"); | ||
| 3483 | } | ||
| 3484 | |||
| 3485 | static void __lock_unpin_lock(struct lockdep_map *lock) | ||
| 3486 | { | ||
| 3487 | struct task_struct *curr = current; | ||
| 3488 | int i; | ||
| 3489 | |||
| 3490 | if (unlikely(!debug_locks)) | ||
| 3491 | return; | ||
| 3492 | |||
| 3493 | for (i = 0; i < curr->lockdep_depth; i++) { | ||
| 3494 | struct held_lock *hlock = curr->held_locks + i; | ||
| 3495 | |||
| 3496 | if (match_held_lock(hlock, lock)) { | ||
| 3497 | if (WARN(!hlock->pin_count, "unpinning an unpinned lock\n")) | ||
| 3498 | return; | ||
| 3499 | |||
| 3500 | hlock->pin_count--; | ||
| 3501 | return; | ||
| 3502 | } | ||
| 3503 | } | ||
| 3504 | |||
| 3505 | WARN(1, "unpinning an unheld lock\n"); | ||
| 3506 | } | ||
| 3507 | |||
| 3462 | /* | 3508 | /* |
| 3463 | * Check whether we follow the irq-flags state precisely: | 3509 | * Check whether we follow the irq-flags state precisely: |
| 3464 | */ | 3510 | */ |
| @@ -3582,6 +3628,40 @@ int lock_is_held(struct lockdep_map *lock) | |||
| 3582 | } | 3628 | } |
| 3583 | EXPORT_SYMBOL_GPL(lock_is_held); | 3629 | EXPORT_SYMBOL_GPL(lock_is_held); |
| 3584 | 3630 | ||
| 3631 | void lock_pin_lock(struct lockdep_map *lock) | ||
| 3632 | { | ||
| 3633 | unsigned long flags; | ||
| 3634 | |||
| 3635 | if (unlikely(current->lockdep_recursion)) | ||
| 3636 | return; | ||
| 3637 | |||
| 3638 | raw_local_irq_save(flags); | ||
| 3639 | check_flags(flags); | ||
| 3640 | |||
| 3641 | current->lockdep_recursion = 1; | ||
| 3642 | __lock_pin_lock(lock); | ||
| 3643 | current->lockdep_recursion = 0; | ||
| 3644 | raw_local_irq_restore(flags); | ||
| 3645 | } | ||
| 3646 | EXPORT_SYMBOL_GPL(lock_pin_lock); | ||
| 3647 | |||
| 3648 | void lock_unpin_lock(struct lockdep_map *lock) | ||
| 3649 | { | ||
| 3650 | unsigned long flags; | ||
| 3651 | |||
| 3652 | if (unlikely(current->lockdep_recursion)) | ||
| 3653 | return; | ||
| 3654 | |||
| 3655 | raw_local_irq_save(flags); | ||
| 3656 | check_flags(flags); | ||
| 3657 | |||
| 3658 | current->lockdep_recursion = 1; | ||
| 3659 | __lock_unpin_lock(lock); | ||
| 3660 | current->lockdep_recursion = 0; | ||
| 3661 | raw_local_irq_restore(flags); | ||
| 3662 | } | ||
| 3663 | EXPORT_SYMBOL_GPL(lock_unpin_lock); | ||
| 3664 | |||
| 3585 | void lockdep_set_current_reclaim_state(gfp_t gfp_mask) | 3665 | void lockdep_set_current_reclaim_state(gfp_t gfp_mask) |
| 3586 | { | 3666 | { |
| 3587 | current->lockdep_reclaim_gfp = gfp_mask; | 3667 | current->lockdep_reclaim_gfp = gfp_mask; |
