Rev 898 | Rev 907 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 898 | Rev 906 | ||
---|---|---|---|
Line 61... | Line 61... | ||
61 | * |
61 | * |
62 | */ |
62 | */ |
63 | void before_thread_runs(void) |
63 | void before_thread_runs(void) |
64 | { |
64 | { |
65 | before_thread_runs_arch(); |
65 | before_thread_runs_arch(); |
66 | #ifdef CONFIG_FPU_LAZY |
66 | #ifdef CONFIG_FPU_LAZY |
67 | if(THREAD==CPU->fpu_owner) |
67 | if(THREAD==CPU->fpu_owner) |
68 | fpu_enable(); |
68 | fpu_enable(); |
69 | else |
69 | else |
70 | fpu_disable(); |
70 | fpu_disable(); |
71 | #else |
71 | #else |
72 | fpu_enable(); |
72 | fpu_enable(); |
73 | if (THREAD->fpu_context_exists) |
73 | if (THREAD->fpu_context_exists) |
74 | fpu_context_restore(&(THREAD->saved_fpu_context)); |
74 | fpu_context_restore(THREAD->saved_fpu_context); |
75 | else { |
75 | else { |
76 | fpu_init(&(THREAD->saved_fpu_context)); |
76 | fpu_init(); |
77 | THREAD->fpu_context_exists=1; |
77 | THREAD->fpu_context_exists=1; |
78 | } |
78 | } |
79 | #endif |
79 | #endif |
80 | } |
80 | } |
81 | 81 | ||
82 | /** Take actions after THREAD had run. |
82 | /** Take actions after THREAD had run. |
83 | * |
83 | * |
84 | * Perform actions that need to be |
84 | * Perform actions that need to be |
Line 100... | Line 100... | ||
100 | spinlock_lock(&CPU->lock); |
100 | spinlock_lock(&CPU->lock); |
101 | 101 | ||
102 | /* Save old context */ |
102 | /* Save old context */ |
103 | if (CPU->fpu_owner != NULL) { |
103 | if (CPU->fpu_owner != NULL) { |
104 | spinlock_lock(&CPU->fpu_owner->lock); |
104 | spinlock_lock(&CPU->fpu_owner->lock); |
105 | fpu_context_save(&CPU->fpu_owner->saved_fpu_context); |
105 | fpu_context_save(CPU->fpu_owner->saved_fpu_context); |
106 | /* don't prevent migration */ |
106 | /* don't prevent migration */ |
107 | CPU->fpu_owner->fpu_context_engaged=0; |
107 | CPU->fpu_owner->fpu_context_engaged=0; |
108 | spinlock_unlock(&CPU->fpu_owner->lock); |
108 | spinlock_unlock(&CPU->fpu_owner->lock); |
109 | } |
109 | } |
110 | 110 | ||
111 | spinlock_lock(&THREAD->lock); |
111 | spinlock_lock(&THREAD->lock); |
112 | if (THREAD->fpu_context_exists) { |
112 | if (THREAD->fpu_context_exists) { |
113 | fpu_context_restore(&THREAD->saved_fpu_context); |
113 | fpu_context_restore(THREAD->saved_fpu_context); |
114 | } else { |
114 | } else { |
- | 115 | /* Allocate FPU context */ |
|
115 | fpu_init(&(THREAD->saved_fpu_context)); |
116 | if (!THREAD->saved_fpu_context) { |
- | 117 | /* Might sleep */ |
|
- | 118 | spinlock_unlock(&THREAD->lock); |
|
- | 119 | THREAD->saved_fpu_context = slab_alloc(fpu_context_slab, |
|
- | 120 | 0); |
|
- | 121 | spinlock_lock(&THREAD->lock); |
|
- | 122 | } |
|
- | 123 | fpu_init(); |
|
116 | THREAD->fpu_context_exists=1; |
124 | THREAD->fpu_context_exists=1; |
117 | } |
125 | } |
118 | CPU->fpu_owner=THREAD; |
126 | CPU->fpu_owner=THREAD; |
119 | THREAD->fpu_context_engaged = 1; |
127 | THREAD->fpu_context_engaged = 1; |
120 | spinlock_unlock(&THREAD->lock); |
128 | spinlock_unlock(&THREAD->lock); |
Line 272... | Line 280... | ||
272 | if (atomic_get(&haltstate)) |
280 | if (atomic_get(&haltstate)) |
273 | halt(); |
281 | halt(); |
274 | 282 | ||
275 | if (THREAD) { |
283 | if (THREAD) { |
276 | spinlock_lock(&THREAD->lock); |
284 | spinlock_lock(&THREAD->lock); |
277 | #ifndef CONFIG_FPU_LAZY |
285 | #ifndef CONFIG_FPU_LAZY |
278 | fpu_context_save(&(THREAD->saved_fpu_context)); |
286 | fpu_context_save(THREAD->saved_fpu_context); |
279 | #endif |
287 | #endif |
280 | if (!context_save(&THREAD->saved_context)) { |
288 | if (!context_save(&THREAD->saved_context)) { |
281 | /* |
289 | /* |
282 | * This is the place where threads leave scheduler(); |
290 | * This is the place where threads leave scheduler(); |
283 | */ |
291 | */ |
284 | spinlock_unlock(&THREAD->lock); |
292 | spinlock_unlock(&THREAD->lock); |
Line 419... | Line 427... | ||
419 | * Both tasks and address spaces are different. |
427 | * Both tasks and address spaces are different. |
420 | * Replace the old one with the new one. |
428 | * Replace the old one with the new one. |
421 | */ |
429 | */ |
422 | as_switch(as1, as2); |
430 | as_switch(as1, as2); |
423 | } |
431 | } |
424 | TASK = THREAD->task; |
432 | TASK = THREAD->task; |
425 | } |
433 | } |
426 | 434 | ||
427 | THREAD->state = Running; |
435 | THREAD->state = Running; |
428 | 436 | ||
429 | #ifdef SCHEDULER_VERBOSE |
437 | #ifdef SCHEDULER_VERBOSE |
430 | printf("cpu%d: tid %d (priority=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, atomic_get(&CPU->nrdy)); |
438 | printf("cpu%d: tid %d (priority=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, atomic_get(&CPU->nrdy)); |
431 | #endif |
439 | #endif |
432 | 440 | ||
433 | /* |
441 | /* |
434 | * Some architectures provide late kernel PA2KA(identity) |
442 | * Some architectures provide late kernel PA2KA(identity) |
435 | * mapping in a page fault handler. However, the page fault |
443 | * mapping in a page fault handler. However, the page fault |
436 | * handler uses the kernel stack of the running thread and |
444 | * handler uses the kernel stack of the running thread and |
Line 544... | Line 552... | ||
544 | if (t) { |
552 | if (t) { |
545 | /* |
553 | /* |
546 | * Ready t on local CPU |
554 | * Ready t on local CPU |
547 | */ |
555 | */ |
548 | spinlock_lock(&t->lock); |
556 | spinlock_lock(&t->lock); |
549 | #ifdef KCPULB_VERBOSE |
557 | #ifdef KCPULB_VERBOSE |
550 | printf("kcpulb%d: TID %d -> cpu%d, nrdy=%d, avg=%d\n", CPU->id, t->tid, CPU->id, atomic_get(&CPU->nrdy), atomic_get(&nrdy) / config.cpu_active); |
558 | printf("kcpulb%d: TID %d -> cpu%d, nrdy=%d, avg=%d\n", CPU->id, t->tid, CPU->id, atomic_get(&CPU->nrdy), atomic_get(&nrdy) / config.cpu_active); |
551 | #endif |
559 | #endif |
552 | t->flags |= X_STOLEN; |
560 | t->flags |= X_STOLEN; |
553 | spinlock_unlock(&t->lock); |
561 | spinlock_unlock(&t->lock); |
554 | 562 | ||
555 | thread_ready(t); |
563 | thread_ready(t); |
556 | 564 |