diff options
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 15 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 54 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 4 |
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; |
61 | out_free: | 70 | out_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 | |||
51 | struct spu_prio_array { | 47 | struct 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; | |||
60 | static struct task_struct *spusched_task; | 56 | static struct task_struct *spusched_task; |
61 | static struct timer_list spusched_timer; | 57 | static 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 | */ | ||
91 | void 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 | |||
63 | static inline int node_allowed(int node) | 99 | static 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 | ||
425 | static void spusched_tick(struct spu_context *ctx) | 461 | static 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 */ |
37 | enum { | 35 | enum { |
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); | |||
197 | int spu_activate(struct spu_context *ctx, unsigned long flags); | 194 | int spu_activate(struct spu_context *ctx, unsigned long flags); |
198 | void spu_deactivate(struct spu_context *ctx); | 195 | void spu_deactivate(struct spu_context *ctx); |
199 | void spu_yield(struct spu_context *ctx); | 196 | void spu_yield(struct spu_context *ctx); |
197 | void spu_set_timeslice(struct spu_context *ctx); | ||
200 | int __init spu_sched_init(void); | 198 | int __init spu_sched_init(void); |
201 | void __exit spu_sched_exit(void); | 199 | void __exit spu_sched_exit(void); |
202 | 200 | ||