Subject: spu sched: replace active_mutex with a spinlock From: Christoph Hellwig The only reason active_mutex had to be a sleeping mutex was that spu_free could potentially block. With my last patch that's not true anymore and we can use much less expensive spinlock protection for it's small critical sections. Signed-off-by: Christoph Hellwig Signed-off-by: Arnd Bergmann Index: linux-cg/arch/powerpc/platforms/cell/spufs/sched.c =================================================================== --- linux-cg.orig/arch/powerpc/platforms/cell/spufs/sched.c +++ linux-cg/arch/powerpc/platforms/cell/spufs/sched.c @@ -53,7 +53,7 @@ struct spu_prio_array { struct list_head runq[MAX_PRIO]; spinlock_t runq_lock; struct list_head active_list[MAX_NUMNODES]; - struct mutex active_mutex[MAX_NUMNODES]; + spinlock_t active_lock[MAX_NUMNODES]; int nr_active[MAX_NUMNODES]; int nr_waiting; }; @@ -121,7 +121,7 @@ void __spu_update_sched_info(struct spu_ ctx->policy = current->policy; /* - * A lot of places that don't hold active_mutex poke into + * A lot of places that don't hold active_lock poke into * cpus_allowed, including grab_runnable_context which * already holds the runq_lock. So abuse runq_lock * to protect this field aswell. @@ -135,9 +135,9 @@ void spu_update_sched_info(struct spu_co { int node = ctx->spu->node; - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); __spu_update_sched_info(ctx); - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); } static int __node_allowed(struct spu_context *ctx, int node) @@ -171,10 +171,10 @@ static void spu_add_to_active_list(struc { int node = spu->node; - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); spu_prio->nr_active[node]++; list_add_tail(&spu->list, &spu_prio->active_list[node]); - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); } static void __spu_remove_from_active_list(struct spu *spu) @@ -191,9 +191,9 @@ static void spu_remove_from_active_list( { int node = spu->node; - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); __spu_remove_from_active_list(spu); - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); } static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier); @@ -213,14 +213,14 @@ static void notify_spus_active(void) */ for (node = 0; node < MAX_NUMNODES; node++) { struct spu *spu; - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); list_for_each_entry(spu, &spu_prio->active_list[node], list) { struct spu_context *ctx = spu->ctx; set_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags); mb(); wake_up_all(&ctx->stop_wq); } - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); } } @@ -400,7 +400,7 @@ static struct spu *find_victim(struct sp if (!node_allowed(ctx, node)) continue; - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); list_for_each_entry(spu, &spu_prio->active_list[node], list) { struct spu_context *tmp = spu->ctx; @@ -408,7 +408,7 @@ static struct spu *find_victim(struct sp (!victim || tmp->prio > victim->prio)) victim = spu->ctx; } - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); if (victim) { /* @@ -570,7 +570,7 @@ static void spusched_tick(struct spu_con return; /* - * Unfortunately active_mutex ranks outside of state_mutex, so + * Unfortunately active_lock ranks outside of state_mutex, so * we have to trylock here. If we fail give the context another * tick and try again. */ @@ -604,7 +604,7 @@ static void spusched_tick(struct spu_con * * Return the number of tasks currently running or waiting to run. * - * Note that we don't take runq_lock / active_mutex here. Reading + * Note that we don't take runq_lock / active_lock here. Reading * a single 32bit value is atomic on powerpc, and we don't care * about memory ordering issues here. */ @@ -662,12 +662,12 @@ static int spusched_thread(void *unused) while (!kthread_should_stop()) { schedule(); for (node = 0; node < MAX_NUMNODES; node++) { - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); list_for_each_entry_safe(spu, next, &spu_prio->active_list[node], list) spusched_tick(spu->ctx); - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); } } @@ -728,7 +728,7 @@ int __init spu_sched_init(void) } __set_bit(MAX_PRIO, spu_prio->bitmap); for (i = 0; i < MAX_NUMNODES; i++) { - mutex_init(&spu_prio->active_mutex[i]); + spin_lock_init(&spu_prio->active_lock[i]); INIT_LIST_HEAD(&spu_prio->active_list[i]); } spin_lock_init(&spu_prio->runq_lock); @@ -763,13 +763,13 @@ void __exit spu_sched_exit(void) kthread_stop(spusched_task); for (node = 0; node < MAX_NUMNODES; node++) { - mutex_lock(&spu_prio->active_mutex[node]); + spin_lock(&spu_prio->active_lock[node]); list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], list) { list_del_init(&spu->list); spu_free(spu); } - mutex_unlock(&spu_prio->active_mutex[node]); + spin_unlock(&spu_prio->active_lock[node]); } kfree(spu_prio); }