diff options
author | Richard Braun <rbraun@sceen.net> | 2012-12-28 19:42:14 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2012-12-28 19:42:14 +0100 |
commit | b841232941239387ca81adaaa64f2887077dabd0 (patch) | |
tree | b74962886b096dfd886320482aec05c48b21e02d /kern/thread.c | |
parent | 6ce63ffacd79c6f3bd5fb690be1168732920eb12 (diff) |
kern/thread: handle preemption in thread_schedule
Diffstat (limited to 'kern/thread.c')
-rw-r--r-- | kern/thread.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/kern/thread.c b/kern/thread.c index 5cfbaf4a..4d5d74ae 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -231,24 +231,29 @@ thread_schedule(void) assert(thread_preempt_enabled()); - flags = cpu_intr_save(); + do { + thread_preempt_disable(); + flags = cpu_intr_save(); - runq = thread_runq_local(); - prev = runq->current; - assert(prev != NULL); + runq = thread_runq_local(); + prev = runq->current; + assert(prev != NULL); - if (prev != runq->idle) - thread_runq_enqueue(runq, prev); + if (prev != runq->idle) + thread_runq_enqueue(runq, prev); - next = thread_runq_dequeue(runq); + prev->flags &= ~THREAD_RESCHEDULE; + next = thread_runq_dequeue(runq); - if (next == NULL) - next = runq->idle; + if (next == NULL) + next = runq->idle; - if (prev != next) - tcb_switch(&prev->tcb, &next->tcb); + if (prev != next) + tcb_switch(&prev->tcb, &next->tcb); - cpu_intr_restore(flags); + cpu_intr_restore(flags); + thread_preempt_enable_no_resched(); + } while (prev->flags & THREAD_RESCHEDULE); } void |