[POWERPC] spufs: runqueue simplification
[linux-2.6] / arch / powerpc / platforms / cell / spufs / sched.c
1 /* sched.c - SPU scheduler.
2  *
3  * Copyright (C) IBM 2005
4  * Author: Mark Nutter <mnutter@us.ibm.com>
5  *
6  * 2006-03-31   NUMA domains added.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #undef DEBUG
24
25 #include <linux/module.h>
26 #include <linux/errno.h>
27 #include <linux/sched.h>
28 #include <linux/kernel.h>
29 #include <linux/mm.h>
30 #include <linux/completion.h>
31 #include <linux/vmalloc.h>
32 #include <linux/smp.h>
33 #include <linux/smp_lock.h>
34 #include <linux/stddef.h>
35 #include <linux/unistd.h>
36 #include <linux/numa.h>
37 #include <linux/mutex.h>
38 #include <linux/notifier.h>
39
40 #include <asm/io.h>
41 #include <asm/mmu_context.h>
42 #include <asm/spu.h>
43 #include <asm/spu_csa.h>
44 #include <asm/spu_priv1.h>
45 #include "spufs.h"
46
47 #define SPU_MIN_TIMESLICE       (100 * HZ / 1000)
48
49 #define SPU_BITMAP_SIZE (((MAX_PRIO+BITS_PER_LONG)/BITS_PER_LONG)+1)
50 struct spu_prio_array {
51         unsigned long bitmap[SPU_BITMAP_SIZE];
52         struct list_head runq[MAX_PRIO];
53         spinlock_t runq_lock;
54         struct list_head active_list[MAX_NUMNODES];
55         struct mutex active_mutex[MAX_NUMNODES];
56 };
57
58 static struct spu_prio_array *spu_prio;
59
60 static inline int node_allowed(int node)
61 {
62         cpumask_t mask;
63
64         if (!nr_cpus_node(node))
65                 return 0;
66         mask = node_to_cpumask(node);
67         if (!cpus_intersects(mask, current->cpus_allowed))
68                 return 0;
69         return 1;
70 }
71
72 /**
73  * spu_add_to_active_list - add spu to active list
74  * @spu:        spu to add to the active list
75  */
76 static void spu_add_to_active_list(struct spu *spu)
77 {
78         mutex_lock(&spu_prio->active_mutex[spu->node]);
79         list_add_tail(&spu->list, &spu_prio->active_list[spu->node]);
80         mutex_unlock(&spu_prio->active_mutex[spu->node]);
81 }
82
83 /**
84  * spu_remove_from_active_list - remove spu from active list
85  * @spu:       spu to remove from the active list
86  *
87  * This function removes an spu from the active list.  If the spu was
88  * found on the active list the function returns 1, else it doesn't do
89  * anything and returns 0.
90  */
91 static int spu_remove_from_active_list(struct spu *spu)
92 {
93         int node = spu->node;
94         struct spu *tmp;
95         int rc = 0;
96
97         mutex_lock(&spu_prio->active_mutex[node]);
98         list_for_each_entry(tmp, &spu_prio->active_list[node], list) {
99                 if (tmp == spu) {
100                         list_del_init(&spu->list);
101                         rc = 1;
102                         break;
103                 }
104         }
105         mutex_unlock(&spu_prio->active_mutex[node]);
106         return rc;
107 }
108
109 static inline void mm_needs_global_tlbie(struct mm_struct *mm)
110 {
111         int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
112
113         /* Global TLBIE broadcast required with SPEs. */
114         __cpus_setall(&mm->cpu_vm_mask, nr);
115 }
116
117 static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
118
119 static void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
120 {
121         blocking_notifier_call_chain(&spu_switch_notifier,
122                             ctx ? ctx->object_id : 0, spu);
123 }
124
125 int spu_switch_event_register(struct notifier_block * n)
126 {
127         return blocking_notifier_chain_register(&spu_switch_notifier, n);
128 }
129
130 int spu_switch_event_unregister(struct notifier_block * n)
131 {
132         return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
133 }
134
135 /**
136  * spu_bind_context - bind spu context to physical spu
137  * @spu:        physical spu to bind to
138  * @ctx:        context to bind
139  */
140 static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
141 {
142         pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
143                  spu->number, spu->node);
144         spu->ctx = ctx;
145         spu->flags = 0;
146         ctx->spu = spu;
147         ctx->ops = &spu_hw_ops;
148         spu->pid = current->pid;
149         spu->mm = ctx->owner;
150         mm_needs_global_tlbie(spu->mm);
151         spu->ibox_callback = spufs_ibox_callback;
152         spu->wbox_callback = spufs_wbox_callback;
153         spu->stop_callback = spufs_stop_callback;
154         spu->mfc_callback = spufs_mfc_callback;
155         spu->dma_callback = spufs_dma_callback;
156         mb();
157         spu_unmap_mappings(ctx);
158         spu_restore(&ctx->csa, spu);
159         spu->timestamp = jiffies;
160         spu_cpu_affinity_set(spu, raw_smp_processor_id());
161         spu_switch_notify(spu, ctx);
162         spu_add_to_active_list(spu);
163         ctx->state = SPU_STATE_RUNNABLE;
164 }
165
166 /**
167  * spu_unbind_context - unbind spu context from physical spu
168  * @spu:        physical spu to unbind from
169  * @ctx:        context to unbind
170  *
171  * If the spu was on the active list the function returns 1, else 0.
172  */
173 static int spu_unbind_context(struct spu *spu, struct spu_context *ctx)
174 {
175         int was_active = spu_remove_from_active_list(spu);
176
177         pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
178                  spu->pid, spu->number, spu->node);
179
180         spu_switch_notify(spu, NULL);
181         spu_unmap_mappings(ctx);
182         spu_save(&ctx->csa, spu);
183         spu->timestamp = jiffies;
184         ctx->state = SPU_STATE_SAVED;
185         spu->ibox_callback = NULL;
186         spu->wbox_callback = NULL;
187         spu->stop_callback = NULL;
188         spu->mfc_callback = NULL;
189         spu->dma_callback = NULL;
190         spu->mm = NULL;
191         spu->pid = 0;
192         ctx->ops = &spu_backing_ops;
193         ctx->spu = NULL;
194         spu->flags = 0;
195         spu->ctx = NULL;
196
197         return was_active;
198 }
199
200 /**
201  * spu_add_to_rq - add a context to the runqueue
202  * @ctx:       context to add
203  */
204 static void spu_add_to_rq(struct spu_context *ctx)
205 {
206         spin_lock(&spu_prio->runq_lock);
207         list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
208         set_bit(ctx->prio, spu_prio->bitmap);
209         spin_unlock(&spu_prio->runq_lock);
210 }
211
212 /**
213  * spu_del_from_rq - remove a context from the runqueue
214  * @ctx:       context to remove
215  */
216 static void spu_del_from_rq(struct spu_context *ctx)
217 {
218         spin_lock(&spu_prio->runq_lock);
219         list_del_init(&ctx->rq);
220         if (list_empty(&spu_prio->runq[ctx->prio]))
221                 clear_bit(ctx->prio, spu_prio->bitmap);
222         spin_unlock(&spu_prio->runq_lock);
223 }
224
225 /**
226  * spu_grab_context - remove one context from the runqueue
227  * @prio:      priority of the context to be removed
228  *
229  * This function removes one context from the runqueue for priority @prio.
230  * If there is more than one context with the given priority the first
231  * task on the runqueue will be taken.
232  *
233  * Returns the spu_context it just removed.
234  *
235  * Must be called with spu_prio->runq_lock held.
236  */
237 static struct spu_context *spu_grab_context(int prio)
238 {
239         struct list_head *rq = &spu_prio->runq[prio];
240
241         if (list_empty(rq))
242                 return NULL;
243         return list_entry(rq->next, struct spu_context, rq);
244 }
245
246 static void spu_prio_wait(struct spu_context *ctx)
247 {
248         DEFINE_WAIT(wait);
249
250         prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE);
251
252         if (!signal_pending(current)) {
253                 mutex_unlock(&ctx->state_mutex);
254                 schedule();
255                 mutex_lock(&ctx->state_mutex);
256         }
257         __set_current_state(TASK_RUNNING);
258         remove_wait_queue(&ctx->stop_wq, &wait);
259 }
260
261 /**
262  * spu_reschedule - try to find a runnable context for a spu
263  * @spu:       spu available
264  *
265  * This function is called whenever a spu becomes idle.  It looks for the
266  * most suitable runnable spu context and schedules it for execution.
267  */
268 static void spu_reschedule(struct spu *spu)
269 {
270         int best;
271
272         spu_free(spu);
273
274         spin_lock(&spu_prio->runq_lock);
275         best = sched_find_first_bit(spu_prio->bitmap);
276         if (best < MAX_PRIO) {
277                 struct spu_context *ctx = spu_grab_context(best);
278                 if (ctx)
279                         wake_up(&ctx->stop_wq);
280         }
281         spin_unlock(&spu_prio->runq_lock);
282 }
283
284 static struct spu *spu_get_idle(struct spu_context *ctx)
285 {
286         struct spu *spu = NULL;
287         int node = cpu_to_node(raw_smp_processor_id());
288         int n;
289
290         for (n = 0; n < MAX_NUMNODES; n++, node++) {
291                 node = (node < MAX_NUMNODES) ? node : 0;
292                 if (!node_allowed(node))
293                         continue;
294                 spu = spu_alloc_node(node);
295                 if (spu)
296                         break;
297         }
298         return spu;
299 }
300
301 /* The three externally callable interfaces
302  * for the scheduler begin here.
303  *
304  *      spu_activate    - bind a context to SPU, waiting as needed.
305  *      spu_deactivate  - unbind a context from its SPU.
306  *      spu_yield       - yield an SPU if others are waiting.
307  */
308
309 /**
310  * spu_activate - find a free spu for a context and execute it
311  * @ctx:        spu context to schedule
312  * @flags:      flags (currently ignored)
313  *
314  * Tries to find a free spu to run @ctx.  If no free spu is availble
315  * add the context to the runqueue so it gets woken up once an spu
316  * is available.
317  */
318 int spu_activate(struct spu_context *ctx, u64 flags)
319 {
320
321         if (ctx->spu)
322                 return 0;
323
324         do {
325                 struct spu *spu;
326
327                 spu = spu_get_idle(ctx);
328                 if (spu) {
329                         spu_bind_context(spu, ctx);
330                         return 0;
331                 }
332
333                 spu_add_to_rq(ctx);
334                 spu_prio_wait(ctx);
335                 spu_del_from_rq(ctx);
336         } while (!signal_pending(current));
337
338         return -ERESTARTSYS;
339 }
340
341 void spu_deactivate(struct spu_context *ctx)
342 {
343         struct spu *spu;
344         int was_active;
345
346         spu = ctx->spu;
347         if (!spu)
348                 return;
349         was_active = spu_unbind_context(spu, ctx);
350         if (was_active)
351                 spu_reschedule(spu);
352 }
353
354 void spu_yield(struct spu_context *ctx)
355 {
356         struct spu *spu;
357         int need_yield = 0;
358
359         if (mutex_trylock(&ctx->state_mutex)) {
360                 if ((spu = ctx->spu) != NULL) {
361                         int best = sched_find_first_bit(spu_prio->bitmap);
362                         if (best < MAX_PRIO) {
363                                 pr_debug("%s: yielding SPU %d NODE %d\n",
364                                          __FUNCTION__, spu->number, spu->node);
365                                 spu_deactivate(ctx);
366                                 need_yield = 1;
367                         }
368                 }
369                 mutex_unlock(&ctx->state_mutex);
370         }
371         if (unlikely(need_yield))
372                 yield();
373 }
374
375 int __init spu_sched_init(void)
376 {
377         int i;
378
379         spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
380         if (!spu_prio) {
381                 printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
382                        __FUNCTION__);
383                 return 1;
384         }
385         for (i = 0; i < MAX_PRIO; i++) {
386                 INIT_LIST_HEAD(&spu_prio->runq[i]);
387                 __clear_bit(i, spu_prio->bitmap);
388         }
389         __set_bit(MAX_PRIO, spu_prio->bitmap);
390         for (i = 0; i < MAX_NUMNODES; i++) {
391                 mutex_init(&spu_prio->active_mutex[i]);
392                 INIT_LIST_HEAD(&spu_prio->active_list[i]);
393         }
394         spin_lock_init(&spu_prio->runq_lock);
395         return 0;
396 }
397
398 void __exit spu_sched_exit(void)
399 {
400         struct spu *spu, *tmp;
401         int node;
402
403         for (node = 0; node < MAX_NUMNODES; node++) {
404                 mutex_lock(&spu_prio->active_mutex[node]);
405                 list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
406                                          list) {
407                         list_del_init(&spu->list);
408                         spu_free(spu);
409                 }
410                 mutex_unlock(&spu_prio->active_mutex[node]);
411         }
412         kfree(spu_prio);
413 }