public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Mike Galbraith <efault@gmx.de>
To: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Rik van Riel <riel@redhat.com>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Avi Kiviti <avi@redhat.com>,
	Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>,
	Chris Wright <chrisw@sous-sol.org>
Subject: Re: [RFC -v3 PATCH 2/3] sched: add yield_to function
Date: Wed, 05 Jan 2011 18:23:10 +0100	[thread overview]
Message-ID: <1294248190.31375.14.camel@marge.simson.net> (raw)
In-Reply-To: <1294247065.2016.267.camel@laptop>

On Wed, 2011-01-05 at 18:04 +0100, Peter Zijlstra wrote:
> On Wed, 2011-01-05 at 17:57 +0100, Mike Galbraith wrote:
> > +               p_cfs_rq = cfs_rq_of(pse);
> > +               local = 1;
> > +       }
> > +#endif
> > +
> > +       /* Tell the scheduler that we'd really like pse to run next. */
> > +       p_cfs_rq->next = pse;
> > +
> > +       /* We know whether we want to preempt or not, but are we allowed? */
> > +       preempt &= same_thread_group(p, task_of(p_cfs_rq->curr));
> > +
> > +       if (local)
> > +               clear_buddies(cfs_rq, se); 
> 
> You might want to clear before setting next :-)

Heh, you made me thwap forehead.. but pse != se or p_cfs_rq->curr.
Moved it back where it came from anyway ;-)


sched: Add yield_to(task, preempt) functionality.

Currently only implemented for fair class tasks.

Add a yield_to_task method() to the fair scheduling class. allowing the
caller of yield_to() to accelerate another thread in it's thread group,
task group, and sched class toward either it's cpu, or potentially the
caller's own cpu if the 'prempt' argument is also passed.

Implemented via a scheduler hint, using cfs_rq->next to encourage the
target being selected.

Signed-off-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Mike Galbraith <efault@gmx.de>

---
 include/linux/sched.h |    1 
 kernel/sched.c        |   56 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/sched_fair.c   |   52 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+)

Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -1056,6 +1056,7 @@ struct sched_class {
 	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
 	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
 	void (*yield_task) (struct rq *rq);
+	int (*yield_to_task) (struct task_struct *p, int preempt);
 
 	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);
 
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -5327,6 +5327,62 @@ void __sched yield(void)
 }
 EXPORT_SYMBOL(yield);
 
