diff options
Diffstat (limited to 'kernel/rtmutex.c')
| -rw-r--r-- | kernel/rtmutex.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c index 3e13a1e5856f..4ab17da46fd8 100644 --- a/kernel/rtmutex.c +++ b/kernel/rtmutex.c | |||
| @@ -251,6 +251,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 251 | 251 | ||
| 252 | /* Grab the next task */ | 252 | /* Grab the next task */ |
| 253 | task = rt_mutex_owner(lock); | 253 | task = rt_mutex_owner(lock); |
| 254 | get_task_struct(task); | ||
| 254 | spin_lock_irqsave(&task->pi_lock, flags); | 255 | spin_lock_irqsave(&task->pi_lock, flags); |
| 255 | 256 | ||
| 256 | if (waiter == rt_mutex_top_waiter(lock)) { | 257 | if (waiter == rt_mutex_top_waiter(lock)) { |
| @@ -269,7 +270,6 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 269 | __rt_mutex_adjust_prio(task); | 270 | __rt_mutex_adjust_prio(task); |
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | get_task_struct(task); | ||
| 273 | spin_unlock_irqrestore(&task->pi_lock, flags); | 273 | spin_unlock_irqrestore(&task->pi_lock, flags); |
| 274 | 274 | ||
| 275 | top_waiter = rt_mutex_top_waiter(lock); | 275 | top_waiter = rt_mutex_top_waiter(lock); |
| @@ -409,7 +409,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, | |||
| 409 | struct task_struct *owner = rt_mutex_owner(lock); | 409 | struct task_struct *owner = rt_mutex_owner(lock); |
| 410 | struct rt_mutex_waiter *top_waiter = waiter; | 410 | struct rt_mutex_waiter *top_waiter = waiter; |
| 411 | unsigned long flags; | 411 | unsigned long flags; |
| 412 | int boost = 0, res; | 412 | int chain_walk = 0, res; |
| 413 | 413 | ||
| 414 | spin_lock_irqsave(¤t->pi_lock, flags); | 414 | spin_lock_irqsave(¤t->pi_lock, flags); |
| 415 | __rt_mutex_adjust_prio(current); | 415 | __rt_mutex_adjust_prio(current); |
| @@ -433,25 +433,23 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, | |||
| 433 | plist_add(&waiter->pi_list_entry, &owner->pi_waiters); | 433 | plist_add(&waiter->pi_list_entry, &owner->pi_waiters); |
| 434 | 434 | ||
| 435 | __rt_mutex_adjust_prio(owner); | 435 | __rt_mutex_adjust_prio(owner); |
| 436 | if (owner->pi_blocked_on) { | 436 | if (owner->pi_blocked_on) |
| 437 | boost = 1; | 437 | chain_walk = 1; |
| 438 | /* gets dropped in rt_mutex_adjust_prio_chain()! */ | ||
| 439 | get_task_struct(owner); | ||
| 440 | } | ||
| 441 | spin_unlock_irqrestore(&owner->pi_lock, flags); | ||
| 442 | } | ||
| 443 | else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) { | ||
| 444 | spin_lock_irqsave(&owner->pi_lock, flags); | ||
| 445 | if (owner->pi_blocked_on) { | ||
| 446 | boost = 1; | ||
| 447 | /* gets dropped in rt_mutex_adjust_prio_chain()! */ | ||
| 448 | get_task_struct(owner); | ||
| 449 | } | ||
| 450 | spin_unlock_irqrestore(&owner->pi_lock, flags); | 438 | spin_unlock_irqrestore(&owner->pi_lock, flags); |
| 451 | } | 439 | } |
| 452 | if (!boost) | 440 | else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) |
| 441 | chain_walk = 1; | ||
| 442 | |||
| 443 | if (!chain_walk) | ||
| 453 | return 0; | 444 | return 0; |
| 454 | 445 | ||
| 446 | /* | ||
| 447 | * The owner can't disappear while holding a lock, | ||
| 448 | * so the owner struct is protected by wait_lock. | ||
| 449 | * Gets dropped in rt_mutex_adjust_prio_chain()! | ||
| 450 | */ | ||
| 451 | get_task_struct(owner); | ||
| 452 | |||
| 455 | spin_unlock(&lock->wait_lock); | 453 | spin_unlock(&lock->wait_lock); |
| 456 | 454 | ||
| 457 | res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, | 455 | res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, |
| @@ -532,7 +530,7 @@ static void remove_waiter(struct rt_mutex *lock, | |||
| 532 | int first = (waiter == rt_mutex_top_waiter(lock)); | 530 | int first = (waiter == rt_mutex_top_waiter(lock)); |
| 533 | struct task_struct *owner = rt_mutex_owner(lock); | 531 | struct task_struct *owner = rt_mutex_owner(lock); |
| 534 | unsigned long flags; | 532 | unsigned long flags; |
| 535 | int boost = 0; | 533 | int chain_walk = 0; |
| 536 | 534 | ||
| 537 | spin_lock_irqsave(¤t->pi_lock, flags); | 535 | spin_lock_irqsave(¤t->pi_lock, flags); |
| 538 | plist_del(&waiter->list_entry, &lock->wait_list); | 536 | plist_del(&waiter->list_entry, &lock->wait_list); |
| @@ -554,19 +552,20 @@ static void remove_waiter(struct rt_mutex *lock, | |||
| 554 | } | 552 | } |
| 555 | __rt_mutex_adjust_prio(owner); | 553 | __rt_mutex_adjust_prio(owner); |
| 556 | 554 | ||
| 557 | if (owner->pi_blocked_on) { | 555 | if (owner->pi_blocked_on) |
| 558 | boost = 1; | 556 | chain_walk = 1; |
| 559 | /* gets dropped in rt_mutex_adjust_prio_chain()! */ | 557 | |
| 560 | get_task_struct(owner); | ||
| 561 | } | ||
| 562 | spin_unlock_irqrestore(&owner->pi_lock, flags); | 558 | spin_unlock_irqrestore(&owner->pi_lock, flags); |
| 563 | } | 559 | } |
| 564 | 560 | ||
| 565 | WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); | 561 | WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); |
| 566 | 562 | ||
| 567 | if (!boost) | 563 | if (!chain_walk) |
| 568 | return; | 564 | return; |
| 569 | 565 | ||
| 566 | /* gets dropped in rt_mutex_adjust_prio_chain()! */ | ||
| 567 | get_task_struct(owner); | ||
| 568 | |||
| 570 | spin_unlock(&lock->wait_lock); | 569 | spin_unlock(&lock->wait_lock); |
| 571 | 570 | ||
| 572 | rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current); | 571 | rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current); |
| @@ -592,10 +591,10 @@ void rt_mutex_adjust_pi(struct task_struct *task) | |||
| 592 | return; | 591 | return; |
| 593 | } | 592 | } |
| 594 | 593 | ||
| 595 | /* gets dropped in rt_mutex_adjust_prio_chain()! */ | ||
| 596 | get_task_struct(task); | ||
| 597 | spin_unlock_irqrestore(&task->pi_lock, flags); | 594 | spin_unlock_irqrestore(&task->pi_lock, flags); |
| 598 | 595 | ||
| 596 | /* gets dropped in rt_mutex_adjust_prio_chain()! */ | ||
| 597 | get_task_struct(task); | ||
| 599 | rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task); | 598 | rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task); |
| 600 | } | 599 | } |
| 601 | 600 | ||
