diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2014-06-09 13:40:34 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2014-06-21 16:05:30 -0400 |
| commit | 3eb65aeadf701976b084e9171e16bb7d1e83fbb0 (patch) | |
| tree | 705c76a9057f352a84e0d4b0d367e80ffc691e66 /kernel/locking | |
| parent | a57594a13a446d1a6ab1dcd48339f799ce586843 (diff) | |
rtmutex: Document pi chain walk
Add commentry to document the chain walk and the protection mechanisms
and their scope.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/rtmutex.c | 100 |
1 files changed, 91 insertions, 9 deletions
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 3e9a75991e83..ed88021953df 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c | |||
| @@ -337,6 +337,48 @@ static inline struct rt_mutex *task_blocked_on_lock(struct task_struct *p) | |||
| 337 | * @top_task: the current top waiter | 337 | * @top_task: the current top waiter |
| 338 | * | 338 | * |
| 339 | * Returns 0 or -EDEADLK. | 339 | * Returns 0 or -EDEADLK. |
| 340 | * | ||
| 341 | * Chain walk basics and protection scope | ||
| 342 | * | ||
| 343 | * [R] refcount on task | ||
| 344 | * [P] task->pi_lock held | ||
| 345 | * [L] rtmutex->wait_lock held | ||
| 346 | * | ||
| 347 | * Step Description Protected by | ||
| 348 | * function arguments: | ||
| 349 | * @task [R] | ||
| 350 | * @orig_lock if != NULL @top_task is blocked on it | ||
| 351 | * @next_lock Unprotected. Cannot be | ||
| 352 | * dereferenced. Only used for | ||
| 353 | * comparison. | ||
| 354 | * @orig_waiter if != NULL @top_task is blocked on it | ||
| 355 | * @top_task current, or in case of proxy | ||
| 356 | * locking protected by calling | ||
| 357 | * code | ||
| 358 | * again: | ||
| 359 | * loop_sanity_check(); | ||
| 360 | * retry: | ||
| 361 | * [1] lock(task->pi_lock); [R] acquire [P] | ||
| 362 | * [2] waiter = task->pi_blocked_on; [P] | ||
| 363 | * [3] check_exit_conditions_1(); [P] | ||
| 364 | * [4] lock = waiter->lock; [P] | ||
| 365 | * [5] if (!try_lock(lock->wait_lock)) { [P] try to acquire [L] | ||
| 366 | * unlock(task->pi_lock); release [P] | ||
| 367 | * goto retry; | ||
| 368 | * } | ||
| 369 | * [6] check_exit_conditions_2(); [P] + [L] | ||
| 370 | * [7] requeue_lock_waiter(lock, waiter); [P] + [L] | ||
| 371 | * [8] unlock(task->pi_lock); release [P] | ||
| 372 | * put_task_struct(task); release [R] | ||
| 373 | * [9] check_exit_conditions_3(); [L] | ||
| 374 | * [10] task = owner(lock); [L] | ||
| 375 | * get_task_struct(task); [L] acquire [R] | ||
| 376 | * lock(task->pi_lock); [L] acquire [P] | ||
| 377 | * [11] requeue_pi_waiter(tsk, waiters(lock));[P] + [L] | ||
| 378 | * [12] check_exit_conditions_4(); [P] + [L] | ||
| 379 | * [13] unlock(task->pi_lock); release [P] | ||
| 380 | * unlock(lock->wait_lock); release [L] | ||
| 381 | * goto again; | ||
| 340 | */ | 382 | */ |
| 341 | static int rt_mutex_adjust_prio_chain(struct task_struct *task, | 383 | static int rt_mutex_adjust_prio_chain(struct task_struct *task, |
| 342 | int deadlock_detect, | 384 | int deadlock_detect, |
| @@ -361,6 +403,9 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 361 | * carefully whether things change under us. | 403 | * carefully whether things change under us. |
| 362 | */ | 404 | */ |
| 363 | again: | 405 | again: |
| 406 | /* | ||
| 407 | * We limit the lock chain length for each invocation. | ||
| 408 | */ | ||
| 364 | if (++depth > max_lock_depth) { | 409 | if (++depth > max_lock_depth) { |
| 365 | static int prev_max; | 410 | static int prev_max; |
| 366 | 411 | ||
| @@ -378,13 +423,28 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 378 | 423 | ||
| 379 | return -EDEADLK; | 424 | return -EDEADLK; |
| 380 | } | 425 | } |
| 426 | |||
| 427 | /* | ||
| 428 | * We are fully preemptible here and only hold the refcount on | ||
| 429 | * @task. So everything can have changed under us since the | ||
| 430 | * caller or our own code below (goto retry/again) dropped all | ||
| 431 | * locks. | ||
| 432 | */ | ||
| 381 | retry: | 433 | retry: |
| 382 | /* | 434 | /* |
| 383 | * Task can not go away as we did a get_task() before ! | 435 | * [1] Task cannot go away as we did a get_task() before ! |
| 384 | */ | 436 | */ |
| 385 | raw_spin_lock_irqsave(&task->pi_lock, flags); | 437 | raw_spin_lock_irqsave(&task->pi_lock, flags); |
| 386 | 438 | ||
| 439 | /* | ||
| 440 | * [2] Get the waiter on which @task is blocked on. | ||
| 441 | */ | ||
| 387 | waiter = task->pi_blocked_on; | 442 | waiter = task->pi_blocked_on; |
| 443 | |||
| 444 | /* | ||
| 445 | * [3] check_exit_conditions_1() protected by task->pi_lock. | ||
| 446 | */ | ||
| 447 | |||
| 388 | /* | 448 | /* |
| 389 | * Check whether the end of the boosting chain has been | 449 | * Check whether the end of the boosting chain has been |
| 390 | * reached or the state of the chain has changed while we | 450 | * reached or the state of the chain has changed while we |
| @@ -435,7 +495,15 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 435 | if (!detect_deadlock && waiter->prio == task->prio) | 495 | if (!detect_deadlock && waiter->prio == task->prio) |
| 436 | goto out_unlock_pi; | 496 | goto out_unlock_pi; |
| 437 | 497 | ||
| 498 | /* | ||
| 499 | * [4] Get the next lock | ||
| 500 | */ | ||
| 438 | lock = waiter->lock; | 501 | lock = waiter->lock; |
| 502 | /* | ||
| 503 | * [5] We need to trylock here as we are holding task->pi_lock, | ||
| 504 | * which is the reverse lock order versus the other rtmutex | ||
| 505 | * operations. | ||
| 506 | */ | ||
| 439 | if (!raw_spin_trylock(&lock->wait_lock)) { | 507 | if (!raw_spin_trylock(&lock->wait_lock)) { |
| 440 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 508 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
| 441 | cpu_relax(); | 509 | cpu_relax(); |
| @@ -443,6 +511,9 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 443 | } | 511 | } |
| 444 | 512 | ||
| 445 | /* | 513 | /* |
| 514 | * [6] check_exit_conditions_2() protected by task->pi_lock and | ||
| 515 | * lock->wait_lock. | ||
| 516 | * | ||
| 446 | * Deadlock detection. If the lock is the same as the original | 517 | * Deadlock detection. If the lock is the same as the original |
| 447 | * lock which caused us to walk the lock chain or if the | 518 | * lock which caused us to walk the lock chain or if the |
| 448 | * current lock is owned by the task which initiated the chain | 519 | * current lock is owned by the task which initiated the chain |
| @@ -462,24 +533,27 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 462 | */ | 533 | */ |
| 463 | prerequeue_top_waiter = rt_mutex_top_waiter(lock); | 534 | prerequeue_top_waiter = rt_mutex_top_waiter(lock); |
| 464 | 535 | ||
| 465 | /* Requeue the waiter in the lock waiter list. */ | 536 | /* [7] Requeue the waiter in the lock waiter list. */ |
| 466 | rt_mutex_dequeue(lock, waiter); | 537 | rt_mutex_dequeue(lock, waiter); |
| 467 | waiter->prio = task->prio; | 538 | waiter->prio = task->prio; |
| 468 | rt_mutex_enqueue(lock, waiter); | 539 | rt_mutex_enqueue(lock, waiter); |
| 469 | 540 | ||
| 470 | /* Release the task */ | 541 | /* [8] Release the task */ |
| 471 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 542 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
| 472 | put_task_struct(task); | 543 | put_task_struct(task); |
| 473 | 544 | ||
| 474 | /* | 545 | /* |
| 546 | * [9] check_exit_conditions_3 protected by lock->wait_lock. | ||
| 547 | * | ||
| 475 | * We must abort the chain walk if there is no lock owner even | 548 | * We must abort the chain walk if there is no lock owner even |
| 476 | * in the dead lock detection case, as we have nothing to | 549 | * in the dead lock detection case, as we have nothing to |
| 477 | * follow here. This is the end of the chain we are walking. | 550 | * follow here. This is the end of the chain we are walking. |
| 478 | */ | 551 | */ |
| 479 | if (!rt_mutex_owner(lock)) { | 552 | if (!rt_mutex_owner(lock)) { |
| 480 | /* | 553 | /* |
| 481 | * If the requeue above changed the top waiter, then we need | 554 | * If the requeue [7] above changed the top waiter, |
| 482 | * to wake the new top waiter up to try to get the lock. | 555 | * then we need to wake the new top waiter up to try |
| 556 | * to get the lock. | ||
| 483 | */ | 557 | */ |
| 484 | if (prerequeue_top_waiter != rt_mutex_top_waiter(lock)) | 558 | if (prerequeue_top_waiter != rt_mutex_top_waiter(lock)) |
| 485 | wake_up_process(rt_mutex_top_waiter(lock)->task); | 559 | wake_up_process(rt_mutex_top_waiter(lock)->task); |
| @@ -487,11 +561,12 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 487 | return 0; | 561 | return 0; |
| 488 | } | 562 | } |
| 489 | 563 | ||
| 490 | /* Grab the next task, i.e. the owner of @lock */ | 564 | /* [10] Grab the next task, i.e. the owner of @lock */ |
| 491 | task = rt_mutex_owner(lock); | 565 | task = rt_mutex_owner(lock); |
| 492 | get_task_struct(task); | 566 | get_task_struct(task); |
| 493 | raw_spin_lock_irqsave(&task->pi_lock, flags); | 567 | raw_spin_lock_irqsave(&task->pi_lock, flags); |
| 494 | 568 | ||
| 569 | /* [11] requeue the pi waiters if necessary */ | ||
| 495 | if (waiter == rt_mutex_top_waiter(lock)) { | 570 | if (waiter == rt_mutex_top_waiter(lock)) { |
| 496 | /* | 571 | /* |
| 497 | * The waiter became the new top (highest priority) | 572 | * The waiter became the new top (highest priority) |
| @@ -526,23 +601,30 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
| 526 | } | 601 | } |
| 527 | 602 | ||
| 528 | /* | 603 | /* |
| 604 | * [12] check_exit_conditions_4() protected by task->pi_lock | ||
| 605 | * and lock->wait_lock. The actual decisions are made after we | ||
| 606 | * dropped the locks. | ||
| 607 | * | ||
| 529 | * Check whether the task which owns the current lock is pi | 608 | * Check whether the task which owns the current lock is pi |
| 530 | * blocked itself. If yes we store a pointer to the lock for | 609 | * blocked itself. If yes we store a pointer to the lock for |
| 531 | * the lock chain change detection above. After we dropped | 610 | * the lock chain change detection above. After we dropped |
| 532 | * task->pi_lock next_lock cannot be dereferenced anymore. | 611 | * task->pi_lock next_lock cannot be dereferenced anymore. |
| 533 | */ | 612 | */ |
| 534 | next_lock = task_blocked_on_lock(task); | 613 | next_lock = task_blocked_on_lock(task); |
| 535 | |||
| 536 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | ||
| 537 | |||
| 538 | /* | 614 | /* |
| 539 | * Store the top waiter of @lock for the end of chain walk | 615 | * Store the top waiter of @lock for the end of chain walk |
| 540 | * decision below. | 616 | * decision below. |
| 541 | */ | 617 | */ |
| 542 | top_waiter = rt_mutex_top_waiter(lock); | 618 | top_waiter = rt_mutex_top_waiter(lock); |
| 619 | |||
| 620 | /* [13] Drop the locks */ | ||
| 621 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | ||
| 543 | raw_spin_unlock(&lock->wait_lock); | 622 | raw_spin_unlock(&lock->wait_lock); |
| 544 | 623 | ||
| 545 | /* | 624 | /* |
| 625 | * Make the actual exit decisions [12], based on the stored | ||
| 626 | * values. | ||
| 627 | * | ||
| 546 | * We reached the end of the lock chain. Stop right here. No | 628 | * We reached the end of the lock chain. Stop right here. No |
| 547 | * point to go back just to figure that out. | 629 | * point to go back just to figure that out. |
| 548 | */ | 630 | */ |
