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); ...@@ -92,7 +92,6 @@ extern unsigned long nr_running(void);
#define TASK_UNINTERRUPTIBLE 2 #define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 4 #define TASK_ZOMBIE 4
#define TASK_STOPPED 8 #define TASK_STOPPED 8
#define PREEMPT_ACTIVE 0x4000000
#define __set_task_state(tsk, state_value) \ #define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0) do { (tsk)->state = (state_value); } while (0)
......
...@@ -761,6 +761,7 @@ asmlinkage void schedule(void) ...@@ -761,6 +761,7 @@ asmlinkage void schedule(void)
if (unlikely(in_interrupt())) if (unlikely(in_interrupt()))
BUG(); BUG();
need_resched:
preempt_disable(); preempt_disable();
prev = current; prev = current;
rq = this_rq(); rq = this_rq();
...@@ -769,15 +770,6 @@ asmlinkage void schedule(void) ...@@ -769,15 +770,6 @@ asmlinkage void schedule(void)
prev->sleep_timestamp = jiffies; prev->sleep_timestamp = jiffies;
spin_lock_irq(&rq->lock); 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) { switch (prev->state) {
case TASK_INTERRUPTIBLE: case TASK_INTERRUPTIBLE:
if (unlikely(signal_pending(prev))) { if (unlikely(signal_pending(prev))) {
...@@ -789,7 +781,7 @@ asmlinkage void schedule(void) ...@@ -789,7 +781,7 @@ asmlinkage void schedule(void)
case TASK_RUNNING: case TASK_RUNNING:
; ;
} }
#if CONFIG_SMP || CONFIG_PREEMPT #if CONFIG_SMP
pick_next_task: pick_next_task:
#endif #endif
if (unlikely(!rq->nr_running)) { if (unlikely(!rq->nr_running)) {
...@@ -838,6 +830,8 @@ asmlinkage void schedule(void) ...@@ -838,6 +830,8 @@ asmlinkage void schedule(void)
reacquire_kernel_lock(current); reacquire_kernel_lock(current);
preempt_enable_no_resched(); preempt_enable_no_resched();
if (test_thread_flag(TIF_NEED_RESCHED))
goto need_resched;
return; return;
} }
...@@ -847,12 +841,8 @@ asmlinkage void schedule(void) ...@@ -847,12 +841,8 @@ asmlinkage void schedule(void)
*/ */
asmlinkage void preempt_schedule(void) asmlinkage void preempt_schedule(void)
{ {
do { current->state = TASK_RUNNING;
current_thread_info()->preempt_count += PREEMPT_ACTIVE; schedule();
schedule();
current_thread_info()->preempt_count -= PREEMPT_ACTIVE;
barrier();
} while (test_thread_flag(TIF_NEED_RESCHED));
} }
#endif /* CONFIG_PREEMPT */ #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