提交 ea1ae594 编写于 作者: C Christoph Hellwig 提交者: Paul Mackerras

[POWERPC] spusched: fix cpu/node binding

Add a cpus_allowed allowed filed to struct spu_context so that we always
use the cpu mask of the owning thread instead of the one happening to
call into the scheduler.  Also use this information in
grab_runnable_context to avoid spurious wakeups.
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Signed-off-by: NArnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: NJeremy Kerr <jk@ozlabs.org>
Signed-off-by: NPaul Mackerras <paulus@samba.org>
上级 2cf2b3b4
...@@ -53,7 +53,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) ...@@ -53,7 +53,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
INIT_LIST_HEAD(&ctx->rq); INIT_LIST_HEAD(&ctx->rq);
if (gang) if (gang)
spu_gang_add_ctx(gang, ctx); spu_gang_add_ctx(gang, ctx);
ctx->cpus_allowed = current->cpus_allowed;
spu_set_timeslice(ctx); spu_set_timeslice(ctx);
goto out; goto out;
out_free: out_free:
......
...@@ -112,6 +112,16 @@ void __spu_update_sched_info(struct spu_context *ctx) ...@@ -112,6 +112,16 @@ void __spu_update_sched_info(struct spu_context *ctx)
else else
ctx->prio = current->static_prio; ctx->prio = current->static_prio;
ctx->policy = current->policy; ctx->policy = current->policy;
/*
* A lot of places that don't hold active_mutex poke into
* cpus_allowed, including grab_runnable_context which
* already holds the runq_lock. So abuse runq_lock
* to protect this field aswell.
*/
spin_lock(&spu_prio->runq_lock);
ctx->cpus_allowed = current->cpus_allowed;
spin_unlock(&spu_prio->runq_lock);
} }
void spu_update_sched_info(struct spu_context *ctx) void spu_update_sched_info(struct spu_context *ctx)
...@@ -123,16 +133,27 @@ void spu_update_sched_info(struct spu_context *ctx) ...@@ -123,16 +133,27 @@ void spu_update_sched_info(struct spu_context *ctx)
mutex_unlock(&spu_prio->active_mutex[node]); mutex_unlock(&spu_prio->active_mutex[node]);
} }
static inline int node_allowed(int node) static int __node_allowed(struct spu_context *ctx, int node)
{ {
cpumask_t mask; if (nr_cpus_node(node)) {
cpumask_t mask = node_to_cpumask(node);
if (!nr_cpus_node(node)) if (cpus_intersects(mask, ctx->cpus_allowed))
return 0; return 1;
mask = node_to_cpumask(node); }
if (!cpus_intersects(mask, current->cpus_allowed))
return 0; return 0;
return 1; }
static int node_allowed(struct spu_context *ctx, int node)
{
int rval;
spin_lock(&spu_prio->runq_lock);
rval = __node_allowed(ctx, node);
spin_unlock(&spu_prio->runq_lock);
return rval;
} }
/** /**
...@@ -289,7 +310,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) ...@@ -289,7 +310,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
for (n = 0; n < MAX_NUMNODES; n++, node++) { for (n = 0; n < MAX_NUMNODES; n++, node++) {
node = (node < MAX_NUMNODES) ? node : 0; node = (node < MAX_NUMNODES) ? node : 0;
if (!node_allowed(node)) if (!node_allowed(ctx, node))
continue; continue;
spu = spu_alloc_node(node); spu = spu_alloc_node(node);
if (spu) if (spu)
...@@ -321,7 +342,7 @@ static struct spu *find_victim(struct spu_context *ctx) ...@@ -321,7 +342,7 @@ static struct spu *find_victim(struct spu_context *ctx)
node = cpu_to_node(raw_smp_processor_id()); node = cpu_to_node(raw_smp_processor_id());
for (n = 0; n < MAX_NUMNODES; n++, node++) { for (n = 0; n < MAX_NUMNODES; n++, node++) {
node = (node < MAX_NUMNODES) ? node : 0; node = (node < MAX_NUMNODES) ? node : 0;
if (!node_allowed(node)) if (!node_allowed(ctx, node))
continue; continue;
mutex_lock(&spu_prio->active_mutex[node]); mutex_lock(&spu_prio->active_mutex[node]);
...@@ -416,23 +437,28 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) ...@@ -416,23 +437,28 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
* Remove the highest priority context on the runqueue and return it * Remove the highest priority context on the runqueue and return it
* to the caller. Returns %NULL if no runnable context was found. * to the caller. Returns %NULL if no runnable context was found.
*/ */
static struct spu_context *grab_runnable_context(int prio) static struct spu_context *grab_runnable_context(int prio, int node)
{ {
struct spu_context *ctx = NULL; struct spu_context *ctx;
int best; int best;
spin_lock(&spu_prio->runq_lock); spin_lock(&spu_prio->runq_lock);
best = sched_find_first_bit(spu_prio->bitmap); best = sched_find_first_bit(spu_prio->bitmap);
if (best < prio) { while (best < prio) {
struct list_head *rq = &spu_prio->runq[best]; struct list_head *rq = &spu_prio->runq[best];
BUG_ON(list_empty(rq)); list_for_each_entry(ctx, rq, rq) {
/* XXX(hch): check for affinity here aswell */
ctx = list_entry(rq->next, struct spu_context, rq); if (__node_allowed(ctx, node)) {
__spu_del_from_rq(ctx); __spu_del_from_rq(ctx);
goto found;
}
}
best++;
} }
ctx = NULL;
found:
spin_unlock(&spu_prio->runq_lock); spin_unlock(&spu_prio->runq_lock);
return ctx; return ctx;
} }
...@@ -442,7 +468,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) ...@@ -442,7 +468,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
struct spu_context *new = NULL; struct spu_context *new = NULL;
if (spu) { if (spu) {
new = grab_runnable_context(max_prio); new = grab_runnable_context(max_prio, spu->node);
if (new || force) { if (new || force) {
spu_remove_from_active_list(spu); spu_remove_from_active_list(spu);
spu_unbind_context(spu, ctx); spu_unbind_context(spu, ctx);
...@@ -496,9 +522,11 @@ static void spusched_tick(struct spu_context *ctx) ...@@ -496,9 +522,11 @@ static void spusched_tick(struct spu_context *ctx)
* tick and try again. * tick and try again.
*/ */
if (mutex_trylock(&ctx->state_mutex)) { if (mutex_trylock(&ctx->state_mutex)) {
struct spu_context *new = grab_runnable_context(ctx->prio + 1); struct spu *spu = ctx->spu;
struct spu_context *new;
new = grab_runnable_context(ctx->prio + 1, spu->node);
if (new) { if (new) {
struct spu *spu = ctx->spu;
__spu_remove_from_active_list(spu); __spu_remove_from_active_list(spu);
spu_unbind_context(spu, ctx); spu_unbind_context(spu, ctx);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/cpumask.h>
#include <asm/spu.h> #include <asm/spu.h>
#include <asm/spu_csa.h> #include <asm/spu_csa.h>
...@@ -80,6 +81,7 @@ struct spu_context { ...@@ -80,6 +81,7 @@ struct spu_context {
struct list_head rq; struct list_head rq;
unsigned int time_slice; unsigned int time_slice;
unsigned long sched_flags; unsigned long sched_flags;
cpumask_t cpus_allowed;
int policy; int policy;
int prio; int prio;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册