voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

commit 3a86ba96296bead08c90a338524dd3bf504e8942
parent 03d41e2e229a4efb1587956b27a9675c13f34ff5
Author: oblique <psyberbits@gmail.com>
Date:   Sat, 27 Oct 2012 00:13:50 +0300

fix a bug in scheduler

Diffstat:
Mkernel/sched.c | 36++++++++++++++++++++++--------------
1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/kernel/sched.c b/kernel/sched.c @@ -86,19 +86,29 @@ schedule(void) static void sched(struct regs *regs) { - struct task_struct *prev = current; - if (list_empty(&task_list_head)) return; - if (prev) { - if (prev->state != TASK_TERMINATE) - prev->regs = *regs; - - if (list_is_last(&prev->list, &task_list_head)) - current = list_first_entry(&task_list_head, struct task_struct, list); - else - current = list_entry(prev->list.next, struct task_struct, list); + if (current) { + struct list_head *iter; + struct task_struct *task, *prev; + + if (current->state != TASK_TERMINATE) + current->regs = *regs; + + prev = current; + list_for_each(iter, &prev->list) { + if (iter == &task_list_head) + continue; + task = list_entry(iter, struct task_struct, list); + if (task->state == TASK_RUNNABLE) { + current = task; + break; + } + } + + if (iter == &prev->list && prev->state != TASK_RUNNING) + current = NULL; if (prev->state == TASK_TERMINATE) { spinlock_lock(prev->lock); @@ -106,10 +116,8 @@ sched(struct regs *regs) spinlock_unlock(prev->lock); kfree(prev->stack_alloc); kfree(prev); - if (list_empty(&task_list_head)) - current = NULL; - } else - current->state = TASK_RUNNABLE; + } else if (prev != current) + prev->state = TASK_RUNNABLE; } else current = list_first_entry(&task_list_head, struct task_struct, list);