Re: [patch] Real-Time Preemption, deactivate() scheduling issue

Ingo Molnar
2005-03-29T08:51:38Z

* Eugeny S. Mints <emints@ru.mvista.com> wrote:

> please consider the following scenario for full RT kernel.
>
> Task A is running then an irq is occured which in turn wakes up irq
> related thread (B) of a higher priority than A.
>
> my current understanding that actual context switch between A and B will
> occure at preempt_schedule_irq() on the "return form irq " path.
>
> in this case the following "if" statement in __schedule() always returns
> false since preempt_schedule_irq() always sets up PREEMPT_ACTIVE
> before __schedule() call.
>
> if ((prev->state & ~TASK_RUNNING_MUTEX) &&
> !(preempt_count() & PREEMPT_ACTIVE)) {
>
> as result the deactivate() is never called for preempted task A in this
> scenario. BUt if the task A is preempted while not in TASK_RUNNING state
> such behaviour seems incorrect since we get a task in not TASK_RUNNING
> state linked into a run queue.

this behavior is intentional: 'forced preemption' (of any sort, even in
the upstream kernel's CONFIG_PREEMPT model) should not impact the task's
state. So it does not modify p->state. [ The TASK_RUNNING_MUTEX state
furthermore enables wakeups to occur in an invariant way: even though
technically the tasks are on the runqueue, a 'normal' wakeup is still
noticed and later on acted upon.]

this is very important for forced preemption to not impact the coding
model of kernel code that is normally tested with !PREEMPT. (the
TASK_RUNNING_MUTEX scheduler feature furthermore enables us to preempt
without impacting wakeup logic.)

> An example:
>
> drivers/net/irda/sir_dev.c: 76 (2.6.10 kernel)
>
> spin_lock_irqsave(&dev->tx_lock, flags); /* serialize th other
> tx operations */
> while (dev->tx_buff.len > 0) { /* wait until tx idle */
> spin_unlock_irqrestore(&dev->tx_lock, flags);
> 76: set_current_state(TASK_UNINTERRUPTIBLE);
> schedule_timeout(msecs_to_jiffies(10));
> spin_lock_irqsave(&dev->tx_lock, flags);
> }
>
> At line 76 irqs are enabled, preemption is enabled.
> Let assume the task A executes this code and gets preempted right after
> line 76. Task state is TASK_UNINTERRUPTIBLE but it will not be
> deactevated. Of cource this is the bug in set_current_state()
> utilization in this particular driver but schedule stuff should be
> robust to such bugs I believe. There are a lot such bugs in the kernel I
> believe.

it is not a problem to have tasks with TASK_UNINTERRUPTIBLE on the
runqueue - this happens every day with CONFIG_PREEMPT kernels, and it's
fully intentional. Can you see any bugs caused by this behavior?

Ingo