/* * kernel/rm_common.c * * Common functions for EDF based scheduler. */ #include #include #include #include #include #include #include /* rm_higher_prio - returns true if first has a higher EDF priority * than second. Deadline ties are broken by PID. * * both first and second may be NULL */ int rm_higher_prio(struct task_struct* first, struct task_struct* second) { struct task_struct *first_task = first; struct task_struct *second_task = second; /* There is no point in comparing a task to itself. */ if (first && first == second) { TRACE_TASK(first, "WARNING: pointless edf priority comparison.\n"); return 0; } /* check for NULL tasks */ if (!first || !second) return first && !second; #ifdef CONFIG_LITMUS_LOCKING /* Check for inherited priorities. Change task * used for comparison in such a case. */ if (unlikely(first->rt_param.inh_task)) first_task = first->rt_param.inh_task; if (unlikely(second->rt_param.inh_task)) second_task = second->rt_param.inh_task; /* Check for priority boosting. Tie-break by start of boosting. */ if (unlikely(is_priority_boosted(first_task))) { /* first_task is boosted, how about second_task? */ if (!is_priority_boosted(second_task) || lt_before(get_boost_start(first_task), get_boost_start(second_task))) return 1; else return 0; } else if (unlikely(is_priority_boosted(second_task))) /* second_task is boosted, first is not*/ return 0; #endif if (!is_realtime(second_task)) return true; if (shorter_period(first_task, second_task)) return true; if (get_rt_period(first_task) == get_rt_period(second_task)) { #ifdef CONFIG_LITMUS_SOFTIRQD if (first_task->rt_param.is_proxy_thread < second_task->rt_param.is_proxy_thread) { return true; } if (first_task->rt_param.is_proxy_thread == second_task->rt_param.is_proxy_thread) { #endif if (first_task->pid < second_task->pid) { return true; } if (first_task->pid == second_task->pid) { return !second->rt_param.inh_task; } #ifdef CONFIG_LITMUS_SOFTIRQD } #endif } return false; #if 0 return !is_realtime(second_task) || shorter_period(first_task, second_task) || ((get_rt_period(first_task) == get_rt_period(second_task)) && earlier_deadline(first_task, second_task)) #ifdef CONFIG_LITMUS_SOFTIRQD /* proxy threads always lose w/o inheritance. */ (first_task->rt_param.is_proxy_thread < second_task->rt_param.is_proxy_thread) || #endif /* is the period of the first task shorter? * Then it has higher priority. */ shorter_period(first_task, second_task) || (earlier_deadline(first_task, second_task) || /* Do we have a deadline tie? * Then break by PID. */ (get_rt_period(first_task) == get_rt_period(second_task) && (first_task->pid < second_task->pid || /* If the PIDs are the same then the task with the inherited * priority wins. */ (first_task->pid == second_task->pid && !second->rt_param.inh_task))); #endif } int rm_ready_order(struct bheap_node* a, struct bheap_node* b) { return rm_higher_prio(bheap2task(a), bheap2task(b)); } void rm_domain_init(rt_domain_t* rt, check_resched_needed_t resched, release_jobs_t release) { rt_domain_init(rt, rm_ready_order, resched, release); } /* need_to_preempt - check whether the task t needs to be preempted * call only with irqs disabled and with ready_lock acquired * THIS DOES NOT TAKE NON-PREEMPTIVE SECTIONS INTO ACCOUNT! */ int rm_preemption_needed(rt_domain_t* rt, struct task_struct *t) { /* we need the read lock for rm_ready_queue */ /* no need to preempt if there is nothing pending */ if (!__jobs_pending(rt)) return 0; /* we need to reschedule if t doesn't exist */ if (!t) return 1; /* NOTE: We cannot check for non-preemptibility since we * don't know what address space we're currently in. */ /* make sure to get non-rt stuff out of the way */ return !is_realtime(t) || rm_higher_prio(__next_ready(rt), t); }