aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c15
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c54
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h4
3 files changed, 58 insertions, 15 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index f084667e4f50..c5ec7cfc24b5 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -53,10 +53,19 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
53 INIT_LIST_HEAD(&ctx->rq); 53 INIT_LIST_HEAD(&ctx->rq);
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
57 /*
58 * We do our own priority calculations, so we normally want
59 * ->static_prio to start with. Unfortunately thies field
60 * contains junk for threads with a realtime scheduling
61 * policy so we have to look at ->prio in this case.
62 */
63 if (rt_prio(current->prio))
64 ctx->prio = current->prio;
65 else
66 ctx->prio = current->static_prio;
57 ctx->policy = current->policy; 67 ctx->policy = current->policy;
58 ctx->prio = current->prio; 68 spu_set_timeslice(ctx);
59 ctx->time_slice = SPU_DEF_TIMESLICE;
60 goto out; 69 goto out;
61out_free: 70out_free:
62 kfree(ctx); 71 kfree(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index d673353b6d33..1b2916bdc1c8 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -44,10 +44,6 @@
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_TIMESLICE (HZ)
48
49#define SPUSCHED_TICK (HZ / 100)
50
51struct spu_prio_array { 47struct spu_prio_array {
52 DECLARE_BITMAP(bitmap, MAX_PRIO); 48 DECLARE_BITMAP(bitmap, MAX_PRIO);
53 struct list_head runq[MAX_PRIO]; 49 struct list_head runq[MAX_PRIO];
@@ -60,6 +56,46 @@ static struct spu_prio_array *spu_prio;
60static struct task_struct *spusched_task; 56static struct task_struct *spusched_task;
61static struct timer_list spusched_timer; 57static struct timer_list spusched_timer;
62 58
59/*
60 * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
61 */
62#define NORMAL_PRIO 120
63
64/*
65 * Frequency of the spu scheduler tick. By default we do one SPU scheduler
66 * tick for every 10 CPU scheduler ticks.
67 */
68#define SPUSCHED_TICK (10)
69
70/*
71 * These are the 'tuning knobs' of the scheduler:
72 *
73 * Minimum timeslice is 5 msecs (or 10 jiffies, whichever is larger),
74 * default timeslice is 100 msecs, maximum timeslice is 800 msecs.
75 */
76#define MIN_SPU_TIMESLICE max(5 * HZ / 100, 10)
77#define DEF_SPU_TIMESLICE (100 * HZ / 100)
78
79#define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO)
80#define SCALE_PRIO(x, prio) \
81 max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
82
83/*
84 * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values:
85 * [800ms ... 100ms ... 5ms]
86 *
87 * The higher a thread's priority, the bigger timeslices
88 * it gets during one round of execution. But even the lowest
89 * priority thread gets MIN_TIMESLICE worth of execution time.
90 */
91void spu_set_timeslice(struct spu_context *ctx)
92{
93 if (ctx->prio < NORMAL_PRIO)
94 ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio);
95 else
96 ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
97}
98
63static inline int node_allowed(int node) 99static inline int node_allowed(int node)
64{ 100{
65 cpumask_t mask; 101 cpumask_t mask;
@@ -265,8 +301,8 @@ static struct spu *find_victim(struct spu_context *ctx)
265 list_for_each_entry(spu, &spu_prio->active_list[node], list) { 301 list_for_each_entry(spu, &spu_prio->active_list[node], list) {
266 struct spu_context *tmp = spu->ctx; 302 struct spu_context *tmp = spu->ctx;
267 303
268 if (tmp->rt_priority < ctx->rt_priority && 304 if (tmp->prio > ctx->prio &&
269 (!victim || tmp->rt_priority < victim->rt_priority)) 305 (!victim || tmp->prio > victim->prio))
270 victim = spu->ctx; 306 victim = spu->ctx;
271 } 307 }
272 mutex_unlock(&spu_prio->active_mutex[node]); 308 mutex_unlock(&spu_prio->active_mutex[node]);
@@ -333,7 +369,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
333 * If this is a realtime thread we try to get it running by 369 * If this is a realtime thread we try to get it running by
334 * preempting a lower priority thread. 370 * preempting a lower priority thread.
335 */ 371 */
336 if (!spu && ctx->rt_priority) 372 if (!spu && rt_prio(ctx->prio))
337 spu = find_victim(ctx); 373 spu = find_victim(ctx);
338 if (spu) { 374 if (spu) {
339 spu_bind_context(spu, ctx); 375 spu_bind_context(spu, ctx);
@@ -424,7 +460,7 @@ void spu_yield(struct spu_context *ctx)
424 460
425static void spusched_tick(struct spu_context *ctx) 461static void spusched_tick(struct spu_context *ctx)
426{ 462{
427 if (ctx->policy != SCHED_RR || --ctx->time_slice) 463 if (ctx->policy == SCHED_FIFO || --ctx->time_slice)
428 return; 464 return;
429 465
430 /* 466 /*
@@ -448,7 +484,7 @@ static void spusched_tick(struct spu_context *ctx)
448 */ 484 */
449 wake_up(&ctx->stop_wq); 485 wake_up(&ctx->stop_wq);
450 } 486 }
451 ctx->time_slice = SPU_DEF_TIMESLICE; 487 spu_set_timeslice(ctx);
452 mutex_unlock(&ctx->state_mutex); 488 mutex_unlock(&ctx->state_mutex);
453 } else { 489 } else {
454 ctx->time_slice++; 490 ctx->time_slice++;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 8068171dfa9c..fddc59c204b5 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -31,8 +31,6 @@
31#include <asm/spu_csa.h> 31#include <asm/spu_csa.h>
32#include <asm/spu_info.h> 32#include <asm/spu_info.h>
33 33
34#define SPU_DEF_TIMESLICE 100
35
36/* The magic number for our file system */ 34/* The magic number for our file system */
37enum { 35enum {
38 SPUFS_MAGIC = 0x23c9b64e, 36 SPUFS_MAGIC = 0x23c9b64e,
@@ -82,7 +80,6 @@ struct spu_context {
82 struct list_head rq; 80 struct list_head rq;
83 unsigned int time_slice; 81 unsigned int time_slice;
84 unsigned long sched_flags; 82 unsigned long sched_flags;
85 unsigned long rt_priority;
86 int policy; 83 int policy;
87 int prio; 84 int prio;
88}; 85};
@@ -197,6 +194,7 @@ void spu_acquire_saved(struct spu_context *ctx);
197int spu_activate(struct spu_context *ctx, unsigned long flags); 194int spu_activate(struct spu_context *ctx, unsigned long flags);
198void spu_deactivate(struct spu_context *ctx); 195void spu_deactivate(struct spu_context *ctx);
199void spu_yield(struct spu_context *ctx); 196void spu_yield(struct spu_context *ctx);
197void spu_set_timeslice(struct spu_context *ctx);
200int __init spu_sched_init(void); 198int __init spu_sched_init(void);
201void __exit spu_sched_exit(void); 199void __exit spu_sched_exit(void);
202 200