diff options
| author | Namhoon Kim <namhoonk@cs.unc.edu> | 2015-01-21 15:54:21 -0500 |
|---|---|---|
| committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2015-01-21 15:54:21 -0500 |
| commit | 16a64e75ff5d1deeeb8adaaa0d11b1d6fe236bbe (patch) | |
| tree | 02c8bfade500a847e039ea340c1583d40d1e9fd6 | |
| parent | 6583dcfbda43e420921e3adf7f2e46dc719e8d26 (diff) | |
Initial lv C impl.wip-mc2
| -rw-r--r-- | include/litmus/reservation.h | 55 | ||||
| -rw-r--r-- | litmus/polling_reservations.c | 1 | ||||
| -rw-r--r-- | litmus/reservation.c | 303 | ||||
| -rw-r--r-- | litmus/sched_mc2.c | 453 |
4 files changed, 739 insertions, 73 deletions
diff --git a/include/litmus/reservation.h b/include/litmus/reservation.h index 4eecd3f088e8..0345d3482916 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 | ||
| 131 | void reservation_init(struct reservation *res); | 134 | void reservation_init(struct reservation *res); |
| @@ -191,4 +194,56 @@ struct task_struct* sup_dispatch(struct sup_reservation_environment* sup_env); | |||
| 191 | struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env, | 194 | struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env, |
| 192 | unsigned int id); | 195 | unsigned int id); |
| 193 | 196 | ||
| 197 | #define ENV_RESCHEDULE_NOW (0) | ||
| 198 | #define ENV_NO_SCHEDULER_UPDATE (ULLONG_MAX) | ||
| 199 | |||
| 200 | struct next_timer_event { | ||
| 201 | lt_t next_event; | ||
| 202 | int timer_armed_on; | ||
| 203 | struct list_head list; | ||
| 204 | }; | ||
| 205 | |||
| 206 | /* A global multiprocessor reservation environment. | ||
| 207 | */ | ||
| 208 | struct 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 | /* - ENV_RESCHEDULE_NOW means call gmp_dispatch() now | ||
| 222 | * - ENV_NO_SCHEDULER_UPDATE means nothing to do | ||
| 223 | * any other value means program a timer for the given time | ||
| 224 | */ | ||
| 225 | struct list_head next_events; | ||
| 226 | raw_spinlock_t event_lock; | ||
| 227 | bool schedule_now; | ||
| 228 | /* set to true if a call to gmp_dispatch() is imminent */ | ||
| 229 | bool will_schedule; | ||
| 230 | }; | ||
| 231 | |||
| 232 | /* Contract: | ||
| 233 | * - before calling into sup_ code, or any reservation methods, | ||
| 234 | * update the time with sup_update_time(); and | ||
| 235 | * - after calling into sup_ code, or any reservation methods, | ||
| 236 | * check next_scheduler_update and program timer or trigger | ||
| 237 | * scheduler invocation accordingly. | ||
| 238 | */ | ||
| 239 | |||
| 240 | void gmp_init(struct gmp_reservation_environment* gmp_env); | ||
| 241 | void gmp_add_new_reservation(struct gmp_reservation_environment* gmp_env, | ||
| 242 | struct reservation* new_res); | ||
| 243 | void gmp_update_time(struct gmp_reservation_environment* gmp_env, lt_t now); | ||
| 244 | struct task_struct* gmp_dispatch(struct gmp_reservation_environment* gmp_env); | ||
| 245 | |||
| 246 | struct reservation* gmp_find_by_id(struct gmp_reservation_environment* gmp_env, | ||
| 247 | unsigned int id); | ||
| 248 | |||
| 194 | #endif | 249 | #endif |
diff --git a/litmus/polling_reservations.c b/litmus/polling_reservations.c index 4c07ee74bf39..81f8e0f54ffd 100644 --- a/litmus/polling_reservations.c +++ b/litmus/polling_reservations.c | |||
| @@ -72,6 +72,7 @@ static void periodic_polling_client_departs( | |||
| 72 | /* do nothing */ | 72 | /* do nothing */ |
| 73 | break; | 73 | break; |
| 74 | } | 74 | } |
| 75 | res->scheduled_on = NO_CPU; | ||
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | static void periodic_polling_on_replenishment( | 78 | static void periodic_polling_on_replenishment( |
diff --git a/litmus/reservation.c b/litmus/reservation.c index 0e43479ff2e1..35b3b5de5d0c 100644 --- a/litmus/reservation.c +++ b/litmus/reservation.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include <linux/sched.h> | 1 | #include <linux/sched.h> |
| 2 | #include <linux/slab.h> | ||
| 2 | 3 | ||
| 3 | #include <litmus/litmus.h> | 4 | #include <litmus/litmus.h> |
| 4 | #include <litmus/reservation.h> | 5 | #include <litmus/reservation.h> |
| @@ -203,8 +204,7 @@ static void sup_charge_budget( | |||
| 203 | { | 204 | { |
| 204 | /* make sure scheduler is invoked when this reservation expires | 205 | /* make sure scheduler is invoked when this reservation expires |
| 205 | * its remaining budget */ | 206 | * its remaining budget */ |
| 206 | TRACE("requesting scheduler update for reservation %u in %llu nanoseconds\n", | 207 | //TRACE("requesting scheduler update for reservation %u in %llu nanoseconds\n", res->id, res->cur_budget); |
| 207 | res->id, res->cur_budget); | ||
| 208 | sup_scheduler_update_after(sup_env, res->cur_budget); | 208 | sup_scheduler_update_after(sup_env, res->cur_budget); |
| 209 | } | 209 | } |
| 210 | if (encountered_active) | 210 | if (encountered_active) |
| @@ -317,3 +317,302 @@ void sup_init(struct sup_reservation_environment* sup_env) | |||
| 317 | 317 | ||
| 318 | sup_env->next_scheduler_update = SUP_NO_SCHEDULER_UPDATE; | 318 | sup_env->next_scheduler_update = SUP_NO_SCHEDULER_UPDATE; |
| 319 | } | 319 | } |
| 320 | |||
| 321 | static void gmp_scheduler_update_at( | ||
| 322 | struct gmp_reservation_environment* gmp_env, | ||
| 323 | lt_t when) | ||
| 324 | { | ||
| 325 | struct next_timer_event *nevent; | ||
| 326 | struct list_head *pos; | ||
| 327 | struct next_timer_event *queued; | ||
| 328 | int found = 0; | ||
| 329 | |||
| 330 | nevent = kzalloc(sizeof(*nevent), GFP_KERNEL); | ||
| 331 | nevent->next_event = when; | ||
| 332 | nevent->timer_armed_on = NO_CPU; | ||
| 333 | |||
| 334 | list_for_each(pos, &gmp_env->next_events) { | ||
| 335 | queued = list_entry(pos, struct next_timer_event, list); | ||
| 336 | if (queued->next_event > nevent->next_event) { | ||
| 337 | list_add(&nevent->list, pos->prev); | ||
| 338 | found = 1; | ||
| 339 | TRACE("NEXT_EVENT ADDED after %llu\n", queued->next_event); | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | if (!found) { | ||
| 345 | list_add_tail(&nevent->list, &gmp_env->next_events); | ||
| 346 | TRACE("NEXT_EVENT ADDED at [0]\n"); | ||
| 347 | } | ||
| 348 | |||
| 349 | TRACE("GMP_SCHEDULER_UPDATE_AT update_time: %llu\n", nevent->next_event); | ||
| 350 | } | ||
| 351 | |||
| 352 | static void gmp_scheduler_update_after( | ||
| 353 | struct gmp_reservation_environment* gmp_env, | ||
| 354 | lt_t timeout) | ||
| 355 | { | ||
| 356 | gmp_scheduler_update_at(gmp_env, gmp_env->env.current_time + timeout); | ||
| 357 | } | ||
| 358 | |||
| 359 | static int _gmp_queue_depleted( | ||
| 360 | struct gmp_reservation_environment* gmp_env, | ||
| 361 | struct reservation *res) | ||
| 362 | { | ||
| 363 | struct list_head *pos; | ||
| 364 | struct reservation *queued; | ||
| 365 | int passed_earlier = 0; | ||
| 366 | |||
| 367 | list_for_each(pos, &gmp_env->depleted_reservations) { | ||
| 368 | queued = list_entry(pos, struct reservation, list); | ||
| 369 | if (queued->next_replenishment > res->next_replenishment) { | ||
| 370 | list_add(&res->list, pos->prev); | ||
| 371 | return passed_earlier; | ||
| 372 | } else | ||
| 373 | passed_earlier = 1; | ||
| 374 | } | ||
| 375 | |||
| 376 | list_add_tail(&res->list, &gmp_env->depleted_reservations); | ||
| 377 | |||
| 378 | return passed_earlier; | ||
| 379 | } | ||
| 380 | |||
| 381 | static void gmp_queue_depleted( | ||
| 382 | struct gmp_reservation_environment* gmp_env, | ||
| 383 | struct reservation *res) | ||
| 384 | { | ||
| 385 | int passed_earlier = _gmp_queue_depleted(gmp_env, res); | ||
| 386 | |||
| 387 | /* check for updated replenishment time */ | ||
| 388 | if (!passed_earlier) | ||
| 389 | gmp_scheduler_update_at(gmp_env, res->next_replenishment); | ||
| 390 | } | ||
| 391 | |||
| 392 | static int _gmp_queue_active( | ||
| 393 | struct gmp_reservation_environment* gmp_env, | ||
| 394 | struct reservation *res) | ||
| 395 | { | ||
| 396 | struct list_head *pos; | ||
| 397 | struct reservation *queued; | ||
| 398 | int passed_active = 0; | ||
| 399 | |||
| 400 | list_for_each(pos, &gmp_env->active_reservations) { | ||
| 401 | queued = list_entry(pos, struct reservation, list); | ||
| 402 | if (queued->priority > res->priority) { | ||
| 403 | list_add(&res->list, pos->prev); | ||
| 404 | return passed_active; | ||
| 405 | } else if (queued->state == RESERVATION_ACTIVE) | ||
| 406 | passed_active = 1; | ||
| 407 | } | ||
| 408 | |||
| 409 | list_add_tail(&res->list, &gmp_env->active_reservations); | ||
| 410 | return passed_active; | ||
| 411 | } | ||
| 412 | |||
| 413 | static void gmp_queue_active( | ||
| 414 | struct gmp_reservation_environment* gmp_env, | ||
| 415 | struct reservation *res) | ||
| 416 | { | ||
| 417 | int passed_active = _gmp_queue_active(gmp_env, res); | ||
| 418 | |||
| 419 | /* check for possible preemption */ | ||
| 420 | if (res->state == RESERVATION_ACTIVE && !passed_active) { | ||
| 421 | gmp_env->schedule_now = true; | ||
