/* * Load-balancing iterator. Note: while the runqueue stays locked * during the whole iteration, the current task might be * dequeued so the iterator has to be dequeue-safe. Here we * achieve that by always pre-iterating before returning * the current task: */ static struct task_struct *load_balance_start_rt(void *arg) { struct rq *rq = arg; struct rt_prio_array *array = &rq->rt.active; struct list_head *head, *curr; struct task_struct *p; int idx; idx = sched_find_first_bit(array->bitmap); if (idx >= MAX_RT_PRIO) return NULL; head = array->queue + idx; curr = head->prev; p = list_entry(curr, struct task_struct, run_list); curr = curr->prev; rq->rt.rt_load_balance_idx = idx; rq->rt.rt_load_balance_head = head; rq->rt.rt_load_balance_curr = curr; return p; }
asmlinkage void schedule(void) { //... array = rq->active; if (unlikely(!array->nr_active)) { /* * Switch the active and expired arrays. */ rq->active = rq->expired; rq->expired = array; array = rq->active; rq->expired_timestamp = 0; } idx = sched_find_first_bit(array->bitmap); queue = array->queue + idx; next = list_entry(queue->next, task_t, run_list); //... if (likely(prev != next)) { next->timestamp = now; rq->nr_switches++; rq->curr = next; prepare_arch_switch(rq, next); prev = context_switch(rq, prev, next); barrier(); finish_task_switch(prev); } //... }
static struct task_struct *pick_next_task_rt(struct rq *rq) { struct rt_prio_array *array = &rq->rt.active; struct task_struct *next; struct list_head *queue; int idx; idx = sched_find_first_bit(array->bitmap); if (idx >= MAX_RT_PRIO) return NULL; queue = array->queue + idx; next = list_entry(queue->next, struct task_struct, run_list); next->se.exec_start = rq->clock; return next; }