aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbipasa chattopadhyay <bipasa@cs.unc.edu>2012-03-30 17:59:22 -0400
committerbipasa chattopadhyay <bipasa@cs.unc.edu>2012-03-30 17:59:22 -0400
commit07c696041ddff8f0b39233fa0fc46d724ad83b9d (patch)
tree31d0cdba154874d67305b05cee9131270ecb6270
parent949ce5e04b64f4ddc1a0e1a101f0f838c16f5492 (diff)
MC-EDF addedwip-mc-bipasa
-rw-r--r--litmus/sched_mc_edf.c678
1 files changed, 678 insertions, 0 deletions
diff --git a/litmus/sched_mc_edf.c b/litmus/sched_mc_edf.c
new file mode 100644
index 000000000000..bdd518523cff
--- /dev/null
+++ b/litmus/sched_mc_edf.c
@@ -0,0 +1,678 @@
1/*
2 * kernel/sched_mc_edf.c
3 *
4 * Implementation of the MC-EDF scheduler plugin.
5 * Based on kern/sched_part_edf.c and kern/sched_gsn_edf.c.
6 *
7 * Suspensions and non-preemptable sections are supported.
8 * Priority inheritance is not supported.
9 */
10
11#include <linux/percpu.h>
12#include <linux/sched.h>
13#include <linux/list.h>
14#include <linux/spinlock.h>
15#include <linux/module.h>
16
17#include <litmus/litmus.h>
18#include <litmus/jobs.h>
19#include <litmus/preempt.h>
20#include <litmus/sched_plugin.h>
21#include <litmus/edf_common.h>
22#include <litmus/sched_trace.h>
23#include <litmus/trace.h>
24#include <litmus/budget.h>
25
26typedef struct {
27 int curr_cri; // mc-bipasa
28 rt_domain_t high_domain; // mc-bipasa
29 rt_domain_t domain;
30 int cpu;
31 struct task_struct* scheduled; /* only RT tasks */
32/*
33 * scheduling lock slock
34 * protects the domain and serializes scheduling decisions
35 */
36#define slock domain.ready_lock
37
38} mcedf_domain_t;
39
40DEFINE_PER_CPU(mcedf_domain_t, mcedf_domains);
41
42#define local_edf (&__get_cpu_var(mcedf_domains).domain)
43#define local_mcedf (&__get_cpu_var(mcedf_domains))
44#define remote_edf(cpu) (&per_cpu(mcedf_domains, cpu).domain)
45#define remote_mcedf(cpu) (&per_cpu(mcedf_domains, cpu))
46#define task_edf(task) remote_edf(get_partition(task))
47#define task_mcedf(task) remote_mcedf(get_partition(task))//mc-bipasa always 0
48
49
50static void mcedf_domain_init(mcedf_domain_t* mcedf,
51 check_resched_needed_t check,
52 release_jobs_t release,
53 int cpu)
54{
55 // high >= 1, low = 0
56 mcedf->curr_cri = 0;
57 edf_mc_domain_init(&mcedf->high_domain, check, release, 1); // mc-bipasa
58 edf_mc_domain_init(&mcedf->domain, check, release, 0); // mc-bipasa
59 mcedf->cpu = cpu;
60 mcedf->scheduled = NULL;
61}
62
63static void requeue(struct task_struct* t, rt_domain_t *edf)
64{
65 if (t->state != TASK_RUNNING)
66 TRACE_TASK(t, "requeue: !TASK_RUNNING\n");
67
68 set_rt_flags(t, RT_F_RUNNING);
69 if (is_released(t, litmus_clock()))
70 __add_ready(edf, t);
71 else
72 add_release(edf, t); /* it has got to wait */
73}
74
75/* we assume the lock is being held */
76static void preempt(mcedf_domain_t *mcedf)
77{
78 preempt_if_preemptable(mcedf->scheduled, mcedf->cpu);
79}
80
81#ifdef CONFIG_LITMUS_LOCKING
82
83static void boost_priority(struct task_struct* t)
84{
85 unsigned long flags;
86 mcedf_domain_t* mcedf = task_mcedf(t);
87 lt_t now;
88
89 raw_spin_lock_irqsave(&mcedf->slock, flags);
90 now = litmus_clock();
91
92 TRACE_TASK(t, "priority boosted at %llu\n", now);
93
94 tsk_rt(t)->priority_boosted = 1;
95 tsk_rt(t)->boost_start_time = now;
96
97 if (mcedf->scheduled != t) {
98 /* holder may be queued: first stop queue changes */
99 raw_spin_lock(&mcedf->domain.release_lock);
100 if (is_queued(t) &&
101 /* If it is queued, then we need to re-order. */
102 bheap_decrease(edf_ready_order, tsk_rt(t)->heap_node) &&
103 /* If we bubbled to the top, then we need to check for preemptions. */
104 edf_preemption_needed(&mcedf->domain, mcedf->scheduled))
105 preempt(mcedf);
106 raw_spin_unlock(&mcedf->domain.release_lock);
107 } /* else: nothing to do since the job is not queued while scheduled */
108
109 raw_spin_unlock_irqrestore(&mcedf->slock, flags);
110}
111
112static void unboost_priority(struct task_struct* t)
113{
114 unsigned long flags;
115 mcedf_domain_t* mcedf = task_mcedf(t);
116 lt_t now;
117
118 raw_spin_lock_irqsave(&mcedf->slock, flags);
119 now = litmus_clock();
120
121 /* assumption: this only happens when the job is scheduled */
122 BUG_ON(mcedf->scheduled != t);
123
124 TRACE_TASK(t, "priority restored at %llu\n", now);
125
126 /* priority boosted jobs must be scheduled */
127 BUG_ON(mcedf->scheduled != t);
128
129 tsk_rt(t)->priority_boosted = 0;
130 tsk_rt(t)->boost_start_time = 0;
131
132 /* check if this changes anything */
133 if (edf_preemption_needed(&mcedf->domain, mcedf->scheduled))
134 preempt(mcedf);
135
136 raw_spin_unlock_irqrestore(&mcedf->slock, flags);
137}
138
139#endif
140
141/* This check is trivial in partioned systems as we only have to consider
142 * the CPU of the partition.
143 */
144static int mcedf_check_resched(rt_domain_t *edf)
145{
146 mcedf_domain_t *mcedf = container_of(edf, mcedf_domain_t, domain);
147
148 /* because this is a callback from rt_domain_t we already hold
149 * the necessary lock for the ready queue
150 */
151 if (edf_preemption_needed(edf, mcedf->scheduled)) {
152 preempt(mcedf);
153 return 1;
154 } else
155 return 0;
156}
157
158static void job_completion(struct task_struct* t, int forced)
159{
160 sched_trace_task_completion(t,forced);
161 TRACE_TASK(t, "job_completion().\n");
162
163 set_rt_flags(t, RT_F_SLEEP);
164
165 prepare_for_next_period(t); // check
166 /*if (forced) {
167 server_release(t);
168 } else {
169 task_release(t);
170 }*/
171}
172
173static void mcedf_tick(struct task_struct *t)
174{
175 mcedf_domain_t *mcedf = local_mcedf;
176
177 /* Check for inconsistency. We don't need the lock for this since
178 * ->scheduled is only changed in schedule, which obviously is not
179 * executing in parallel on this CPU
180 */
181 BUG_ON(is_realtime(t) && t != mcedf->scheduled);
182
183 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) {
184 if (!is_np(t)) {
185 litmus_reschedule_local();
186 TRACE("mcedf_scheduler_tick: "
187 "%d is preemptable "
188 " => FORCE_RESCHED\n", t->pid);
189 } else if (is_user_np(t)) {
190 TRACE("mcedf_scheduler_tick: "
191 "%d is non-preemptable, "
192 "preemption delayed.\n", t->pid);
193 request_exit_np(t);
194 }
195 }
196}
197
198static struct task_struct* mcedf_schedule(struct task_struct * prev)
199{
200 mcedf_domain_t* mcedf = local_mcedf;
201 rt_domain_t* edf = &mcedf->domain;
202 struct task_struct* next;
203
204