This does not look symmetrical, add and sub and bitops...
> +#define PREEMPT_ACTIVE 0x4000000
> + /*
> + * 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;
> +
> + do {
> + current_thread_info()->preempt_count += PREEMPT_ACTIVE;
> + schedule();
> + current_thread_info()->preempt_count -= PREEMPT_ACTIVE;
> + barrier();
And since it has to be zero to end up in the routine anyway...
asmlinkage void preempt_schedule(void)
{
BUG_ON(current_thread_info()->preempt_count != 0);
do {
/* Problem: suppose a new interrupt happens before we got to set
* preempt_count... then we will call this routine recursively.
* innermost will select the correct process, but wont it be scheduled
* away in enclosing preempt_schedule() - schedule() will be called
* with PREEMPT_ACTIVE but not TIF_NEED_RESCHED...
* (goto pick_next_task) */
current_thread_info()->preempt_count = PREEMPT_ACTIVE;
/* interrupts here might cause calls to preempt_schedule() but those will
bounce off above since preempt_count != 0 */
schedule();
current_thread_info()->preempt_count = 0;
/* interrupt here will possibly preempt the right process - no problem */
/* need to check if any interrupt happened during the preemption off time,
* this case is in fact unlikely */
while (unlikely(test_thread_flag(TIF_NEED_RESCHED)));
}
/RogerL
-- Roger Larsson Skellefteċ Sweden- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/