Commit 9bf40b14 authored by Ingo Molnar's avatar Ingo Molnar

a cleanup and a bugfix in the preemptive kernel:

- the PREEMPT_ACTIVE trick is not needed

- schedule() should check for need_resched, we might miss a
  reschedule otherwise.

the cleanup also fixes the bug. The only reason why i kept
preempt_schedule() was to fix up p->state to TASK_RUNNING,
to make it possible to preempt from places that mark the
task TASK_UNINTERRUPTIBLE before adding the task to a waitqueue,
and thus a preemption in that small window could cause the
task to be removed from the runqueue erroneously.
parent e496368c
......@@ -92,7 +92,6 @@ extern unsigned long nr_running(void);
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 4
#define TASK_STOPPED 8
#define PREEMPT_ACTIVE 0x4000000
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
......
......@@ -761,6 +761,7 @@ asmlinkage void schedule(void)
if (unlikely(in_interrupt()))
BUG();
need_resched:
preempt_disable();
prev = current;
rq = this_rq();
......@@ -769,15 +770,6 @@ asmlinkage void schedule(void)
prev->sleep_timestamp = jiffies;
spin_lock_irq(&rq->lock);
#ifdef CONFIG_PREEMPT
/*
* if entering from preempt_schedule, off a kernel preemption,
* go straight to picking the next task.
*/
if (unlikely(preempt_get_count() & PREEMPT_ACTIVE))
goto pick_next_task;
#endif
switch (prev->state) {
case TASK_INTERRUPTIBLE:
if (unlikely(signal_pending(prev))) {
......@@ -789,7 +781,7 @@ asmlinkage void schedule(void)
case TASK_RUNNING:
;
}
#if CONFIG_SMP || CONFIG_PREEMPT
#if CONFIG_SMP
pick_next_task:
#endif
if (unlikely(!rq->nr_running)) {
......@@ -838,6 +830,8 @@ asmlinkage void schedule(void)
reacquire_kernel_lock(current);
preempt_enable_no_resched();
if (test_thread_flag(TIF_NEED_RESCHED))
goto need_resched;
return;
}
......@@ -847,12 +841,8 @@ asmlinkage void schedule(void)
*/
asmlinkage void preempt_schedule(void)
{
do {
current_thread_info()->preempt_count += PREEMPT_ACTIVE;
schedule();
current_thread_info()->preempt_count -= PREEMPT_ACTIVE;
barrier();
} while (test_thread_flag(TIF_NEED_RESCHED));
current->state = TASK_RUNNING;
schedule();
}
#endif /* CONFIG_PREEMPT */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment