aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2014-09-17 11:25:50 -0400
committerNamhoon Kim <namhoonk@cs.unc.edu>2014-11-03 21:59:45 -0500
commitf460d28c594341d8e8f78cfe92e6e0d42b2f5616 (patch)
tree0b3b3b5bdb77e7586103943afe0fc880cb7fc48c
parent33ad22dfbddcff613fd530f3721cd3e941f4614c (diff)
Reservations: fix time-tracking of table-driven reservations
Keep track of the current slot and major cycle explicitly to avoid ambiguity when the budget charging is delayed into the next major cycle due to a late interrupt or other sources of delay.
-rw-r--r--include/litmus/polling_reservations.h5
-rw-r--r--litmus/polling_reservations.c53
-rw-r--r--litmus/reservation.c2
3 files changed, 46 insertions, 14 deletions
diff --git a/include/litmus/polling_reservations.h b/include/litmus/polling_reservations.h
index fa221817ad30..66c9b1e31f20 100644
--- a/include/litmus/polling_reservations.h
+++ b/include/litmus/polling_reservations.h
@@ -24,7 +24,10 @@ struct table_driven_reservation {
24 unsigned int next_interval; 24 unsigned int next_interval;
25 unsigned int num_intervals; 25 unsigned int num_intervals;
26 struct lt_interval *intervals; 26 struct lt_interval *intervals;
27 struct lt_interval *cur_interval; 27
28 /* info about current scheduling slot */
29 struct lt_interval cur_interval;
30 lt_t major_cycle_start;
28}; 31};
29 32
30void table_driven_reservation_init(struct table_driven_reservation *tdres, 33void table_driven_reservation_init(struct table_driven_reservation *tdres,
diff --git a/litmus/polling_reservations.c b/litmus/polling_reservations.c
index 2c481b46ba39..86a32068a3a8 100644
--- a/litmus/polling_reservations.c
+++ b/litmus/polling_reservations.c
@@ -318,7 +318,8 @@ static void td_client_arrives(
318 switch (res->state) { 318 switch (res->state) {
319 case RESERVATION_INACTIVE: 319 case RESERVATION_INACTIVE:
320 /* Figure out first replenishment time. */ 320 /* Figure out first replenishment time. */
321 res->next_replenishment = td_next_major_cycle_start(tdres); 321 tdres->major_cycle_start = td_next_major_cycle_start(tdres);
322 res->next_replenishment = tdres->major_cycle_start;
322 res->next_replenishment += tdres->intervals[0].start; 323 res->next_replenishment += tdres->intervals[0].start;
323 tdres->next_interval = 0; 324 tdres->next_interval = 0;
324 325
@@ -368,11 +369,12 @@ static void td_client_departs(
368static lt_t td_time_remaining_until_end(struct table_driven_reservation *tdres) 369static lt_t td_time_remaining_until_end(struct table_driven_reservation *tdres)
369{ 370{
370 lt_t now = tdres->res.env->current_time; 371 lt_t now = tdres->res.env->current_time;
371 lt_t end = td_cur_major_cycle_start(tdres) + tdres->cur_interval->end; 372 lt_t end = tdres->cur_interval.end;
372 TRACE("td_remaining(%u): start=%llu now=%llu end=%llu\n", 373 TRACE("td_remaining(%u): start=%llu now=%llu end=%llu state=%d\n",
373 tdres->res.id, 374 tdres->res.id,
374 td_cur_major_cycle_start(tdres) + tdres->cur_interval->start, 375 tdres->cur_interval.start,
375 now, end); 376 now, end,
377 tdres->res.state);
376 if (now >= end) 378 if (now >= end)
377 return 0; 379 return 0;
378 else 380 else
@@ -385,20 +387,36 @@ static void td_replenish(
385 struct table_driven_reservation *tdres = 387 struct table_driven_reservation *tdres =
386 container_of(res, struct table_driven_reservation, res); 388 container_of(res, struct table_driven_reservation, res);
387 389
388 /* replenish budget */ 390 TRACE("td_replenish(%u): expected_replenishment=%llu\n", res->id,
389 tdres->cur_interval = tdres->intervals + tdres->next_interval; 391 res->next_replenishment);
392
393 /* figure out current interval */
394 tdres->cur_interval.start = tdres->major_cycle_start +
395 tdres->intervals[tdres->next_interval].start;
396 tdres->cur_interval.end = tdres->major_cycle_start +
397 tdres->intervals[tdres->next_interval].end;
398 TRACE("major_cycle_start=%llu => [%llu, %llu]\n",
399 tdres->major_cycle_start,
400 tdres->cur_interval.start,
401 tdres->cur_interval.end);
402
403 /* reset budget */
390 res->cur_budget = td_time_remaining_until_end(tdres); 404 res->cur_budget = td_time_remaining_until_end(tdres);
391 res->budget_consumed = 0; 405 res->budget_consumed = 0;
392 TRACE("td_replenish(%u): %s budget=%llu\n", res->id, 406 TRACE("td_replenish(%u): %s budget=%llu\n", res->id,
393 res->cur_budget ? "" : "WARNING", res->cur_budget); 407 res->cur_budget ? "" : "WARNING", res->cur_budget);
394 408
409 /* prepare next slot */
395 tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals; 410 tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals;
396 if (tdres->next_interval) 411 if (!tdres->next_interval)
397 res->next_replenishment = td_cur_major_cycle_start(tdres);
398 else
399 /* wrap to next major cycle */ 412 /* wrap to next major cycle */
400 res->next_replenishment = td_next_major_cycle_start(tdres); 413 tdres->major_cycle_start += tdres->major_cycle;
414
415 /* determine next time this reservation becomes eligible to execute */
416 res->next_replenishment = tdres->major_cycle_start;
401 res->next_replenishment += tdres->intervals[tdres->next_interval].start; 417 res->next_replenishment += tdres->intervals[tdres->next_interval].start;
418 TRACE("td_replenish(%u): next_replenishment=%llu\n", res->id,
419 res->next_replenishment);
402 420
403 421
404 switch (res->state) { 422 switch (res->state) {
@@ -433,6 +451,9 @@ static void td_drain_budget(
433 /* Table-driven scheduling: instead of tracking the budget, we compute 451 /* Table-driven scheduling: instead of tracking the budget, we compute
434 * how much time is left in this allocation interval. */ 452 * how much time is left in this allocation interval. */
435 453
454 /* sanity check: we should never try to drain from future slots */
455 BUG_ON(tdres->cur_interval.start > res->env->current_time);
456
436 switch (res->state) { 457 switch (res->state) {
437 case RESERVATION_DEPLETED: 458 case RESERVATION_DEPLETED:
438 case RESERVATION_INACTIVE: 459 case RESERVATION_INACTIVE:
@@ -447,7 +468,12 @@ static void td_drain_budget(
447 if (!res->cur_budget) { 468 if (!res->cur_budget) {
448 res->env->change_state(res->env, res, 469 res->env->change_state(res->env, res,
449 RESERVATION_DEPLETED); 470 RESERVATION_DEPLETED);
450 } /* else: stay in current state */ 471 } else {
472 /* sanity check budget calculation */
473 BUG_ON(res->env->current_time >= tdres->cur_interval.end);
474 BUG_ON(res->env->current_time < tdres->cur_interval.start);
475 }
476
451 break; 477 break;
452 } 478 }
453} 479}
@@ -515,7 +541,8 @@ void table_driven_reservation_init(
515 reservation_init(&tdres->res); 541 reservation_init(&tdres->res);
516 tdres->major_cycle = major_cycle; 542 tdres->major_cycle = major_cycle;
517 tdres->intervals = intervals; 543 tdres->intervals = intervals;
518 tdres->cur_interval = intervals; 544 tdres->cur_interval.start = 0;
545 tdres->cur_interval.end = 0;
519 tdres->num_intervals = num_intervals; 546 tdres->num_intervals = num_intervals;
520 tdres->res.ops = &td_ops; 547 tdres->res.ops = &td_ops;
521} 548}
diff --git a/litmus/reservation.c b/litmus/reservation.c
index 447fc5b1be23..f79689823be7 100644
--- a/litmus/reservation.c
+++ b/litmus/reservation.c
@@ -206,6 +206,7 @@ static void sup_charge_budget(
206 /* stop at the first ACTIVE reservation */ 206 /* stop at the first ACTIVE reservation */
207 break; 207 break;
208 } 208 }
209 TRACE("finished charging budgets\n");
209} 210}
210 211
211static void sup_replenish_budgets(struct sup_reservation_environment* sup_env) 212static void sup_replenish_budgets(struct sup_reservation_environment* sup_env)
@@ -222,6 +223,7 @@ static void sup_replenish_budgets(struct sup_reservation_environment* sup_env)
222 break; 223 break;
223 } 224 }
224 } 225 }
226 TRACE("finished replenishing budgets\n");
225 227
226 /* request a scheduler update at the next replenishment instant */ 228 /* request a scheduler update at the next replenishment instant */
227 res = list_first_entry_or_null(&sup_env->depleted_reservations, 229 res = list_first_entry_or_null(&sup_env->depleted_reservations,