From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752952AbbC3Nls (ORCPT ); Mon, 30 Mar 2015 09:41:48 -0400 Received: from smtprelay0196.hostedemail.com ([216.40.44.196]:59095 "EHLO smtprelay.hostedemail.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752601AbbC3Nlp (ORCPT ); Mon, 30 Mar 2015 09:41:45 -0400 X-Session-Marker: 726F737465647440676F6F646D69732E6F7267 X-Spam-Summary: 2,0,0,,d41d8cd98f00b204,rostedt@goodmis.org,:::::::::,RULES_HIT:41:355:379:541:599:960:973:988:989:1260:1277:1311:1313:1314:1345:1359:1437:1515:1516:1518:1535:1544:1593:1594:1605:1711:1730:1747:1777:1792:2194:2199:2393:2553:2559:2562:2898:3138:3139:3140:3141:3142:3622:3865:3867:3868:3870:3871:3872:3874:4250:5007:6119:6261:7875:7901:7903:9108:10004:10848:10967:11026:11232:11473:11658:11914:12043:12296:12438:12517:12519:12555:12740:13161:13229:13255:14096:14097: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:0:0 X-HE-Tag: drug00_8365489700625 X-Filterd-Recvd-Size: 5307 Date: Mon, 30 Mar 2015 09:41:40 -0400 From: Steven Rostedt To: Wanpeng Li Cc: Ingo Molnar , Peter Zijlstra , Juri Lelli , linux-kernel@vger.kernel.org Subject: Re: [PATCH] sched/deadline: Use IPI to trigger DL task push migration instead of pulling Message-ID: <20150330094140.31dcc1cf@gandalf.local.home> In-Reply-To: <1427670430-4667-1-git-send-email-wanpeng.li@linux.intel.com> References: <1427670430-4667-1-git-send-email-wanpeng.li@linux.intel.com> X-Mailer: Claws Mail 3.11.1 (GTK+ 2.24.25; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 30 Mar 2015 07:07:10 +0800 Wanpeng Li wrote: > +static int find_next_push_cpu(struct rq *rq) > +{ > + struct rq *next_rq; > + int cpu; > + > + while (1) { > + cpu = dlo_next_cpu(rq); > + if (cpu >= nr_cpu_ids) > + break; > + next_rq = cpu_rq(cpu); > + > + /* Make sure the next rq can push to this rq */ > + if (dl_time_before(next_rq->dl.earliest_dl.next, > + rq->dl.earliest_dl.curr)) > + break; > + } > + > + return cpu; > +} > + Is it possible that we don't duplicate the code and that we can find a way to share the code between rt and dl? It's not that trivial to just cut and paste. If a bug is found in one, it most likely wont be ported to the other. The best is if we can share the code here some way. Perhaps have a single IPI that checks both rt and dl? -- Steve > +#define RT_PUSH_IPI_EXECUTING 1 > +#define RT_PUSH_IPI_RESTART 2 > + > +static void tell_cpu_to_push(struct rq *rq) > +{ > + int cpu; > + > + if (rq->dl.push_flags & RT_PUSH_IPI_EXECUTING) { > + raw_spin_lock(&rq->dl.push_lock); > + /* Make sure it's still executing */ > + if (rq->dl.push_flags & RT_PUSH_IPI_EXECUTING) { > + /* > + * Tell the IPI to restart the loop as things have > + * changed since it started. > + */ > + rq->dl.push_flags |= RT_PUSH_IPI_RESTART; > + raw_spin_unlock(&rq->dl.push_lock); > + return; > + } > + raw_spin_unlock(&rq->dl.push_lock); > + } > + > + /* When here, there's no IPI going around */ > + > + rq->dl.push_cpu = rq->cpu; > + cpu = find_next_push_cpu(rq); > + if (cpu >= nr_cpu_ids) > + return; > + > + rq->dl.push_flags = RT_PUSH_IPI_EXECUTING; > + > + irq_work_queue_on(&rq->dl.push_work, cpu); > +} > + > +/* Called from hardirq context */ > +static void try_to_push_tasks(void *arg) > +{ > + struct dl_rq *dl_rq = arg; > + struct rq *rq, *src_rq; > + int this_cpu; > + int cpu; > + > + this_cpu = dl_rq->push_cpu; > + > + /* Paranoid check */ > + BUG_ON(this_cpu != smp_processor_id()); > + > + rq = cpu_rq(this_cpu); > + src_rq = rq_of_dl_rq(dl_rq); > + > +again: > + if (has_pushable_dl_tasks(rq)) { > + raw_spin_lock(&rq->lock); > + push_dl_task(rq); > + raw_spin_unlock(&rq->lock); > + } > + > + /* Pass the IPI to the next rt overloaded queue */ > + raw_spin_lock(&dl_rq->push_lock); > + /* > + * If the source queue changed since the IPI went out, > + * we need to restart the search from that CPU again. > + */ > + if (dl_rq->push_flags & RT_PUSH_IPI_RESTART) { > + dl_rq->push_flags &= ~RT_PUSH_IPI_RESTART; > + dl_rq->push_cpu = src_rq->cpu; > + } > + > + cpu = find_next_push_cpu(src_rq); > + > + if (cpu >= nr_cpu_ids) > + dl_rq->push_flags &= ~RT_PUSH_IPI_EXECUTING; > + raw_spin_unlock(&dl_rq->push_lock); > + > + if (cpu >= nr_cpu_ids) > + return; > + > + /* > + * It is possible that a restart caused this CPU to be > + * chosen again. Don't bother with an IPI, just see if we > + * have more to push. > + */ > + if (unlikely(cpu == rq->cpu)) > + goto again; > + > + /* Try the next RT overloaded CPU */ > + irq_work_queue_on(&dl_rq->push_work, cpu); > +} > + > +static void push_irq_work_func(struct irq_work *work) > +{ > + struct dl_rq *dl_rq = container_of(work, struct dl_rq, push_work); > + > + try_to_push_tasks(dl_rq); > +} > +#endif /* HAVE_RT_PUSH_IPI */ > + > static int pull_dl_task(struct rq *this_rq) > { > int this_cpu = this_rq->cpu, ret = 0, cpu; > @@ -1432,6 +1602,13 @@ static int pull_dl_task(struct rq *this_rq) > */ > smp_rmb(); > > +#ifdef HAVE_RT_PUSH_IPI > + if (sched_feat(RT_PUSH_IPI)) { > + tell_cpu_to_push(this_rq); > + return 0; > + } > +#endif > + > for_each_cpu(cpu, this_rq->rd->dlo_mask) { > if (this_cpu == cpu) > continue; > diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h > index dd532c5..87a937c 100644 > --- a/kernel/sched/sched.h > +++ b/kernel/sched/sched.h > @@ -500,6 +500,12 @@ struct dl_rq { > */ > struct rb_root pushable_dl_tasks_root; > struct rb_node *pushable_dl_tasks_leftmost; > +#ifdef HAVE_RT_PUSH_IPI > + int push_flags; > + int push_cpu; > + struct irq_work push_work; > + raw_spinlock_t push_lock; > +#endif > #else > struct dl_bw dl_bw; > #endif