summaryrefslogtreecommitdiff
path: root/kern/thread.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2012-12-28 19:42:14 +0100
committerRichard Braun <rbraun@sceen.net>2012-12-28 19:42:14 +0100
commitb841232941239387ca81adaaa64f2887077dabd0 (patch)
treeb74962886b096dfd886320482aec05c48b21e02d /kern/thread.c
parent6ce63ffacd79c6f3bd5fb690be1168732920eb12 (diff)
kern/thread: handle preemption in thread_schedule
Diffstat (limited to 'kern/thread.c')
-rw-r--r--kern/thread.c29
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