aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhoon Kim <namhoonk@cs.unc.edu>2015-01-24 04:55:04 -0500
committerNamhoon Kim <namhoonk@cs.unc.edu>2015-01-24 04:55:04 -0500
commit5be3aecdd4b8b0beb981cc0f7fc84b0d0ded2c47 (patch)
tree7df48cce968c60a37b9c11d4b03b852b201f5d67
parent6583dcfbda43e420921e3adf7f2e46dc719e8d26 (diff)
slack stealing
-rw-r--r--include/litmus/mc2_common.h2
-rw-r--r--include/litmus/reservation.h44
-rw-r--r--include/litmus/rt_param.h4
-rw-r--r--litmus/jobs.c1
-rw-r--r--litmus/polling_reservations.c28
-rw-r--r--litmus/reservation.c16
-rw-r--r--litmus/sched_mc2.c185
7 files changed, 237 insertions, 43 deletions
diff --git a/include/litmus/mc2_common.h b/include/litmus/mc2_common.h
index bdc3a6d82a56..e3c0af28f1b9 100644
--- a/include/litmus/mc2_common.h
+++ b/include/litmus/mc2_common.h
@@ -21,6 +21,8 @@ struct mc2_task {
21 21
22#include <litmus/reservation.h> 22#include <litmus/reservation.h>
23 23
24#define tsk_mc2_data(t) (tsk_rt(t)->mc2_data)
25
24long mc2_task_client_init(struct task_client *tc, struct mc2_task *mc2_param, struct task_struct *tsk, 26long mc2_task_client_init(struct task_client *tc, struct mc2_task *mc2_param, struct task_struct *tsk,
25 struct reservation *res); 27 struct reservation *res);
26 28
diff --git a/include/litmus/reservation.h b/include/litmus/reservation.h
index 4eecd3f088e8..5ccb20055a56 100644
--- a/include/litmus/reservation.h
+++ b/include/litmus/reservation.h
@@ -126,6 +126,9 @@ struct reservation {
126 struct reservation_ops *ops; 126 struct reservation_ops *ops;
127 127
128 struct list_head clients; 128 struct list_head clients;
129
130 /* for global env. */
131 int scheduled_on;
129}; 132};
130 133
131void reservation_init(struct reservation *res); 134void reservation_init(struct reservation *res);
@@ -185,10 +188,51 @@ struct sup_reservation_environment {
185void sup_init(struct sup_reservation_environment* sup_env); 188void sup_init(struct sup_reservation_environment* sup_env);
186void sup_add_new_reservation(struct sup_reservation_environment* sup_env, 189void sup_add_new_reservation(struct sup_reservation_environment* sup_env,
187 struct reservation* new_res); 190 struct reservation* new_res);
191void sup_scheduler_update_after(struct sup_reservation_environment* sup_env,
192 lt_t timeout);
188void sup_update_time(struct sup_reservation_environment* sup_env, lt_t now); 193void sup_update_time(struct sup_reservation_environment* sup_env, lt_t now);
189struct task_struct* sup_dispatch(struct sup_reservation_environment* sup_env); 194struct task_struct* sup_dispatch(struct sup_reservation_environment* sup_env);
190 195
191struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env, 196struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env,
192 unsigned int id); 197 unsigned int id);
198
199/* A global multiprocessor reservation environment. */
193 200
201struct next_timer_event {
202 lt_t next_update;
203 int timer_armed_on;
204 unsigned int id;
205 struct list_head list;
206};
207
208struct gmp_reservation_environment {
209 raw_spinlock_t lock;
210 struct reservation_environment env;
211
212 /* ordered by priority */
213 struct list_head active_reservations;
214
215 /* ordered by next_replenishment */
216 struct list_head depleted_reservations;
217
218 /* unordered */
219 struct list_head inactive_reservations;
220
221 /* timer event ordered by next_update */
222 struct list_head next_events;
223 /* (schedule_now == true) means call gmp_dispatch() now */
224 bool schedule_now;
225 /* set to true if a call to gmp_dispatch() is imminent */
226 bool will_schedule;
227};
228/*
229void gmp_init(struct gmp_reservation_environment* gmp_env);
230void gmp_add_new_reservation(struct gmp_reservation_environment* gmp_env,
231 struct reservation* new_res);
232void gmp_update_time(struct gmp_reservation_environment* gmp_env, lt_t now);
233struct task_struct* gmp_dispatch(struct gmp_reservation_environment* gmp_env);
234
235struct reservation* gmp_find_by_id(struct gmp_reservation_environment* gmp_env,
236 unsigned int id);
237*/
194#endif 238#endif
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index e626bbbe60d5..284b89e95a51 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -206,6 +206,7 @@ struct rt_job {
206}; 206};
207 207
208struct pfair_param; 208struct pfair_param;
209struct mc2_task;
209 210
210/* RT task parameters for scheduling extensions 211/* RT task parameters for scheduling extensions
211 * These parameters are inherited during clone and therefore must 212 * These parameters are inherited during clone and therefore must
@@ -322,6 +323,9 @@ struct rt_param {
322 323
323 /* Pointer to the page shared between userspace and kernel. */ 324 /* Pointer to the page shared between userspace and kernel. */
324 struct control_page * ctrl_page; 325 struct control_page * ctrl_page;
326
327 /* Mixed-criticality specific data */
328 struct mc2_task* mc2_data;
325}; 329};
326 330
327#endif 331#endif
diff --git a/litmus/jobs.c b/litmus/jobs.c
index 547222c3387a..e523e29ea8a6 100644
--- a/litmus/jobs.c
+++ b/litmus/jobs.c
@@ -45,6 +45,7 @@ void release_at(struct task_struct *t, lt_t start)
45{ 45{
46 BUG_ON(!t); 46 BUG_ON(!t);
47 setup_release(t, start); 47 setup_release(t, start);
48 TRACE("RELEASE!!\n");
48 tsk_rt(t)->completed = 0; 49 tsk_rt(t)->completed = 0;
49} 50}
50 51
diff --git a/litmus/polling_reservations.c b/litmus/polling_reservations.c
index 4c07ee74bf39..941a371c26e9 100644
--- a/litmus/polling_reservations.c
+++ b/litmus/polling_reservations.c
@@ -19,11 +19,19 @@ static void periodic_polling_client_arrives(
19 switch (res->state) { 19 switch (res->state) {
20 case RESERVATION_INACTIVE: 20 case RESERVATION_INACTIVE:
21 /* Figure out next replenishment time. */ 21 /* Figure out next replenishment time. */
22 tmp = res->env->current_time - res->env->time_zero; 22 if (res->env->time_zero == 0) {
23 instances = div64_u64(tmp, pres->period); 23 tmp = res->env->current_time - res->env->time_zero;
24 res->next_replenishment = 24 instances = div64_u64(tmp, pres->period);
25 (instances + 1) * pres->period + pres->offset; 25 res->next_replenishment =
26 26 (instances + 1) * pres->period + pres->offset;
27 }
28 else {
29 tmp = res->env->current_time - res->env->time_zero;
30 instances = div64_u64(tmp, pres->period);
31 res->next_replenishment = res->env->time_zero + instances * pres->period;
32 }
33
34 TRACE("ENV_TIME_ZERO %llu\n", res->env->time_zero);
27 TRACE("pol-res: activate tmp=%llu instances=%llu period=%llu nextrp=%llu cur=%llu\n", 35 TRACE("pol-res: activate tmp=%llu instances=%llu period=%llu nextrp=%llu cur=%llu\n",
28 tmp, instances, pres->period, res->next_replenishment, 36 tmp, instances, pres->period, res->next_replenishment,
29 res->env->current_time); 37 res->env->current_time);
@@ -62,9 +70,10 @@ static void periodic_polling_client_departs(
62 case RESERVATION_ACTIVE: 70 case RESERVATION_ACTIVE:
63 if (list_empty(&res->clients)) { 71 if (list_empty(&res->clients)) {
64 res->env->change_state(res->env, res, 72 res->env->change_state(res->env, res,
65 did_signal_job_completion ?
66 RESERVATION_DEPLETED :
67 RESERVATION_ACTIVE_IDLE); 73 RESERVATION_ACTIVE_IDLE);
74// did_signal_job_completion ?
75// RESERVATION_DEPLETED :
76// RESERVATION_ACTIVE_IDLE);
68 } /* else: nothing to do, more clients ready */ 77 } /* else: nothing to do, more clients ready */
69 break; 78 break;
70 79
@@ -86,6 +95,7 @@ static void periodic_polling_on_replenishment(
86 res->next_replenishment += pres->period; 95 res->next_replenishment += pres->period;
87 res->budget_consumed = 0; 96 res->budget_consumed = 0;
88 97
98 TRACE("polling_replenish(%u): next_replenishment=%llu\n", res->id, res->next_replenishment);
89 switch (res->state) { 99 switch (res->state) {
90 case RESERVATION_DEPLETED: 100 case RESERVATION_DEPLETED:
91 case RESERVATION_INACTIVE: 101 case RESERVATION_INACTIVE:
@@ -270,6 +280,7 @@ void polling_reservation_init(
270 pres->period = period; 280 pres->period = period;
271 pres->deadline = deadline; 281 pres->deadline = deadline;
272 pres->offset = offset; 282 pres->offset = offset;
283 TRACE_TASK(current, "polling_reservation_init: periodic %d, use_edf %d\n", use_periodic_polling, use_edf_prio);
273 if (use_periodic_polling) { 284 if (use_periodic_polling) {
274 if (use_edf_prio) 285 if (use_edf_prio)
275 pres->res.ops = &periodic_polling_ops_edf; 286 pres->res.ops = &periodic_polling_ops_edf;
@@ -460,7 +471,8 @@ static void td_drain_budget(
460 switch (res->state) { 471 switch (res->state) {
461 case RESERVATION_DEPLETED: 472 case RESERVATION_DEPLETED:
462 case RESERVATION_INACTIVE: 473 case RESERVATION_INACTIVE:
463 BUG(); 474 //BUG();
475 TRACE("TD_DRAIN!!!!!!!!! RES_STATE = %d\n", res->state);
464 break; 476 break;
465 477
466 case RESERVATION_ACTIVE_IDLE: 478 case RESERVATION_ACTIVE_IDLE:
diff --git a/litmus/reservation.c b/litmus/reservation.c
index 0e43479ff2e1..2dc3dc2b4688 100644
--- a/litmus/reservation.c
+++ b/litmus/reservation.c
@@ -48,11 +48,12 @@ static void sup_scheduler_update_at(
48 struct sup_reservation_environment* sup_env, 48 struct sup_reservation_environment* sup_env,
49 lt_t when) 49 lt_t when)
50{ 50{
51 TRACE("SCHEDULER_UPDATE_AT update: %llu > when %llu\n", sup_env->next_scheduler_update, when);
51 if (sup_env->next_scheduler_update > when) 52 if (sup_env->next_scheduler_update > when)
52 sup_env->next_scheduler_update = when; 53 sup_env->next_scheduler_update = when;
53} 54}
54 55
55static void sup_scheduler_update_after( 56void sup_scheduler_update_after(
56 struct sup_reservation_environment* sup_env, 57 struct sup_reservation_environment* sup_env,
57 lt_t timeout) 58 lt_t timeout)
58{ 59{
@@ -192,10 +193,13 @@ static void sup_charge_budget(
192 /* charge all ACTIVE_IDLE up to the first ACTIVE reservation */ 193 /* charge all ACTIVE_IDLE up to the first ACTIVE reservation */
193 res = list_entry(pos, struct reservation, list); 194 res = list_entry(pos, struct reservation, list);
194 if (res->state == RESERVATION_ACTIVE) { 195 if (res->state == RESERVATION_ACTIVE) {
195 res->ops->drain_budget(res, delta); 196 TRACE("sup_charge_budget ACTIVE R%u drain %llu\n", res->id, delta);
197 if (encountered_active == 0)
198 res->ops->drain_budget(res, delta);
196 encountered_active = 1; 199 encountered_active = 1;
197 } else { 200 } else {
198 BUG_ON(res->state != RESERVATION_ACTIVE_IDLE); 201 BUG_ON(res->state != RESERVATION_ACTIVE_IDLE);
202 TRACE("sup_charge_budget INACTIVE R%u drain %llu\n", res->id, delta);
199 res->ops->drain_budget(res, delta); 203 res->ops->drain_budget(res, delta);
200 } 204 }
201 if (res->state == RESERVATION_ACTIVE || 205 if (res->state == RESERVATION_ACTIVE ||
@@ -207,9 +211,9 @@ static void sup_charge_budget(
207 res->id, res->cur_budget); 211 res->id, res->cur_budget);
208 sup_scheduler_update_after(sup_env, res->cur_budget); 212 sup_scheduler_update_after(sup_env, res->cur_budget);
209 } 213 }
210 if (encountered_active) 214 //if (encountered_active == 2)
211 /* stop at the first ACTIVE reservation */ 215 /* stop at the first ACTIVE reservation */
212 break; 216 // break;
213 } 217 }
214 //TRACE("finished charging budgets\n"); 218 //TRACE("finished charging budgets\n");
215} 219}
@@ -246,7 +250,7 @@ void sup_update_time(
246 /* If the time didn't advance, there is nothing to do. 250 /* If the time didn't advance, there is nothing to do.
247 * This check makes it safe to call sup_advance_time() potentially 251 * This check makes it safe to call sup_advance_time() potentially
248 * multiple times (e.g., via different code paths. */ 252 * multiple times (e.g., via different code paths. */
249 //TRACE("(sup_update_time) now: %llu, current_time: %llu\n", now, sup_env->env.current_time); 253 TRACE("(sup_update_time) now: %llu, current_time: %llu\n", now, sup_env->env.current_time);
250 if (unlikely(now <= sup_env->env.current_time)) 254 if (unlikely(now <= sup_env->env.current_time))
251 return; 255 return;
252 256
@@ -258,9 +262,11 @@ void sup_update_time(
258 sup_env->next_scheduler_update = SUP_NO_SCHEDULER_UPDATE; 262 sup_env->next_scheduler_update = SUP_NO_SCHEDULER_UPDATE;
259 263
260 /* deplete budgets by passage of time */ 264 /* deplete budgets by passage of time */
265 TRACE("CHARGE###\n");
261 sup_charge_budget(sup_env, delta); 266 sup_charge_budget(sup_env, delta);
262 267
263 /* check if any budgets where replenished */ 268 /* check if any budgets where replenished */
269 TRACE("REPLENISH###\n");
264 sup_replenish_budgets(sup_env); 270 sup_replenish_budgets(sup_env);
265} 271}
266 272
diff --git a/litmus/sched_mc2.c b/litmus/sched_mc2.c
index b9f05238461b..6b29d527fa3a 100644
--- a/litmus/sched_mc2.c
+++ b/litmus/sched_mc2.c
@@ -22,15 +22,22 @@ struct mc2_task_state {
22 struct mc2_task mc2_param; 22 struct mc2_task mc2_param;
23}; 23};
24 24
25struct crit_entry {
26 enum crit_level level;
27 struct task_struct *running;
28 struct hrtimer ghost_timer;
29};
30
25struct mc2_cpu_state { 31struct mc2_cpu_state {
26 raw_spinlock_t lock; 32 raw_spinlock_t lock;
27 33
28 struct sup_reservation_environment sup_env; 34 struct sup_reservation_environment sup_env;
29 struct hrtimer timer; 35 struct hrtimer timer;
36 struct hrtimer g_timer;
30 37
31 int cpu; 38 int cpu;
32 struct task_struct* scheduled; 39 struct task_struct* scheduled;
33 enum crit_level run_level; 40 struct crit_entry crit_entries[NUM_CRIT_LEVELS];
34}; 41};
35 42
36static DEFINE_PER_CPU(struct mc2_cpu_state, mc2_cpu_state); 43static DEFINE_PER_CPU(struct mc2_cpu_state, mc2_cpu_state);
@@ -42,30 +49,53 @@ static struct mc2_task_state* get_mc2_state(struct task_struct *tsk)
42{ 49{
43 return (struct mc2_task_state*) tsk_rt(tsk)->plugin_state; 50 return (struct mc2_task_state*) tsk_rt(tsk)->plugin_state;
44} 51}
52static enum crit_level get_task_crit_level(struct task_struct *tsk)
53{
54 struct mc2_task_state *tinfo = get_mc2_state(tsk);
55 if (!tinfo)
56 return NUM_CRIT_LEVELS;
57 else
58 return tinfo->mc2_param.crit;
59}
45 60
46static void task_departs(struct task_struct *tsk, int job_complete) 61static void task_departs(struct task_struct *tsk, int job_complete)
47{ 62{
48 struct mc2_task_state* state = get_mc2_state(tsk); 63 struct mc2_task_state* tinfo = get_mc2_state(tsk);
64 struct mc2_cpu_state* state = local_cpu_state();
49 struct reservation* res; 65 struct reservation* res;
50 struct reservation_client *client; 66 struct reservation_client *client;
51 67
52 res = state->res_info.client.reservation; 68 res = tinfo->res_info.client.reservation;
53 client = &state->res_info.client; 69 client = &tinfo->res_info.client;
54 70
55 res->ops->client_departs(res, client, job_complete); 71 res->ops->client_departs(res, client, job_complete);
56 state->has_departed = true; 72 tinfo->has_departed = true;
73 TRACE_TASK(tsk, "CLIENT DEPART with budget %llu\n", res->cur_budget);
74 if (job_complete && res->cur_budget) {
75 struct crit_entry* ce;
76 enum crit_level lv = tinfo->mc2_param.crit;
77 //lt_t now = litmus_clock();
78
79 ce = &state->crit_entries[lv];
80 ce->running = tsk;
81 TRACE_TASK(tsk, "BECOME GHOST at %llu\n", litmus_clock());
82
83 BUG_ON(hrtimer_active(&ce->ghost_timer));
84 //TRACE("setting GHOST timer %llu\n", ns_to_ktime(now + res->cur_budget));
85 //__hrtimer_start_range_ns(&ce->ghost_timer, ns_to_ktime(now + res->cur_budget), 0, HRTIMER_MODE_ABS_PINNED, 0);
86 }
57} 87}
58 88
59static void task_arrives(struct task_struct *tsk) 89static void task_arrives(struct task_struct *tsk)
60{ 90{
61 struct mc2_task_state* state = get_mc2_state(tsk); 91 struct mc2_task_state* tinfo = get_mc2_state(tsk);
62 struct reservation* res; 92 struct reservation* res;
63 struct reservation_client *client; 93 struct reservation_client *client;
64 94
65 res = state->res_info.client.reservation; 95 res = tinfo->res_info.client.reservation;
66 client = &state->res_info.client; 96 client = &tinfo->res_info.client;
67 97
68 state->has_departed = false; 98 tinfo->has_departed = false;
69 res->ops->client_arrives(res, client); 99 res->ops->client_arrives(res, client);
70} 100}
71 101
@@ -94,7 +124,7 @@ static void mc2_update_timer_and_unlock(struct mc2_cpu_state *state)
94 /* Reprogram only if not already set correctly. */ 124 /* Reprogram only if not already set correctly. */
95 if (!hrtimer_active(&state->timer) || 125 if (!hrtimer_active(&state->timer) ||
96 ktime_to_ns(hrtimer_get_expires(&state->timer)) != update) { 126 ktime_to_ns(hrtimer_get_expires(&state->timer)) != update) {
97 TRACE("canceling timer...\n"); 127 TRACE("canceling timer...at %llu\n", ktime_to_ns(hrtimer_get_expires(&state->timer)));
98 hrtimer_cancel(&state->timer); 128 hrtimer_cancel(&state->timer);
99 TRACE("setting scheduler timer for %llu\n", update); 129 TRACE("setting scheduler timer for %llu\n", update);
100 /* We cannot use hrtimer_start() here because the 130 /* We cannot use hrtimer_start() here because the
@@ -127,6 +157,49 @@ static void mc2_update_timer_and_unlock(struct mc2_cpu_state *state)
127 } 157 }
128} 158}
129 159
160static void mc2_update_ghost_state(struct mc2_cpu_state *state)
161{
162 int lv = 0;
163 struct crit_entry* ce;
164 struct reservation *res;
165 struct mc2_task_state *tinfo;
166
167 for (lv = 0; lv < NUM_CRIT_LEVELS; lv++) {
168 ce = &state->crit_entries[lv];
169 if (ce->running != NULL) {
170 tinfo = get_mc2_state(ce->running);
171 if (lv != CRIT_LEVEL_C)
172 res = sup_find_by_id(&state->sup_env, tinfo->mc2_param.res_id);
173 else
174 continue;
175 TRACE("LV %d running id %d budget %llu\n", lv, tinfo->mc2_param.res_id, res->cur_budget);
176 if (!res->cur_budget) {
177 TRACE("GHOST FINISH id %d at %llu\n", tinfo->mc2_param.res_id, litmus_clock());
178 ce->running = NULL;
179 }
180 }
181 }
182}
183
184static enum hrtimer_restart on_ghost_timer(struct hrtimer *timer)
185{
186 struct crit_entry *ce;
187 struct mc2_cpu_state *state;
188
189 ce = container_of(timer, struct crit_entry, ghost_timer);
190 state = container_of(ce, struct mc2_cpu_state, crit_entries[ce->level]);
191
192 TRACE("GHOST_TIMER FIRED at %llu\n", litmus_clock());
193
194 raw_spin_lock(&state->lock);
195 sup_update_time(&state->sup_env, litmus_clock());
196 mc2_update_ghost_state(state);
197
198 raw_spin_unlock(&state->lock);
199
200 return HRTIMER_NORESTART;
201}
202
130static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) 203static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
131{ 204{
132 unsigned long flags; 205 unsigned long flags;
@@ -144,9 +217,11 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
144 */ 217 */
145 BUG_ON(state->cpu != raw_smp_processor_id()); 218 BUG_ON(state->cpu != raw_smp_processor_id());
146 219
220 TRACE("TIMER FIRED at %llu\n", litmus_clock());
147 raw_spin_lock_irqsave(&state->lock, flags); 221 raw_spin_lock_irqsave(&state->lock, flags);
148 sup_update_time(&state->sup_env, litmus_clock()); 222 sup_update_time(&state->sup_env, litmus_clock());
149 223 mc2_update_ghost_state(state);
224
150 update = state->sup_env.next_scheduler_update; 225 update = state->sup_env.next_scheduler_update;
151 now = state->sup_env.env.current_time; 226 now = state->sup_env.env.current_time;
152 227
@@ -165,6 +240,36 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
165 return restart; 240 return restart;
166} 241}
167 242
243struct task_struct* mc2_dispatch(struct sup_reservation_environment* sup_env, struct mc2_cpu_state* state)
244{
245 struct reservation *res, *next;
246 struct task_struct *tsk = NULL;
247 struct crit_entry *ce;
248 enum crit_level lv;
249 lt_t time_slice;
250
251 list_for_each_entry_safe(res, next, &sup_env->active_reservations, list) {
252 if (res->state == RESERVATION_ACTIVE) {
253 tsk = res->ops->dispatch_client(res, &time_slice);
254 if (likely(tsk)) {
255 lv = get_task_crit_level(tsk);
256 if (lv == NUM_CRIT_LEVELS) {
257 sup_scheduler_update_after(sup_env, res->cur_budget);
258 return tsk;
259 } else {
260 ce = &state->crit_entries[lv];
261 if (likely(!ce->running)) {
262 sup_scheduler_update_after(sup_env, res->cur_budget);
263 return tsk;
264 }
265 }
266 }
267 }
268 }
269
270 return NULL;
271}
272
168static struct task_struct* mc2_schedule(struct task_struct * prev) 273static struct task_struct* mc2_schedule(struct task_struct * prev)
169{ 274{
170 /* next == NULL means "schedule background work". */ 275 /* next == NULL means "schedule background work". */
@@ -178,14 +283,17 @@ static struct task_struct* mc2_schedule(struct task_struct * prev)
178 283
179 /* update time */ 284 /* update time */
180 state->sup_env.will_schedule = true; 285 state->sup_env.will_schedule = true;
286 TRACE_TASK(prev, "MC2_SCHEDULE sup_update_time ####\n");
181 sup_update_time(&state->sup_env, litmus_clock()); 287 sup_update_time(&state->sup_env, litmus_clock());
182 288 TRACE_TASK(prev, "MC2_SCHEDULE sup_update_time !!!!\n");
289 mc2_update_ghost_state(state);
290
183 /* remove task from reservation if it blocks */ 291 /* remove task from reservation if it blocks */
184 if (is_realtime(prev) && !is_running(prev)) 292 if (is_realtime(prev) && !is_running(prev))
185 task_departs(prev, is_completed(prev)); 293 task_departs(prev, is_completed(prev));
186 294
187 /* figure out what to schedule next */ 295 /* figure out what to schedule next */
188 state->scheduled = sup_dispatch(&state->sup_env); 296 state->scheduled = mc2_dispatch(&state->sup_env, state);
189 297
190 /* Notify LITMUS^RT core that we've arrived at a scheduling decision. */ 298 /* Notify LITMUS^RT core that we've arrived at a scheduling decision. */
191 sched_state_task_picked(); 299 sched_state_task_picked();
@@ -197,7 +305,6 @@ static struct task_struct* mc2_schedule(struct task_struct * prev)
197 305
198 if (prev != state->scheduled && is_realtime(prev)) { 306 if (prev != state->scheduled && is_realtime(prev)) {
199 TRACE_TASK(prev, "descheduled.\n"); 307 TRACE_TASK(prev, "descheduled.\n");
200 state->run_level = NUM_CRIT_LEVELS;
201 } 308 }
202 if (state->scheduled) { 309 if (state->scheduled) {
203 TRACE_TASK(state->scheduled, "scheduled.\n"); 310 TRACE_TASK(state->scheduled, "scheduled.\n");
@@ -242,9 +349,10 @@ static void mc2_task_resume(struct task_struct *tsk)
242 * since we might not actually be executing on tinfo->cpu 349 * since we might not actually be executing on tinfo->cpu
243 * at the moment. */ 350 * at the moment. */
244 sup_update_time(&state->sup_env, litmus_clock()); 351 sup_update_time(&state->sup_env, litmus_clock());
352 mc2_update_ghost_state(state);
245 task_arrives(tsk); 353 task_arrives(tsk);
246 /* NOTE: drops state->lock */ 354 /* NOTE: drops state->lock */
247 TRACE("mc2_resume()\n"); 355 TRACE_TASK(tsk, "mc2_resume()\n");
248 mc2_update_timer_and_unlock(state); 356 mc2_update_timer_and_unlock(state);
249 local_irq_restore(flags); 357 local_irq_restore(flags);
250 } else { 358 } else {
@@ -263,34 +371,36 @@ static long mc2_complete_job(void)
263 struct mc2_cpu_state *state = local_cpu_state(); 371 struct mc2_cpu_state *state = local_cpu_state();
264 struct reservation_environment *env = &(state->sup_env.env); 372 struct reservation_environment *env = &(state->sup_env.env);
265 struct mc2_task_state *tinfo = get_mc2_state(current); 373 struct mc2_task_state *tinfo = get_mc2_state(current);
374 struct reservation *res;
266 375
376 res = sup_find_by_id(&state->sup_env, tinfo->mc2_param.res_id);
377 if (!res)
378 ; // find in global env
267 379
268 TRACE_CUR("mc2_complete_job at %llu (deadline: %llu)\n", litmus_clock(), 380 TRACE_CUR("mc2_complete_job at %llu (deadline: %llu) (cur->budget: %llu)\n", litmus_clock(),
269 get_deadline(current)); 381 get_deadline(current), res->cur_budget);
270 382
271 tsk_rt(current)->completed = 1; 383 tsk_rt(current)->completed = 1;
272 384
273 if (tsk_rt(current)->sporadic_release) { 385 if (tsk_rt(current)->sporadic_release) {
274 env->time_zero = tsk_rt(current)->sporadic_release_time; 386 env->time_zero = tsk_rt(current)->sporadic_release_time;
275 387 res->next_replenishment = tsk_rt(current)->sporadic_release_time;
388 res->cur_budget = 0;
389 res->env->change_state(res->env, res, RESERVATION_DEPLETED);
390
276 if (tinfo->mc2_param.crit == CRIT_LEVEL_A) { 391 if (tinfo->mc2_param.crit == CRIT_LEVEL_A) {
277 struct reservation *res;
278 struct table_driven_reservation *tdres; 392 struct table_driven_reservation *tdres;
279 393
280 sup_update_time(&state->sup_env, litmus_clock()); 394 //sup_update_time(&state->sup_env, litmus_clock());
281 res = sup_find_by_id(&state->sup_env, tinfo->mc2_param.res_id); 395 //res = sup_find_by_id(&state->sup_env, tinfo->mc2_param.res_id);
282 tdres = container_of(res, struct table_driven_reservation, res); 396 tdres = container_of(res, struct table_driven_reservation, res);
283 tdres->next_interval = 0; 397 tdres->next_interval = 0;
284 tdres->major_cycle_start = tsk_rt(current)->sporadic_release_time; 398 tdres->major_cycle_start = tsk_rt(current)->sporadic_release_time;
285 res->next_replenishment = tsk_rt(current)->sporadic_release_time; 399 res->next_replenishment += tdres->intervals[0].start;
286 res->next_replenishment += tdres->intervals[0].start;
287 res->env->change_state(res->env, res, RESERVATION_DEPLETED);
288
289 TRACE_CUR("CHANGE NEXT_REP = %llu\n NEXT_UPDATE = %llu\n", res->next_replenishment, state->sup_env.next_scheduler_update);
290 } 400 }
291 401 TRACE_CUR("CHANGE NEXT_REP = %llu\n NEXT_UPDATE = %llu\n", res->next_replenishment, state->sup_env.next_scheduler_update);
292 } 402 }
293 403
294 prepare_for_next_period(current); 404 prepare_for_next_period(current);
295 next_release = ns_to_ktime(get_release(current)); 405 next_release = ns_to_ktime(get_release(current));
296 preempt_disable(); 406 preempt_disable();
@@ -385,6 +495,7 @@ static void mc2_task_new(struct task_struct *tsk, int on_runqueue,
385 /* Assumption: litmus_clock() is synchronized across cores 495 /* Assumption: litmus_clock() is synchronized across cores
386 * [see comment in pres_task_resume()] */ 496 * [see comment in pres_task_resume()] */
387 sup_update_time(&state->sup_env, litmus_clock()); 497 sup_update_time(&state->sup_env, litmus_clock());
498 mc2_update_ghost_state(state);
388 task_arrives(tsk); 499 task_arrives(tsk);
389 /* NOTE: drops state->lock */ 500 /* NOTE: drops state->lock */
390 TRACE("mc2_new()\n"); 501 TRACE("mc2_new()\n");
@@ -456,18 +567,26 @@ static void mc2_task_exit(struct task_struct *tsk)
456 unsigned long flags; 567 unsigned long flags;
457 struct mc2_task_state* tinfo = get_mc2_state(tsk); 568 struct mc2_task_state* tinfo = get_mc2_state(tsk);
458 struct mc2_cpu_state *state = cpu_state_for(tinfo->cpu); 569 struct mc2_cpu_state *state = cpu_state_for(tinfo->cpu);
570 enum crit_level lv = tinfo->mc2_param.crit;
571 struct crit_entry* ce;
459 572
460 raw_spin_lock_irqsave(&state->lock, flags); 573 raw_spin_lock_irqsave(&state->lock, flags);
461 574
462 if (state->scheduled == tsk) 575 if (state->scheduled == tsk)
463 state->scheduled = NULL; 576 state->scheduled = NULL;
464 577
578 ce = &state->crit_entries[lv];
579 if (ce->running == tsk)
580 ce->running = NULL;
581
465 /* remove from queues */ 582 /* remove from queues */
466 if (is_running(tsk)) { 583 if (is_running(tsk)) {
467 /* Assumption: litmus_clock() is synchronized across cores 584 /* Assumption: litmus_clock() is synchronized across cores
468 * [see comment in pres_task_resume()] */ 585 * [see comment in pres_task_resume()] */
469 sup_update_time(&state->sup_env, litmus_clock()); 586 sup_update_time(&state->sup_env, litmus_clock());
587 mc2_update_ghost_state(state);
470 task_departs(tsk, 0); 588 task_departs(tsk, 0);
589
471 /* NOTE: drops state->lock */ 590 /* NOTE: drops state->lock */
472 TRACE("mc2_exit()\n"); 591 TRACE("mc2_exit()\n");
473 mc2_update_timer_and_unlock(state); 592 mc2_update_timer_and_unlock(state);
@@ -729,7 +848,7 @@ static void mc2_setup_domain_proc(void)
729 848
730static long mc2_activate_plugin(void) 849static long mc2_activate_plugin(void)
731{ 850{
732 int cpu; 851 int cpu, lv;
733 struct mc2_cpu_state *state; 852 struct mc2_cpu_state *state;
734 853
735 for_each_online_cpu(cpu) { 854 for_each_online_cpu(cpu) {
@@ -740,7 +859,13 @@ static long mc2_activate_plugin(void)
740 raw_spin_lock_init(&state->lock); 859 raw_spin_lock_init(&state->lock);
741 state->cpu = cpu; 860 state->cpu = cpu;
742 state->scheduled = NULL; 861 state->scheduled = NULL;
743 862 for (lv = 0; lv < NUM_CRIT_LEVELS; lv++) {
863 struct crit_entry *ce = &state->crit_entries[lv];
864 ce->level = lv;
865 ce->running = NULL;
866 hrtimer_init(&ce->ghost_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
867 ce->ghost_timer.function = on_ghost_timer;
868 }
744 sup_init(&state->sup_env); 869 sup_init(&state->sup_env);
745 870
746 hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); 871 hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);