How about this ( draft ) :
struct task_struct {
...
struct task_struct * wlist_next;
...
};
static union {
struct schedule_data {
struct task_struct * curr;
struct task_struct * wlist;
cycles_t last_schedule;
} schedule_data;
char __pad [SMP_CACHE_BYTES];
} aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}};
static inline struct task_struct * wpick(aligned_data * ad) {
struct task_struct * tsk = ad->wlist;
if (tsk) {
ad->wlist = tsk->wlist_next;
add_to_runqueue(tsk);
}
return tsk;
}
static inline void wpush(aligned_data * ad, struct task_struct * tsk) {
if (task_on_runqueue(tsk))
list_del(&tsk->run_list);
tsk->wlist_next = ad->wlist;
ad->wlist = tsk;
}
asmlinkage void schedule(void)
{
...
if ((next = wpick(sched_data)))
goto ...;
...
}
In reschedule_idle() when before sending the IPI we do a wpush().
We modify aligned_data->wlist and tsk->wlist_next under runqueue_lock so we
don't need another one.
A slight change is needed to reschedule_idle() to handle the new field.
Pros to this solution are 1) we are not going to give other fields a different
meaning 2) when the idle will call schedule it'll pick the task w/o rescan.
- Davide
-
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/