aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/rm_common.c
blob: f608a084d3b86269a2653e720c5c5acf6f00b2c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * kernel/rm_common.c
 *
 * Common functions for RM based scheduler.
 */

#include <linux/percpu.h>
#include <linux/sched.h>
#include <linux/list.h>

#include <litmus/litmus.h>
#include <litmus/sched_plugin.h>
#include <litmus/sched_trace.h>

#include <litmus/rm_common.h>

/* rm_higher_prio -  returns true if first has a higher RM 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 rm priority comparison.\n");
		return 0;
	}


	/* check for NULL tasks */
	if (!first || !second)
		return first && !second;

	return !is_realtime(second_task)  ||

		/* is the deadline of the first task earlier?
		 * Then it has higher priority.
		 */
		lt_before(get_rt_period(first_task), get_rt_period(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)));
}

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);
}