From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756445AbbCMPcm (ORCPT ); Fri, 13 Mar 2015 11:32:42 -0400 Received: from smtprelay0169.hostedemail.com ([216.40.44.169]:41243 "EHLO smtprelay.hostedemail.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755887AbbCMPPT (ORCPT ); Fri, 13 Mar 2015 11:15:19 -0400 X-Session-Marker: 6E657665747340676F6F646D69732E6F7267 X-Spam-Summary: 2,0,0,,d41d8cd98f00b204,,::::::::::::::,RULES_HIT:355:379:871:988:989:1183:1260:1277:1312:1313:1314:1345:1516:1518:1519:1522:1535:1593:1594:1595:1596:1692:1730:1747:1777:1792:2392:2393:2559:2562:2828:3138:3139:3140:3141:3142:3876:3877:4117:5007:6114:6261:6642:6748:7281:7901:10848:11604:11914:12517:12519:13895:14394:21080,0,RBL:none,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fn,MSBL:0,DNSBL:none,Custom_rules:0:1:0 X-HE-Tag: curve96_6845a648d0455 X-Filterd-Recvd-Size: 6033 Message-Id: <20150313151515.852935348@goodmis.org> User-Agent: quilt/0.61-1 Date: Fri, 13 Mar 2015 11:15:00 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-rt-users Cc: Thomas Gleixner , Carsten Emde , Sebastian Andrzej Siewior , John Kacur , Paul Gortmaker Subject: [PATCH RT 06/31] rtmutex: Clarify the boost/deboost part References: <20150313151454.809081378@goodmis.org> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Disposition: inline; filename=0006-rtmutex-Clarify-the-boost-deboost-part.patch Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.10.70-rt75-rc1 stable review patch. If anyone has any objections, please let me know. ------------------ From: Thomas Gleixner upstream commit: a57594a13a446d1a6ab1dcd48339f799ce586843 Add a separate local variable for the boost/deboost logic to make the code more readable. Add comments where appropriate. Signed-off-by: Thomas Gleixner Reviewed-by: Steven Rostedt Signed-off-by: Steven Rostedt Conflicts: kernel/rtmutex.c --- kernel/rtmutex.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c index eb748b542095..4384a96bd0a0 100644 --- a/kernel/rtmutex.c +++ b/kernel/rtmutex.c @@ -276,9 +276,10 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, struct rt_mutex_waiter *orig_waiter, struct task_struct *top_task) { - struct rt_mutex *lock; struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter; + struct rt_mutex_waiter *prerequeue_top_waiter; int detect_deadlock, ret = 0, depth = 0; + struct rt_mutex *lock; unsigned long flags; detect_deadlock = debug_rt_mutex_detect_deadlock(orig_waiter, @@ -385,9 +386,14 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, goto out_unlock_pi; } - top_waiter = rt_mutex_top_waiter(lock); + /* + * Store the current top waiter before doing the requeue + * operation on @lock. We need it for the boost/deboost + * decision below. + */ + prerequeue_top_waiter = rt_mutex_top_waiter(lock); - /* Requeue the waiter */ + /* Requeue the waiter in the lock waiter list. */ rt_mutex_dequeue(lock, waiter); waiter->list_entry.prio = task->prio; rt_mutex_enqueue(lock, waiter); @@ -396,6 +402,11 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, raw_spin_unlock_irqrestore(&task->pi_lock, flags); put_task_struct(task); + /* + * We must abort the chain walk if there is no lock owner even + * in the dead lock detection case, as we have nothing to + * follow here. This is the end of the chain we are walking. + */ if (!rt_mutex_owner(lock)) { struct rt_mutex_waiter *lock_top_waiter; @@ -404,29 +415,48 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, * to wake the new top waiter up to try to get the lock. */ lock_top_waiter = rt_mutex_top_waiter(lock); - if (top_waiter != lock_top_waiter) + if (prerequeue_top_waiter != lock_top_waiter) rt_mutex_wake_waiter(lock_top_waiter); raw_spin_unlock(&lock->wait_lock); return 0; } - /* Grab the next task */ + /* Grab the next task, i.e. the owner of @lock */ task = rt_mutex_owner(lock); get_task_struct(task); raw_spin_lock_irqsave(&task->pi_lock, flags); if (waiter == rt_mutex_top_waiter(lock)) { - /* Boost the owner */ - rt_mutex_dequeue_pi(task, top_waiter); + /* + * The waiter became the new top (highest priority) + * waiter on the lock. Replace the previous top waiter + * in the owner tasks pi waiters list with this waiter + * and adjust the priority of the owner. + */ + rt_mutex_dequeue_pi(task, prerequeue_top_waiter); rt_mutex_enqueue_pi(task, waiter); __rt_mutex_adjust_prio(task); - } else if (top_waiter == waiter) { - /* Deboost the owner */ + } else if (prerequeue_top_waiter == waiter) { + /* + * The waiter was the top waiter on the lock, but is + * no longer the top prority waiter. Replace waiter in + * the owner tasks pi waiters list with the new top + * (highest priority) waiter and adjust the priority + * of the owner. + * The new top waiter is stored in @waiter so that + * @waiter == @top_waiter evaluates to true below and + * we continue to deboost the rest of the chain. + */ rt_mutex_dequeue_pi(task, waiter); waiter = rt_mutex_top_waiter(lock); rt_mutex_enqueue_pi(task, waiter); __rt_mutex_adjust_prio(task); + } else { + /* + * Nothing changed. No need to do any priority + * adjustment. + */ } /* @@ -439,6 +469,10 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, raw_spin_unlock_irqrestore(&task->pi_lock, flags); + /* + * Store the top waiter of @lock for the end of chain walk + * decision below. + */ top_waiter = rt_mutex_top_waiter(lock); raw_spin_unlock(&lock->wait_lock); @@ -449,6 +483,11 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, if (!next_lock) goto out_put_task; + /* + * If the current waiter is not the top waiter on the lock, + * then we can stop the chain walk here if we are not in full + * deadlock detection mode. + */ if (!detect_deadlock && waiter != top_waiter) goto out_put_task; -- 2.1.4