aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZelin Tong <ztong@ludwig.cs.unc.edu>2020-09-30 14:32:59 -0400
committerZelin Tong <ztong@ludwig.cs.unc.edu>2020-09-30 14:32:59 -0400
commit3f90761ec77c8d75e23d694e8fea8d5a905e7a53 (patch)
treeb7c578918bd08e51d3724e32e803cb7a8a6c0c16
parentbcb55fd97e58271de5043b95cfc37f689691513f (diff)
C2 WIP2
-rw-r--r--litmus/sched_ext_res_c1.c393
1 files changed, 393 insertions, 0 deletions
diff --git a/litmus/sched_ext_res_c1.c b/litmus/sched_ext_res_c1.c
new file mode 100644
index 000000000000..63f6d821d2d4
--- /dev/null
+++ b/litmus/sched_ext_res_c1.c
@@ -0,0 +1,393 @@
1#include <linux/percpu.h>
2#include <linux/slab.h>
3#include <linux/module.h>
4#include <asm/uaccess.h>
5
6#include <litmus/sched_plugin.h>
7#include <litmus/preempt.h>
8#include <litmus/debug_trace.h>
9
10#include <litmus/litmus.h>
11#include <litmus/jobs.h>
12#include <litmus/budget.h>
13#include <litmus/litmus_proc.h>
14#include <litmus/sched_trace.h>
15
16#include <litmus/reservations/ext_reservation.h>
17#include <litmus/reservations/gedf_reservation.h>
18
19struct gedf_reservation_environment* gedf_env;
20
21struct cpu_time {
22 struct hrtimer timer;
23 lt_t last_update_time;
24};
25
26static DEFINE_PER_CPU(struct cpu_time, cpu_time);
27
28static enum hrtimer_restart on_budget_timeout(struct hrtimer *timer)
29{
30 litmus_reschedule_local();
31 return HRTIMER_NORESTART;
32}
33
34/*
35static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
36{
37 unsigned long flags;
38 enum hrtimer_restart restart = HRTIMER_NORESTART;
39 struct pres_cpu_state *state;
40 lt_t update, now;
41
42 state = container_of(timer, struct pres_cpu_state, timer);
43
44 // The scheduling timer should only fire on the local CPU, because
45 // otherwise deadlocks via timer_cancel() are possible.
46 // Note: this does not interfere with dedicated interrupt handling, as
47 // even under dedicated interrupt handling scheduling timers for
48 // budget enforcement must occur locally on each CPU.
49 //
50 BUG_ON(state->cpu != raw_smp_processor_id());
51
52 raw_spin_lock_irqsave(&state->lock, flags);
53 sup_update_time(&state->sup_env, litmus_clock());
54
55 update = state->sup_env.next_scheduler_update;
56 now = state->sup_env.env.current_time;
57
58 TRACE_CUR("on_scheduling_timer at %llu, upd:%llu (for cpu=%d)\n",
59 now, update, state->cpu);
60
61 if (update <= now) {
62 litmus_reschedule_local();
63 } else if (update != SUP_NO_SCHEDULER_UPDATE) {
64 hrtimer_set_expires(timer, ns_to_ktime(update));
65 restart = HRTIMER_RESTART;
66 }
67
68 raw_spin_unlock_irqrestore(&state->lock, flags);
69
70 return restart;
71}
72*/
73
74static struct task_struct* ext_res_schedule(struct task_struct * prev)
75{
76 int cpu = smp_processor_id();
77 lt_t delta, time_slice;
78 struct cpu_time* entry;
79 struct task_struct* next;
80
81 entry = this_cpu_ptr(&cpu_time);
82 delta = litmus_clock() - entry->last_update_time;
83
84 //TODO: implement per cpu lt_t to track time
85
86 gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu);
87 next = gedf_env->env.ops->dispatch(&gedf_env->env, &time_slice, cpu);
88
89 entry->last_update_time = litmus_clock();
90
91 if (time_slice != ULLONG_MAX) {
92 hrtimer_start(&entry->timer,
93 ns_to_ktime(entry->last_update_time + time_slice),
94 HRTIMER_MODE_ABS_PINNED);
95 } else
96 hrtimer_try_to_cancel(&entry->timer);
97
98 sched_state_task_picked();
99
100 return next;
101}
102
103/* Called when a task should be removed from the ready queue.
104 */
105static void ext_res_task_block(struct task_struct *tsk)
106{
107 struct reservation* res;
108
109 TRACE_TASK(tsk, "thread suspends at %llu \n", litmus_clock());
110
111 res = (struct reservation*) tsk_rt(tsk)->plugin_state;
112 res->par_env->ops->remove_res(res->par_env, res, 0, 0);
113}
114
115
116/* Called when the state of tsk changes back to TASK_RUNNING.
117 * We need to requeue the task.
118 */
119static void ext_res_task_resume(struct task_struct *tsk)
120{
121 struct reservation* res;
122
123 TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock());
124
125 res = (struct reservation*) tsk_rt(tsk)->plugin_state;
126 res->par_env->ops->add_res(res->par_env, res, 0);
127}
128
129static long ext_res_admit_task(struct task_struct *tsk)
130{
131 long err = 0;
132
133 struct gedf_task_reservation* gedf_task_res;
134
135 err = alloc_gedf_task_reservation(&gedf_task_res, tsk);
136 if (err)
137 return err;
138
139 gedf_task_res->gedf_res.res.par_env = &gedf_env->env;
140
141 //TODO: for checkpoint 2, need to find component and insert into it
142
143 return 0;
144}
145
146static void ext_res_task_new(struct task_struct *tsk, int on_runqueue,
147 int is_running)
148{
149 struct reservation* res;
150 lt_t now = litmus_clock();
151
152 TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n",
153 now, on_runqueue, is_running);
154
155 res = (struct reservation*)tsk_rt(tsk)->plugin_state;
156
157 release_at(tsk, now);
158 res->replenishment_time = now;
159
160 res->par_env->ops->add_res(res->par_env, res, 0);
161
162 if (is_running)
163 litmus_reschedule_local();
164}
165
166/*
167static bool pres_fork_task(struct task_struct *tsk)
168{
169 TRACE_CUR("is forking\n");
170 TRACE_TASK(tsk, "forked child rt:%d cpu:%d task_cpu:%d "
171 "wcet:%llu per:%llu\n",
172 is_realtime(tsk),
173 tsk_rt(tsk)->task_params.cpu,
174 task_cpu(tsk),
175 tsk_rt(tsk)->task_params.exec_cost,
176 tsk_rt(tsk)->task_params.period);
177
178 // We always allow forking.
179 // The newly forked task will be in the same reservation.
180 return true;
181}
182*/
183
184static void ext_res_task_exit(struct task_struct *tsk)
185{
186 struct reservation* res;
187 struct reservation_environment* par_env;
188
189 res = (struct reservation*)tsk_rt(tsk)->plugin_state;
190 par_env = res->par_env;
191
192 par_env->ops->remove_res(par_env, res, 1, 0);
193
194 TRACE_TASK(tsk, "task exits at %llu \n", litmus_clock());
195}
196
197/* used by task budget tracking in budget.c. Since we have tasks in containers that track
198 * budget, we don't need this. Furthermore, this scheme doesn't work efficiently with
199 * multicore reservations
200 */
201/*
202static void pres_current_budget(lt_t *used_so_far, lt_t *remaining)
203{
204 struct pres_task_state *tstate = get_pres_state(current);
205 struct pres_cpu_state *state;
206
207 // FIXME: protect against concurrent task_exit()
208
209 local_irq_disable();
210
211 state = cpu_state_for(tstate->cpu);
212
213 raw_spin_lock(&state->lock);
214
215 sup_update_time(&state->sup_env, litmus_clock());
216 if (remaining)
217 *remaining = tstate->client->reservation->cur_budget;