aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2009-12-17 21:32:31 -0500
committerAndrea Bastoni <bastoni@cs.unc.edu>2009-12-17 21:32:31 -0500
commita4dc9c48f83ebcb68cd99d118cd34c5e265cfd34 (patch)
tree18940992d7a1e2abd1c155c83c6e5d40abebb774
parentb7ca066915c003a0138f80f04aec9a3c30c873f3 (diff)
Add common EDF functions
-rw-r--r--include/litmus/edf_common.h27
-rw-r--r--litmus/Makefile1
-rw-r--r--litmus/edf_common.c102
3 files changed, 130 insertions, 0 deletions
diff --git a/include/litmus/edf_common.h b/include/litmus/edf_common.h
new file mode 100644
index 000000000000..166cdac6bcab
--- /dev/null
+++ b/include/litmus/edf_common.h
@@ -0,0 +1,27 @@
1/*
2 * EDF common data structures and utility functions shared by all EDF
3 * based scheduler plugins
4 */
5
6/* CLEANUP: Add comments and make it less messy.
7 *
8 */
9
10#ifndef __UNC_EDF_COMMON_H__
11#define __UNC_EDF_COMMON_H__
12
13#include <litmus/rt_domain.h>
14
15void edf_domain_init(rt_domain_t* rt, check_resched_needed_t resched,
16 release_jobs_t release);
17
18int edf_higher_prio(struct task_struct* first,
19 struct task_struct* second);
20
21int edf_ready_order(struct heap_node* a, struct heap_node* b);
22
23int edf_preemption_needed(rt_domain_t* rt, struct task_struct *t);
24
25int edf_set_hp_task(struct pi_semaphore *sem);
26int edf_set_hp_cpu_task(struct pi_semaphore *sem, int cpu);
27#endif
diff --git a/litmus/Makefile b/litmus/Makefile
index 576c1ded20e9..59f61cbc7f10 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -6,6 +6,7 @@ obj-y = sched_plugin.o litmus.o \
6 jobs.o \ 6 jobs.o \
7 sync.o \ 7 sync.o \
8 rt_domain.o \ 8 rt_domain.o \
9 edf_common.o \
9 heap.o 10 heap.o
10 11
11obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o 12obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o
diff --git a/litmus/edf_common.c b/litmus/edf_common.c
new file mode 100644
index 000000000000..97e37761cedc
--- /dev/null
+++ b/litmus/edf_common.c
@@ -0,0 +1,102 @@
1/*
2 * kernel/edf_common.c
3 *
4 * Common functions for EDF based scheduler.
5 */
6
7#include <linux/percpu.h>
8#include <linux/sched.h>
9#include <linux/list.h>
10
11#include <litmus/litmus.h>
12#include <litmus/sched_plugin.h>
13#include <litmus/sched_trace.h>
14
15#include <litmus/edf_common.h>
16
17/* edf_higher_prio - returns true if first has a higher EDF priority
18 * than second. Deadline ties are broken by PID.
19 *
20 * both first and second may be NULL
21 */
22int edf_higher_prio(struct task_struct* first,
23 struct task_struct* second)
24{
25 struct task_struct *first_task = first;
26 struct task_struct *second_task = second;
27
28 /* There is no point in comparing a task to itself. */
29 if (first && first == second) {
30 TRACE_TASK(first,
31 "WARNING: pointless edf priority comparison.\n");
32 return 0;
33 }
34
35
36 /* Check for inherited priorities. Change task
37 * used for comparison in such a case.
38 */
39 if (first && first->rt_param.inh_task)
40 first_task = first->rt_param.inh_task;
41 if (second && second->rt_param.inh_task)
42 second_task = second->rt_param.inh_task;
43
44 return
45 /* it has to exist in order to have higher priority */
46 first_task && (
47 /* does the second task exist and is it a real-time task? If
48 * not, the first task (which is a RT task) has higher
49 * priority.
50 */
51 !second_task || !is_realtime(second_task) ||
52
53 /* is the deadline of the first task earlier?
54 * Then it has higher priority.
55 */
56 earlier_deadline(first_task, second_task) ||
57
58 /* Do we have a deadline tie?
59 * Then break by PID.
60 */
61 (get_deadline(first_task) == get_deadline(second_task) &&
62 (first_task->pid < second_task->pid ||
63
64 /* If the PIDs are the same then the task with the inherited
65 * priority wins.
66 */
67 (first_task->pid == second_task->pid &&
68 !second->rt_param.inh_task))));
69}
70
71int edf_ready_order(struct heap_node* a, struct heap_node* b)
72{
73 return edf_higher_prio(heap2task(a), heap2task(b));
74}
75
76void edf_domain_init(rt_domain_t* rt, check_resched_needed_t resched,
77 release_jobs_t release)
78{
79 rt_domain_init(rt, edf_ready_order, resched, release);
80}
81
82/* need_to_preempt - check whether the task t needs to be preempted
83 * call only with irqs disabled and with ready_lock acquired
84 * THIS DOES NOT TAKE NON-PREEMPTIVE SECTIONS INTO ACCOUNT!
85 */
86int edf_preemption_needed(rt_domain_t* rt, struct task_struct *t)
87{
88 /* we need the read lock for edf_ready_queue */
89 /* no need to preempt if there is nothing pending */
90 if (!__jobs_pending(rt))
91 return 0;
92 /* we need to reschedule if t doesn't exist */
93 if (!t)
94 return 1;
95
96 /* NOTE: We cannot check for non-preemptibility since we
97 * don't know what address space we're currently in.
98 */
99
100 /* make sure to get non-rt stuff out of the way */
101 return !is_realtime(t) || edf_higher_prio(__next_ready(rt), t);
102}