+/**
+ * yield_to - yield the current processor to another thread in
+ * your thread group, or accelerate that thread toward the
+ * processor it's on.
+ *
+ * It's the caller's job to ensure that the target task struct
+ * can't go away on us before we can do any checks.
+ */
+void __sched yield_to(struct task_struct *p, int preempt)
+{
+	struct task_struct *curr = current;
+	struct rq *rq, *p_rq;
+	unsigned long flags;
+	int yield = 0;
+
+	local_irq_save(flags);
+	rq = this_rq();
+
+again:
+	p_rq = task_rq(p);
+	double_rq_lock(rq, p_rq);
+	while (task_rq(p) != p_rq) {
+		double_rq_unlock(rq, p_rq);
+		goto again;
+	}
+
+	if (!curr->sched_class->yield_to_task)
+		goto out;
+
+	if (curr->sched_class != p->sched_class)
+		goto out;
+
+	if (task_running(p_rq, p) || p->state)
+		goto out;
+
+	if (!same_thread_group(p, curr))
+		goto out;
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	if (task_group(p) != task_group(curr))
+		goto out;
+#endif
+
+	yield = curr->sched_class->yield_to_task(p, preempt);
+
+out:
+	double_rq_unlock(rq, p_rq);
+	local_irq_restore(flags);
+
+	if (yield) {
+		set_current_state(TASK_RUNNING);
+		schedule();
+	}
+}
+EXPORT_SYMBOL_GPL(yield_to);
+
 /*
  * This task is about to go to sleep on IO. Increment rq->nr_iowait so
  * that process accounting knows that this is a task in IO wait state.
Index: linux-2.6/kernel/sched_fair.c
===================================================================
--- linux-2.6.orig/kernel/sched_fair.c
+++ linux-2.6/kernel/sched_fair.c
@@ -1337,6 +1337,57 @@ static void yield_task_fair(struct rq *r
 }
 
 #ifdef CONFIG_SMP
+static void pull_task(struct rq *src_rq, struct task_struct *p,
+		      struct rq *this_rq, int this_cpu);
+#endif
+
+static int yield_to_task_fair(struct task_struct *p, int preempt)
+{
+	struct sched_entity *se = &current->se;
+	struct sched_entity *pse = &p->se;
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+	struct cfs_rq *p_cfs_rq = cfs_rq_of(pse);
+	int local = cfs_rq == p_cfs_rq;
+	int this_cpu = smp_processor_id();
+
+	if (!pse->on_rq)
+		return 0;
+
+#ifdef CONFIG_SMP
+	/*
+	 * If this yield is important enough to want to preempt instead
+	 * of only dropping a ->next hint, we're alone, and the target
+	 * is not alone, pull the target to this cpu.
+	 *
+	 * NOTE: the target may be alone in it's cfs_rq if another class
+	 * task or another task group is currently executing on it's cpu.
+	 * In this case, we still pull, to accelerate it toward the cpu.
+	 */
+	if (!local && preempt && cfs_rq->nr_running == 1 &&
+			cpumask_test_cpu(this_cpu, &p->cpus_allowed)) {
+		pull_task(task_rq(p), p, this_rq(), this_cpu);
+		p_cfs_rq = cfs_rq_of(pse);
+		local = 1;
+	}
+#endif
+
+	/* We know whether we want to preempt or not, but are we allowed? */
+	preempt &= same_thread_group(p, task_of(p_cfs_rq->curr));
+
+	if (local)
+		clear_buddies(cfs_rq, se);
+	else if (preempt) {
+		clear_buddies(p_cfs_rq, p_cfs_rq->curr);
+		resched_task(task_of(p_cfs_rq->curr));
+	}
+
+	/* Tell the scheduler that we'd really like pse to run next. */
+	p_cfs_rq->next = pse;
+
+	return local;
+}
+
+#ifdef CONFIG_SMP
 
 static void task_waking_fair(struct rq *rq, struct task_struct *p)
 {
@@ -4143,6 +4194,7 @@ static const struct sched_class fair_sch
 	.enqueue_task		= enqueue_task_fair,
 	.dequeue_task		= dequeue_task_fair,
 	.yield_task		= yield_task_fair,
+	.yield_to_task		= yield_to_task_fair,
 
 	.check_preempt_curr	= check_preempt_wakeup,
 











  reply	other threads:[~2011-01-05 17:23 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-03 21:26 [RFC -v3 PATCH 0/3] directed yield for Pause Loop Exiting Rik van Riel
2011-01-03 21:27 ` [RFC -v3 PATCH 1/3] kvm: keep track of which task is running a KVM vcpu Rik van Riel
2011-01-03 21:29 ` [RFC -v3 PATCH 2/3] sched: add yield_to function Rik van Riel
2011-01-04  1:51   ` Mike Galbraith
2011-01-04  6:14   ` KOSAKI Motohiro
2011-01-04 12:03     ` Avi Kivity
2011-01-05  2:39       ` KOSAKI Motohiro
2011-01-05  8:35         ` Avi Kivity
2011-01-05  8:40           ` KOSAKI Motohiro
2011-01-05  9:08             ` Avi Kivity
2011-01-05  9:30               ` KOSAKI Motohiro
2011-01-05  9:34                 ` Avi Kivity
2011-01-05 10:24             ` Peter Zijlstra
2011-01-05 10:04         ` Peter Zijlstra
2011-01-04 17:16     ` Peter Zijlstra
2011-01-05  3:17       ` KOSAKI Motohiro
2011-01-04 14:28   ` Hillf Danton
2011-01-04 16:41   ` Hillf Danton
2011-01-04 16:44     ` Rik van Riel
2011-01-04 16:51       ` Hillf Danton
2011-01-04 16:54         ` Rik van Riel
2011-01-04 17:02           ` Hillf Danton
2011-01-04 17:08         ` Peter Zijlstra
2011-01-04 17:12           ` Hillf Danton
2011-01-04 17:22             ` Peter Zijlstra
2011-01-04 17:53           ` Rik van Riel
2011-01-04 18:05             ` Peter Zijlstra
2011-01-04 18:04   ` Peter Zijlstra
2011-01-04 18:53     ` Mike Galbraith
2011-01-05 16:57     ` Mike Galbraith
2011-01-05 17:04       ` Peter Zijlstra
2011-01-05 17:23         ` Mike Galbraith [this message]
2011-01-07  5:29         ` Mike Galbraith
2011-01-13  3:02           ` Rik van Riel
2011-01-13  3:26             ` Mike Galbraith
2011-01-13  5:08               ` Rik van Riel
2011-01-06 14:33       ` Hillf Danton
2011-01-05 17:10     ` Avi Kivity
2011-01-05 17:15       ` Peter Zijlstra
2011-01-05 17:19         ` Avi Kivity
2011-01-05 17:28           ` Peter Zijlstra
2011-01-05 17:35             ` Avi Kivity
2011-01-05 17:39               ` Peter Zijlstra
2011-01-06  3:49                 ` Tejun Heo
2011-01-03 21:30 ` [RFC -v3 PATCH 3/3] Subject: kvm: use yield_to instead of sleep in kvm_vcpu_on_spin Rik van Riel
2011-01-04  6:42 ` [RFC -v3 PATCH 0/3] directed yield for Pause Loop Exiting Mike Galbraith
2011-01-04  9:09   ` Avi Kivity
2011-01-04 10:32     ` Mike Galbraith
2011-01-04 10:35       ` Avi Kivity
2011-01-04  9:14 ` Avi Kivity
2011-01-04 10:26   ` Mike Galbraith
2011-01-04 17:20     ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1294248190.31375.14.camel@marge.simson.net \
    --to=efault@gmx.de \
    --cc=a.p.zijlstra@chello.nl \
    --cc=avi@redhat.com \
    --cc=chrisw@sous-sol.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=riel@redhat.com \
    --cc=vatsa@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox