aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-02-13 15:54:29 -0500
committerArnd Bergmann <arnd@klappe.arndb.de>2007-02-13 15:55:43 -0500
commit2eb1b12049844a8ebc670e0e4fc908bc3f8933d3 (patch)
treeb02521b88557dddabcb9de649855151323881cc0 /arch
parent72cb360839f88c02ccf38f1df214316e05886ff3 (diff)
[POWERPC] spu sched: static timeslicing for SCHED_RR contexts
For SCHED_RR tasks we can do some really trivial timeslicing. Basically we fire up a time for every scheduler tick that searches for a higher or same priority thread that is on the runqueue and if there is one context switches to it. Because we can't lock spus from timer context we actually run this from a delayed runqueue instead of a timer. A nice optimization would be to skip the actual priority bitmap search when there are less contexts than physical spus available. To implement this I need a so far unpublished patch from Andre, and it will be added after we have that patch in. Note that right now we only do the time slicing for SCHED_RR tasks. The code would work for SCHED_OTHER tasks aswell, but their prio value is defered from the one the PPU thread has at time of spu_run, and using this for spu scheduling decisions would make the code very unfair. SCHED_OTHER support will be enabled once we the spu scheduler knows how to calculcate cpu_context.prio (very soon) Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c9
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c43
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h5
4 files changed, 56 insertions, 3 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index d581f4ec99ba..04ad2e364e97 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -54,7 +54,9 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
54 if (gang) 54 if (gang)
55 spu_gang_add_ctx(gang, ctx); 55 spu_gang_add_ctx(gang, ctx);
56 ctx->rt_priority = current->rt_priority; 56 ctx->rt_priority = current->rt_priority;
57 ctx->policy = current->policy;
57 ctx->prio = current->prio; 58 ctx->prio = current->prio;
59 INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
58 goto out; 60 goto out;
59out_free: 61out_free:
60 kfree(ctx); 62 kfree(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index a973e79e9fdc..353a8fa07ab8 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -164,8 +164,10 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
164 (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); 164 (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
165 if (runcntl == 0) 165 if (runcntl == 0)
166 runcntl = SPU_RUNCNTL_RUNNABLE; 166 runcntl = SPU_RUNCNTL_RUNNABLE;
167 } else 167 } else {
168 spu_start_tick(ctx);
168 ctx->ops->npc_write(ctx, *npc); 169 ctx->ops->npc_write(ctx, *npc);
170 }
169 171
170 ctx->ops->runcntl_write(ctx, runcntl); 172 ctx->ops->runcntl_write(ctx, runcntl);
171 return ret; 173 return ret;
@@ -176,6 +178,7 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
176{ 178{
177 int ret = 0; 179 int ret = 0;
178 180
181 spu_stop_tick(ctx);
179 *status = ctx->ops->status_read(ctx); 182 *status = ctx->ops->status_read(ctx);
180 *npc = ctx->ops->npc_read(ctx); 183 *npc = ctx->ops->npc_read(ctx);
181 spu_release(ctx); 184 spu_release(ctx);
@@ -329,8 +332,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
329 } 332 }
330 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { 333 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
331 ret = spu_reacquire_runnable(ctx, npc, &status); 334 ret = spu_reacquire_runnable(ctx, npc, &status);
332 if (ret) 335 if (ret) {
336 spu_stop_tick(ctx);
333 goto out2; 337 goto out2;
338 }
334 continue; 339 continue;
335 } 340 }
336 ret = spu_process_events(ctx); 341 ret = spu_process_events(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index ba4b01e01ace..2f25e68b4bac 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -44,7 +44,7 @@
44#include <asm/spu_priv1.h> 44#include <asm/spu_priv1.h>
45#include "spufs.h" 45#include "spufs.h"
46 46
47#define SPU_MIN_TIMESLICE (100 * HZ / 1000) 47#define SPU_TIMESLICE (HZ)
48 48
49struct spu_prio_array { 49struct spu_prio_array {
50 DECLARE_BITMAP(bitmap, MAX_PRIO); 50 DECLARE_BITMAP(bitmap, MAX_PRIO);
@@ -55,6 +55,7 @@ struct spu_prio_array {
55}; 55};
56 56
57static struct spu_prio_array *spu_prio; 57static struct spu_prio_array *spu_prio;
58static struct workqueue_struct *spu_sched_wq;
58 59
59static inline int node_allowed(int node) 60static inline int node_allowed(int node)
60{ 61{
@@ -68,6 +69,40 @@ static inline int node_allowed(int node)
68 return 1; 69 return 1;
69} 70}
70 71
72void spu_start_tick(struct spu_context *ctx)
73{
74 if (ctx->policy == SCHED_RR)
75 queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
76}
77
78void spu_stop_tick(struct spu_context *ctx)
79{
80 if (ctx->policy == SCHED_RR)
81 cancel_delayed_work(&ctx->sched_work);
82}
83
84void spu_sched_tick(struct work_struct *work)
85{
86 struct spu_context *ctx =
87 container_of(work, struct spu_context, sched_work.work);
88 struct spu *spu;
89 int rearm = 1;
90
91 mutex_lock(&ctx->state_mutex);
92 spu = ctx->spu;
93 if (spu) {
94 int best = sched_find_first_bit(spu_prio->bitmap);
95 if (best <= ctx->prio) {
96 spu_deactivate(ctx);
97 rearm = 0;
98 }
99 }
100 mutex_unlock(&ctx->state_mutex);
101
102 if (rearm)
103 spu_start_tick(ctx);
104}
105
71/** 106/**
72 * spu_add_to_active_list - add spu to active list 107 * spu_add_to_active_list - add spu to active list
73 * @spu: spu to add to the active list 108 * @spu: spu to add to the active list
@@ -437,10 +472,15 @@ int __init spu_sched_init(void)
437{ 472{
438 int i; 473 int i;
439 474
475 spu_sched_wq = create_singlethread_workqueue("spusched");
476 if (!spu_sched_wq)
477 return 1;
478
440 spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); 479 spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
441 if (!spu_prio) { 480 if (!spu_prio) {
442 printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", 481 printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
443 __FUNCTION__); 482 __FUNCTION__);
483 destroy_workqueue(spu_sched_wq);
444 return 1; 484 return 1;
445 } 485 }
446 for (i = 0; i < MAX_PRIO; i++) { 486 for (i = 0; i < MAX_PRIO; i++) {
@@ -471,4 +511,5 @@ void __exit spu_sched_exit(void)
471 mutex_unlock(&spu_prio->active_mutex[node]); 511 mutex_unlock(&spu_prio->active_mutex[node]);
472 } 512 }
473 kfree(spu_prio); 513 kfree(spu_prio);
514 destroy_workqueue(spu_sched_wq);
474} 515}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 85b182d16464..0c437891dfd5 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -82,8 +82,10 @@ struct spu_context {
82 82
83 /* scheduler fields */ 83 /* scheduler fields */
84 struct list_head rq; 84 struct list_head rq;
85 struct delayed_work sched_work;
85 unsigned long sched_flags; 86 unsigned long sched_flags;
86 unsigned long rt_priority; 87 unsigned long rt_priority;
88 int policy;
87 int prio; 89 int prio;
88}; 90};
89 91
@@ -195,6 +197,9 @@ enum {
195int spu_activate(struct spu_context *ctx, unsigned long flags); 197int spu_activate(struct spu_context *ctx, unsigned long flags);
196void spu_deactivate(struct spu_context *ctx); 198void spu_deactivate(struct spu_context *ctx);
197void spu_yield(struct spu_context *ctx); 199void spu_yield(struct spu_context *ctx);
200void spu_start_tick(struct spu_context *ctx);
201void spu_stop_tick(struct spu_context *ctx);
202void spu_sched_tick(struct work_struct *work);
198int __init spu_sched_init(void); 203int __init spu_sched_init(void);
199void __exit spu_sched_exit(void); 204void __exit spu_sched_exit(void);
200 205