[POWERPC] spufs: scheduler support for NUMA.

This patch adds NUMA support to the the spufs scheduler.

The new arch/powerpc/platforms/cell/spufs/sched.c is greatly
simplified, in an attempt to reduce complexity while adding
support for NUMA scheduler domains. SPUs are allocated starting
from the calling thread's node, moving to others as supported by
current->cpus_allowed. Preemption is gone as it was buggy, but
should be re-enabled in another patch when stable.

The new arch/powerpc/platforms/cell/spu_base.c maintains idle
lists on a per-node basis, and allows caller to specify which
node(s) an SPU should be allocated from, while passing -1 tells
spu_alloc() that any node is allowed.

Since the patch removes the currently implemented preemptive
scheduling, it is technically a regression, but practically
all users have since migrated to this version, as it is
part of the IBM SDK and the yellowdog distribution, so there
is not much point holding it back while the new preemptive
scheduling patch gets delayed further.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by Mark Nutter and committed by Paul Mackerras a68cf983 27d5bf2a

+203 -303
+34 -17
arch/powerpc/platforms/cell/spu_base.c
··· 317 317 free_irq(spu->irqs[2], spu); 318 318 } 319 319 320 - static LIST_HEAD(spu_list); 320 + static struct list_head spu_list[MAX_NUMNODES]; 321 321 static DEFINE_MUTEX(spu_mutex); 322 322 323 323 static void spu_init_channels(struct spu *spu) ··· 354 354 } 355 355 } 356 356 357 - struct spu *spu_alloc(void) 357 + struct spu *spu_alloc_node(int node) 358 358 { 359 - struct spu *spu; 359 + struct spu *spu = NULL; 360 360 361 361 mutex_lock(&spu_mutex); 362 - if (!list_empty(&spu_list)) { 363 - spu = list_entry(spu_list.next, struct spu, list); 362 + if (!list_empty(&spu_list[node])) { 363 + spu = list_entry(spu_list[node].next, struct spu, list); 364 364 list_del_init(&spu->list); 365 - pr_debug("Got SPU %x %d\n", spu->isrc, spu->number); 366 - } else { 367 - pr_debug("No SPU left\n"); 368 - spu = NULL; 365 + pr_debug("Got SPU %x %d %d\n", 366 + spu->isrc, spu->number, spu->node); 367 + spu_init_channels(spu); 369 368 } 370 369 mutex_unlock(&spu_mutex); 371 370 372 - if (spu) 373 - spu_init_channels(spu); 371 + return spu; 372 + } 373 + EXPORT_SYMBOL_GPL(spu_alloc_node); 374 + 375 + struct spu *spu_alloc(void) 376 + { 377 + struct spu *spu = NULL; 378 + int node; 379 + 380 + for (node = 0; node < MAX_NUMNODES; node++) { 381 + spu = spu_alloc_node(node); 382 + if (spu) 383 + break; 384 + } 374 385 375 386 return spu; 376 387 } 377 - EXPORT_SYMBOL_GPL(spu_alloc); 378 388 379 389 void spu_free(struct spu *spu) 380 390 { 381 391 mutex_lock(&spu_mutex); 382 - list_add_tail(&spu->list, &spu_list); 392 + list_add_tail(&spu->list, &spu_list[spu->node]); 383 393 mutex_unlock(&spu_mutex); 384 394 } 385 395 EXPORT_SYMBOL_GPL(spu_free); ··· 722 712 if (ret) 723 713 goto out_free_irqs; 724 714 725 - list_add(&spu->list, &spu_list); 715 + list_add(&spu->list, &spu_list[spu->node]); 726 716 mutex_unlock(&spu_mutex); 727 717 728 718 pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", ··· 755 745 static void cleanup_spu_base(void) 756 746 { 757 747 struct spu *spu, *tmp; 748 + int node; 749 + 758 750 mutex_lock(&spu_mutex); 759 - list_for_each_entry_safe(spu, tmp, &spu_list, list) 760 - destroy_spu(spu); 751 + for (node = 0; node < MAX_NUMNODES; node++) { 752 + list_for_each_entry_safe(spu, tmp, &spu_list[node], list) 753 + destroy_spu(spu); 754 + } 761 755 mutex_unlock(&spu_mutex); 762 756 sysdev_class_unregister(&spu_sysdev_class); 763 757 } ··· 770 756 static int __init init_spu_base(void) 771 757 { 772 758 struct device_node *node; 773 - int ret; 759 + int i, ret; 774 760 775 761 /* create sysdev class for spus */ 776 762 ret = sysdev_class_register(&spu_sysdev_class); 777 763 if (ret) 778 764 return ret; 765 + 766 + for (i = 0; i < MAX_NUMNODES; i++) 767 + INIT_LIST_HEAD(&spu_list[i]); 779 768 780 769 ret = -ENODEV; 781 770 for (node = of_find_node_by_type(NULL, "spe");
+168 -286
arch/powerpc/platforms/cell/spufs/sched.c
··· 3 3 * Copyright (C) IBM 2005 4 4 * Author: Mark Nutter <mnutter@us.ibm.com> 5 5 * 6 - * SPU scheduler, based on Linux thread priority. For now use 7 - * a simple "cooperative" yield model with no preemption. SPU 8 - * scheduling will eventually be preemptive: When a thread with 9 - * a higher static priority gets ready to run, then an active SPU 10 - * context will be preempted and returned to the waitq. 6 + * 2006-03-31 NUMA domains added. 11 7 * 12 8 * This program is free software; you can redistribute it and/or modify 13 9 * it under the terms of the GNU General Public License as published by ··· 33 37 #include <linux/smp_lock.h> 34 38 #include <linux/stddef.h> 35 39 #include <linux/unistd.h> 40 + #include <linux/numa.h> 41 + #include <linux/mutex.h> 36 42 37 43 #include <asm/io.h> 38 44 #include <asm/mmu_context.h> ··· 47 49 48 50 #define SPU_BITMAP_SIZE (((MAX_PRIO+BITS_PER_LONG)/BITS_PER_LONG)+1) 49 51 struct spu_prio_array { 50 - atomic_t nr_blocked; 51 52 unsigned long bitmap[SPU_BITMAP_SIZE]; 52 53 wait_queue_head_t waitq[MAX_PRIO]; 54 + struct list_head active_list[MAX_NUMNODES]; 55 + struct mutex active_mutex[MAX_NUMNODES]; 53 56 }; 54 57 55 - /* spu_runqueue - This is the main runqueue data structure for SPUs. */ 56 - struct spu_runqueue { 57 - struct semaphore sem; 58 - unsigned long nr_active; 59 - unsigned long nr_idle; 60 - unsigned long nr_switches; 61 - struct list_head active_list; 62 - struct list_head idle_list; 63 - struct spu_prio_array prio; 64 - }; 58 + static struct spu_prio_array *spu_prio; 65 59 66 - static struct spu_runqueue *spu_runqueues = NULL; 67 - 68 - static inline struct spu_runqueue *spu_rq(void) 60 + static inline int node_allowed(int node) 69 61 { 70 - /* Future: make this a per-NODE array, 71 - * and use cpu_to_node(smp_processor_id()) 72 - */ 73 - return spu_runqueues; 74 - } 62 + cpumask_t mask; 75 63 76 - static inline struct spu *del_idle(struct spu_runqueue *rq) 77 - { 78 - struct spu *spu; 79 - 80 - BUG_ON(rq->nr_idle <= 0); 81 - BUG_ON(list_empty(&rq->idle_list)); 82 - /* Future: Move SPU out of low-power SRI state. */ 83 - spu = list_entry(rq->idle_list.next, struct spu, sched_list); 84 - list_del_init(&spu->sched_list); 85 - rq->nr_idle--; 86 - return spu; 87 - } 88 - 89 - static inline void del_active(struct spu_runqueue *rq, struct spu *spu) 90 - { 91 - BUG_ON(rq->nr_active <= 0); 92 - BUG_ON(list_empty(&rq->active_list)); 93 - list_del_init(&spu->sched_list); 94 - rq->nr_active--; 95 - } 96 - 97 - static inline void add_idle(struct spu_runqueue *rq, struct spu *spu) 98 - { 99 - /* Future: Put SPU into low-power SRI state. */ 100 - list_add_tail(&spu->sched_list, &rq->idle_list); 101 - rq->nr_idle++; 102 - } 103 - 104 - static inline void add_active(struct spu_runqueue *rq, struct spu *spu) 105 - { 106 - rq->nr_active++; 107 - rq->nr_switches++; 108 - list_add_tail(&spu->sched_list, &rq->active_list); 109 - } 110 - 111 - static void prio_wakeup(struct spu_runqueue *rq) 112 - { 113 - if (atomic_read(&rq->prio.nr_blocked) && rq->nr_idle) { 114 - int best = sched_find_first_bit(rq->prio.bitmap); 115 - if (best < MAX_PRIO) { 116 - wait_queue_head_t *wq = &rq->prio.waitq[best]; 117 - wake_up_interruptible_nr(wq, 1); 118 - } 119 - } 120 - } 121 - 122 - static void prio_wait(struct spu_runqueue *rq, struct spu_context *ctx, 123 - u64 flags) 124 - { 125 - int prio = current->prio; 126 - wait_queue_head_t *wq = &rq->prio.waitq[prio]; 127 - DEFINE_WAIT(wait); 128 - 129 - __set_bit(prio, rq->prio.bitmap); 130 - atomic_inc(&rq->prio.nr_blocked); 131 - prepare_to_wait_exclusive(wq, &wait, TASK_INTERRUPTIBLE); 132 - if (!signal_pending(current)) { 133 - up(&rq->sem); 134 - up_write(&ctx->state_sema); 135 - pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__, 136 - current->pid, current->prio); 137 - schedule(); 138 - down_write(&ctx->state_sema); 139 - down(&rq->sem); 140 - } 141 - finish_wait(wq, &wait); 142 - atomic_dec(&rq->prio.nr_blocked); 143 - if (!waitqueue_active(wq)) 144 - __clear_bit(prio, rq->prio.bitmap); 145 - } 146 - 147 - static inline int is_best_prio(struct spu_runqueue *rq) 148 - { 149 - int best_prio; 150 - 151 - best_prio = sched_find_first_bit(rq->prio.bitmap); 152 - return (current->prio < best_prio) ? 1 : 0; 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; 153 70 } 154 71 155 72 static inline void mm_needs_global_tlbie(struct mm_struct *mm) 156 73 { 74 + int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1; 75 + 157 76 /* Global TLBIE broadcast required with SPEs. */ 158 - #if (NR_CPUS > 1) 159 - __cpus_setall(&mm->cpu_vm_mask, NR_CPUS); 160 - #else 161 - __cpus_setall(&mm->cpu_vm_mask, NR_CPUS+1); /* is this ok? */ 162 - #endif 77 + __cpus_setall(&mm->cpu_vm_mask, nr); 163 78 } 164 79 165 80 static inline void bind_context(struct spu *spu, struct spu_context *ctx) 166 81 { 167 - pr_debug("%s: pid=%d SPU=%d\n", __FUNCTION__, current->pid, 168 - spu->number); 82 + pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, 83 + spu->number, spu->node); 169 84 spu->ctx = ctx; 170 85 spu->flags = 0; 171 86 ctx->flags = 0; ··· 96 185 spu_unmap_mappings(ctx); 97 186 spu_restore(&ctx->csa, spu); 98 187 spu->timestamp = jiffies; 188 + spu_cpu_affinity_set(spu, raw_smp_processor_id()); 99 189 } 100 190 101 191 static inline void unbind_context(struct spu *spu, struct spu_context *ctx) 102 192 { 103 - pr_debug("%s: unbind pid=%d SPU=%d\n", __FUNCTION__, 104 - spu->pid, spu->number); 193 + pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, 194 + spu->pid, spu->number, spu->node); 105 195 spu_unmap_mappings(ctx); 106 196 spu_save(&ctx->csa, spu); 107 197 spu->timestamp = jiffies; ··· 121 209 spu->ctx = NULL; 122 210 } 123 211 124 - static void spu_reaper(void *data) 212 + static inline void spu_add_wq(wait_queue_head_t * wq, wait_queue_t * wait, 213 + int prio) 125 214 { 126 - struct spu_context *ctx = data; 127 - struct spu *spu; 215 + prepare_to_wait_exclusive(wq, wait, TASK_INTERRUPTIBLE); 216 + set_bit(prio, spu_prio->bitmap); 217 + } 128 218 129 - down_write(&ctx->state_sema); 130 - spu = ctx->spu; 131 - if (spu && test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) { 132 - if (atomic_read(&spu->rq->prio.nr_blocked)) { 133 - pr_debug("%s: spu=%d\n", __func__, spu->number); 134 - ctx->ops->runcntl_stop(ctx); 135 - spu_deactivate(ctx); 136 - wake_up_all(&ctx->stop_wq); 137 - } else { 138 - clear_bit(SPU_CONTEXT_PREEMPT, &ctx->flags); 139 - } 219 + static inline void spu_del_wq(wait_queue_head_t * wq, wait_queue_t * wait, 220 + int prio) 221 + { 222 + u64 flags; 223 + 224 + __set_current_state(TASK_RUNNING); 225 + 226 + spin_lock_irqsave(&wq->lock, flags); 227 + 228 + remove_wait_queue_locked(wq, wait); 229 + if (list_empty(&wq->task_list)) 230 + clear_bit(prio, spu_prio->bitmap); 231 + 232 + spin_unlock_irqrestore(&wq->lock, flags); 233 + } 234 + 235 + static void spu_prio_wait(struct spu_context *ctx, u64 flags) 236 + { 237 + int prio = current->prio; 238 + wait_queue_head_t *wq = &spu_prio->waitq[prio]; 239 + DEFINE_WAIT(wait); 240 + 241 + if (ctx->spu) 242 + return; 243 + 244 + spu_add_wq(wq, &wait, prio); 245 + 246 + if (!signal_pending(current)) { 247 + up_write(&ctx->state_sema); 248 + pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__, 249 + current->pid, current->prio); 250 + schedule(); 251 + down_write(&ctx->state_sema); 140 252 } 141 - up_write(&ctx->state_sema); 142 - put_spu_context(ctx); 253 + 254 + spu_del_wq(wq, &wait, prio); 143 255 } 144 256 145 - static void schedule_spu_reaper(struct spu_runqueue *rq, struct spu *spu) 257 + static void spu_prio_wakeup(void) 146 258 { 147 - struct spu_context *ctx = get_spu_context(spu->ctx); 148 - unsigned long now = jiffies; 149 - unsigned long expire = spu->timestamp + SPU_MIN_TIMESLICE; 150 - 151 - set_bit(SPU_CONTEXT_PREEMPT, &ctx->flags); 152 - INIT_WORK(&ctx->reap_work, spu_reaper, ctx); 153 - if (time_after(now, expire)) 154 - schedule_work(&ctx->reap_work); 155 - else 156 - schedule_delayed_work(&ctx->reap_work, expire - now); 157 - } 158 - 159 - static void check_preempt_active(struct spu_runqueue *rq) 160 - { 161 - struct list_head *p; 162 - struct spu *worst = NULL; 163 - 164 - list_for_each(p, &rq->active_list) { 165 - struct spu *spu = list_entry(p, struct spu, sched_list); 166 - struct spu_context *ctx = spu->ctx; 167 - if (!test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) { 168 - if (!worst || (spu->prio > worst->prio)) { 169 - worst = spu; 170 - } 171 - } 259 + int best = sched_find_first_bit(spu_prio->bitmap); 260 + if (best < MAX_PRIO) { 261 + wait_queue_head_t *wq = &spu_prio->waitq[best]; 262 + wake_up_interruptible_nr(wq, 1); 172 263 } 173 - if (worst && (current->prio < worst->prio)) 174 - schedule_spu_reaper(rq, worst); 175 - } 176 - 177 - static struct spu *get_idle_spu(struct spu_context *ctx, u64 flags) 178 - { 179 - struct spu_runqueue *rq; 180 - struct spu *spu = NULL; 181 - 182 - rq = spu_rq(); 183 - down(&rq->sem); 184 - for (;;) { 185 - if (rq->nr_idle > 0) { 186 - if (is_best_prio(rq)) { 187 - /* Fall through. */ 188 - spu = del_idle(rq); 189 - break; 190 - } else { 191 - prio_wakeup(rq); 192 - up(&rq->sem); 193 - yield(); 194 - if (signal_pending(current)) { 195 - return NULL; 196 - } 197 - rq = spu_rq(); 198 - down(&rq->sem); 199 - continue; 200 - } 201 - } else { 202 - check_preempt_active(rq); 203 - prio_wait(rq, ctx, flags); 204 - if (signal_pending(current)) { 205 - prio_wakeup(rq); 206 - spu = NULL; 207 - break; 208 - } 209 - continue; 210 - } 211 - } 212 - up(&rq->sem); 213 - return spu; 214 - } 215 - 216 - static void put_idle_spu(struct spu *spu) 217 - { 218 - struct spu_runqueue *rq = spu->rq; 219 - 220 - down(&rq->sem); 221 - add_idle(rq, spu); 222 - prio_wakeup(rq); 223 - up(&rq->sem); 224 264 } 225 265 226 266 static int get_active_spu(struct spu *spu) 227 267 { 228 - struct spu_runqueue *rq = spu->rq; 229 - struct list_head *p; 268 + int node = spu->node; 230 269 struct spu *tmp; 231 270 int rc = 0; 232 271 233 - down(&rq->sem); 234 - list_for_each(p, &rq->active_list) { 235 - tmp = list_entry(p, struct spu, sched_list); 272 + mutex_lock(&spu_prio->active_mutex[node]); 273 + list_for_each_entry(tmp, &spu_prio->active_list[node], list) { 236 274 if (tmp == spu) { 237 - del_active(rq, spu); 275 + list_del_init(&spu->list); 238 276 rc = 1; 239 277 break; 240 278 } 241 279 } 242 - up(&rq->sem); 280 + mutex_unlock(&spu_prio->active_mutex[node]); 243 281 return rc; 244 282 } 245 283 246 284 static void put_active_spu(struct spu *spu) 247 285 { 248 - struct spu_runqueue *rq = spu->rq; 286 + int node = spu->node; 249 287 250 - down(&rq->sem); 251 - add_active(rq, spu); 252 - up(&rq->sem); 288 + mutex_lock(&spu_prio->active_mutex[node]); 289 + list_add_tail(&spu->list, &spu_prio->active_list[node]); 290 + mutex_unlock(&spu_prio->active_mutex[node]); 253 291 } 254 292 255 - /* Lock order: 256 - * spu_activate() & spu_deactivate() require the 257 - * caller to have down_write(&ctx->state_sema). 293 + static struct spu *spu_get_idle(struct spu_context *ctx, u64 flags) 294 + { 295 + struct spu *spu = NULL; 296 + int node = cpu_to_node(raw_smp_processor_id()); 297 + int n; 298 + 299 + for (n = 0; n < MAX_NUMNODES; n++, node++) { 300 + node = (node < MAX_NUMNODES) ? node : 0; 301 + if (!node_allowed(node)) 302 + continue; 303 + spu = spu_alloc_node(node); 304 + if (spu) 305 + break; 306 + } 307 + return spu; 308 + } 309 + 310 + static inline struct spu *spu_get(struct spu_context *ctx, u64 flags) 311 + { 312 + /* Future: spu_get_idle() if possible, 313 + * otherwise try to preempt an active 314 + * context. 315 + */ 316 + return spu_get_idle(ctx, flags); 317 + } 318 + 319 + /* The three externally callable interfaces 320 + * for the scheduler begin here. 258 321 * 259 - * The rq->sem is breifly held (inside or outside a 260 - * given ctx lock) for list management, but is never 261 - * held during save/restore. 322 + * spu_activate - bind a context to SPU, waiting as needed. 323 + * spu_deactivate - unbind a context from its SPU. 324 + * spu_yield - yield an SPU if others are waiting. 262 325 */ 263 326 264 327 int spu_activate(struct spu_context *ctx, u64 flags) 265 328 { 266 329 struct spu *spu; 330 + int ret = 0; 267 331 268 - if (ctx->spu) 269 - return 0; 270 - spu = get_idle_spu(ctx, flags); 271 - if (!spu) 272 - return (signal_pending(current)) ? -ERESTARTSYS : -EAGAIN; 273 - bind_context(spu, ctx); 274 - /* 275 - * We're likely to wait for interrupts on the same 276 - * CPU that we are now on, so send them here. 277 - */ 278 - spu_cpu_affinity_set(spu, raw_smp_processor_id()); 279 - put_active_spu(spu); 280 - return 0; 332 + for (;;) { 333 + if (ctx->spu) 334 + return 0; 335 + spu = spu_get(ctx, flags); 336 + if (spu != NULL) { 337 + if (ctx->spu != NULL) { 338 + spu_free(spu); 339 + spu_prio_wakeup(); 340 + break; 341 + } 342 + bind_context(spu, ctx); 343 + put_active_spu(spu); 344 + break; 345 + } 346 + spu_prio_wait(ctx, flags); 347 + if (signal_pending(current)) { 348 + ret = -ERESTARTSYS; 349 + spu_prio_wakeup(); 350 + break; 351 + } 352 + } 353 + return ret; 281 354 } 282 355 283 356 void spu_deactivate(struct spu_context *ctx) ··· 275 378 return; 276 379 needs_idle = get_active_spu(spu); 277 380 unbind_context(spu, ctx); 278 - if (needs_idle) 279 - put_idle_spu(spu); 381 + if (needs_idle) { 382 + spu_free(spu); 383 + spu_prio_wakeup(); 384 + } 280 385 } 281 386 282 387 void spu_yield(struct spu_context *ctx) ··· 286 387 struct spu *spu; 287 388 int need_yield = 0; 288 389 289 - down_write(&ctx->state_sema); 290 - spu = ctx->spu; 291 - if (spu && (sched_find_first_bit(spu->rq->prio.bitmap) < MAX_PRIO)) { 292 - pr_debug("%s: yielding SPU %d\n", __FUNCTION__, spu->number); 293 - spu_deactivate(ctx); 294 - ctx->state = SPU_STATE_SAVED; 295 - need_yield = 1; 296 - } else if (spu) { 297 - spu->prio = MAX_PRIO; 390 + if (down_write_trylock(&ctx->state_sema)) { 391 + if ((spu = ctx->spu) != NULL) { 392 + int best = sched_find_first_bit(spu_prio->bitmap); 393 + if (best < MAX_PRIO) { 394 + pr_debug("%s: yielding SPU %d NODE %d\n", 395 + __FUNCTION__, spu->number, spu->node); 396 + spu_deactivate(ctx); 397 + ctx->state = SPU_STATE_SAVED; 398 + need_yield = 1; 399 + } else { 400 + spu->prio = MAX_PRIO; 401 + } 402 + } 403 + up_write(&ctx->state_sema); 298 404 } 299 - up_write(&ctx->state_sema); 300 405 if (unlikely(need_yield)) 301 406 yield(); 302 407 } 303 408 304 409 int __init spu_sched_init(void) 305 410 { 306 - struct spu_runqueue *rq; 307 - struct spu *spu; 308 411 int i; 309 412 310 - rq = spu_runqueues = kmalloc(sizeof(struct spu_runqueue), GFP_KERNEL); 311 - if (!rq) { 312 - printk(KERN_WARNING "%s: Unable to allocate runqueues.\n", 413 + spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); 414 + if (!spu_prio) { 415 + printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", 313 416 __FUNCTION__); 314 417 return 1; 315 418 } 316 - memset(rq, 0, sizeof(struct spu_runqueue)); 317 - init_MUTEX(&rq->sem); 318 - INIT_LIST_HEAD(&rq->active_list); 319 - INIT_LIST_HEAD(&rq->idle_list); 320 - rq->nr_active = 0; 321 - rq->nr_idle = 0; 322 - rq->nr_switches = 0; 323 - atomic_set(&rq->prio.nr_blocked, 0); 324 419 for (i = 0; i < MAX_PRIO; i++) { 325 - init_waitqueue_head(&rq->prio.waitq[i]); 326 - __clear_bit(i, rq->prio.bitmap); 420 + init_waitqueue_head(&spu_prio->waitq[i]); 421 + __clear_bit(i, spu_prio->bitmap); 327 422 } 328 - __set_bit(MAX_PRIO, rq->prio.bitmap); 329 - for (;;) { 330 - spu = spu_alloc(); 331 - if (!spu) 332 - break; 333 - pr_debug("%s: adding SPU[%d]\n", __FUNCTION__, spu->number); 334 - add_idle(rq, spu); 335 - spu->rq = rq; 336 - spu->timestamp = jiffies; 337 - } 338 - if (!rq->nr_idle) { 339 - printk(KERN_WARNING "%s: No available SPUs.\n", __FUNCTION__); 340 - kfree(rq); 341 - return 1; 423 + __set_bit(MAX_PRIO, spu_prio->bitmap); 424 + for (i = 0; i < MAX_NUMNODES; i++) { 425 + mutex_init(&spu_prio->active_mutex[i]); 426 + INIT_LIST_HEAD(&spu_prio->active_list[i]); 342 427 } 343 428 return 0; 344 429 } 345 430 346 431 void __exit spu_sched_exit(void) 347 432 { 348 - struct spu_runqueue *rq = spu_rq(); 349 - struct spu *spu; 433 + struct spu *spu, *tmp; 434 + int node; 350 435 351 - if (!rq) { 352 - printk(KERN_WARNING "%s: no runqueues!\n", __FUNCTION__); 353 - return; 436 + for (node = 0; node < MAX_NUMNODES; node++) { 437 + mutex_lock(&spu_prio->active_mutex[node]); 438 + list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], 439 + list) { 440 + list_del_init(&spu->list); 441 + spu_free(spu); 442 + } 443 + mutex_unlock(&spu_prio->active_mutex[node]); 354 444 } 355 - while (rq->nr_idle > 0) { 356 - spu = del_idle(rq); 357 - if (!spu) 358 - break; 359 - spu_free(spu); 360 - } 361 - kfree(rq); 445 + kfree(spu_prio); 362 446 }
+1
include/asm-powerpc/spu.h
··· 147 147 }; 148 148 149 149 struct spu *spu_alloc(void); 150 + struct spu *spu_alloc_node(int node); 150 151 void spu_free(struct spu *spu); 151 152 int spu_irq_class_0_bottom(struct spu *spu); 152 153 int spu_irq_class_1_bottom(struct spu *spu);