History

rtmutex: Document pi chain walk

Add commentry to document the chain walk and the protection mechanisms and their scope.

Thomas Gleixner committed 12 years ago

Commit 3eb65ae1 parent a57594a1 file · +91 −9Browse files

Unified · Split

kernel/locking/rtmutex.c+91−9
@@ -337,6 +337,48 @@ static inline struct rt_mutex *task_blocked_on_lock(struct task_struct *p) · 336 unmodified lines
337337 * @top_task: the current top waiter
338338 *
339339 * 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;
340382 */
341383 static int rt_mutex_adjust_prio_chain(struct task_struct *task,
342384 int deadlock_detect,
@@ -361,6 +403,9 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, · 18 unmodified lines
361403 * carefully whether things change under us.
362404 */
363405 again:
406+ /*
407+ * We limit the lock chain length for each invocation.
408+ */
364409 if (++depth > max_lock_depth) {
365410 static int prev_max;
366411
@@ -378,13 +423,28 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, · 11 unmodified lines
378423
379424 return -EDEADLK;
380425 }
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+ */
381433 retry:
382434 /*
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 !
384436 */
385437 raw_spin_lock_irqsave(&task->pi_lock, flags);
386438
439+ /*
440+ * [2] Get the waiter on which @task is blocked on.
441+ */
387442 waiter = task->pi_blocked_on;
443+
444+ /*
445+ * [3] check_exit_conditions_1() protected by task->pi_lock.
446+ */
447+
388448 /*
389449 * Check whether the end of the boosting chain has been
390450 * 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, · 44 unmodified lines
435495 if (!detect_deadlock && waiter->prio == task->prio)
436496 goto out_unlock_pi;
437497
498+ /*
499+ * [4] Get the next lock
500+ */
438501 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+ */
439507 if (!raw_spin_trylock(&lock->wait_lock)) {
440508 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
441509 cpu_relax();
@@ -443,6 +511,9 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, · 1 unmodified line
443511 }
444512
445513 /*
514+ * [6] check_exit_conditions_2() protected by task->pi_lock and
515+ * lock->wait_lock.
516+ *
446517 * Deadlock detection. If the lock is the same as the original
447518 * lock which caused us to walk the lock chain or if the
448519 * 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, · 13 unmodified lines
462533 */
463534 prerequeue_top_waiter = rt_mutex_top_waiter(lock);
464535
465− /* Requeue the waiter in the lock waiter list. */
536+ /* [7] Requeue the waiter in the lock waiter list. */
466537 rt_mutex_dequeue(lock, waiter);
467538 waiter->prio = task->prio;
468539 rt_mutex_enqueue(lock, waiter);
469540
470− /* Release the task */
541+ /* [8] Release the task */
471542 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
472543 put_task_struct(task);
473544
474545 /*
546+ * [9] check_exit_conditions_3 protected by lock->wait_lock.
547+ *
475548 * We must abort the chain walk if there is no lock owner even
476549 * in the dead lock detection case, as we have nothing to
477550 * follow here. This is the end of the chain we are walking.
478551 */
479552 if (!rt_mutex_owner(lock)) {
480553 /*
481− * If the requeue above changed the top waiter, then we need
482− * to wake the new top waiter up to try to get the lock.
554+ * If the requeue [7] above changed the top waiter,
555+ * then we need to wake the new top waiter up to try
556+ * to get the lock.
483557 */
484558 if (prerequeue_top_waiter != rt_mutex_top_waiter(lock))
485559 wake_up_process(rt_mutex_top_waiter(lock)->task);
@@ -487,11 +561,12 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, · 1 unmodified line
487561 return 0;
488562 }
489563
490− /* Grab the next task, i.e. the owner of @lock */
564+ /* [10] Grab the next task, i.e. the owner of @lock */
491565 task = rt_mutex_owner(lock);
492566 get_task_struct(task);
493567 raw_spin_lock_irqsave(&task->pi_lock, flags);
494568
569+ /* [11] requeue the pi waiters if necessary */
495570 if (waiter == rt_mutex_top_waiter(lock)) {
496571 /*
497572 * The waiter became the new top (highest priority)
@@ -526,23 +601,30 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, · 28 unmodified lines
526601 }
527602
528603 /*
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+ *
529608 * Check whether the task which owns the current lock is pi
530609 * blocked itself. If yes we store a pointer to the lock for
531610 * the lock chain change detection above. After we dropped
532611 * task->pi_lock next_lock cannot be dereferenced anymore.
533612 */
534613 next_lock = task_blocked_on_lock(task);
535−
536− raw_spin_unlock_irqrestore(&task->pi_lock, flags);
537−
538614 /*
539615 * Store the top waiter of @lock for the end of chain walk
540616 * decision below.
541617 */
542618 top_waiter = rt_mutex_top_waiter(lock);
619+
620+ /* [13] Drop the locks */
621+ raw_spin_unlock_irqrestore(&task->pi_lock, flags);
543622 raw_spin_unlock(&lock->wait_lock);
544623
545624 /*
625+ * Make the actual exit decisions [12], based on the stored
626+ * values.
627+ *
546628 * We reached the end of the lock chain. Stop right here. No
547629 * point to go back just to figure that out.
548630 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t