aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2014-09-08 12:24:18 -0400
committerNamhoon Kim <namhoonk@cs.unc.edu>2014-11-03 21:58:52 -0500
commitaca9db004d887d28621a0fc30818d7ebf77fc9bf (patch)
treea9e7ccf3927727ed0d76afb46abd471726575b49
parentfcd5e594a26012c7457197fd111e58820bc34741 (diff)
Table-driven replenishments should depend on the current time
Make sure we don't accidentally bleed past the current reservation scheduling slot (due to jitter) by determining the remaining budget precisely when replenishing the reservation budget.
-rw-r--r--litmus/polling_reservations.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/litmus/polling_reservations.c b/litmus/polling_reservations.c
index e6c57f592780..5c9b1832d2d9 100644
--- a/litmus/polling_reservations.c
+++ b/litmus/polling_reservations.c
@@ -361,11 +361,6 @@ static void td_client_departs(
361 } 361 }
362} 362}
363 363
364static lt_t td_interval_length(struct lt_interval *ival)
365{
366 return ival->end - ival->start;
367}
368
369static lt_t td_time_remaining_until_end(struct table_driven_reservation *tdres) 364static lt_t td_time_remaining_until_end(struct table_driven_reservation *tdres)
370{ 365{
371 lt_t now = tdres->res.env->current_time; 366 lt_t now = tdres->res.env->current_time;
@@ -388,7 +383,9 @@ static void td_replenish(
388 383
389 /* replenish budget */ 384 /* replenish budget */
390 tdres->cur_interval = tdres->intervals + tdres->next_interval; 385 tdres->cur_interval = tdres->intervals + tdres->next_interval;
391 res->cur_budget = td_interval_length(tdres->cur_interval); 386 res->cur_budget = td_time_remaining_until_end(tdres);
387 TRACE("td_replenish(%u): %s budget=%llu\n", res->id,
388 res->cur_budget ? "" : "WARNING", res->cur_budget);
392 389
393 tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals; 390 tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals;
394 if (tdres->next_interval) 391 if (tdres->next_interval)
@@ -447,10 +444,44 @@ static void td_drain_budget(
447 } 444 }
448} 445}
449 446
447static struct task_struct* td_dispatch_client(
448 struct reservation *res,
449 lt_t *for_at_most)
450{
451 struct task_struct *t;
452 struct table_driven_reservation *tdres =
453 container_of(res, struct table_driven_reservation, res);
450 454
455 /* usual logic for selecting a client */
456 t = default_dispatch_client(res, for_at_most);
457
458 TRACE_TASK(t, "td_dispatch_client(%u): selected, budget=%llu\n",
459 res->id, res->cur_budget);
460
461 /* check how much budget we have left in this time slot */
462 res->cur_budget = td_time_remaining_until_end(tdres);
463
464 TRACE_TASK(t, "td_dispatch_client(%u): updated to budget=%llu next=%d\n",
465 res->id, res->cur_budget, tdres->next_interval);
466
467 if (unlikely(!res->cur_budget)) {
468 /* Unlikely case: if we ran out of budget, the user configured
469 * a broken scheduling table (overlapping table slots).
470 * Not much we can do about this, but we can't dispatch a job
471 * now without causing overload. So let's register this reservation
472 * as depleted and wait for the next allocation. */
473 TRACE("td_dispatch_client(%u): budget unexpectedly depleted "
474 "(check scheduling table for unintended overlap)\n",
475 res->id);
476 res->env->change_state(res->env, res,
477 RESERVATION_DEPLETED);
478 return NULL;
479 } else
480 return t;
481}
451 482
452static struct reservation_ops td_ops = { 483static struct reservation_ops td_ops = {
453 .dispatch_client = default_dispatch_client, 484 .dispatch_client = td_dispatch_client,
454 .client_arrives = td_client_arrives, 485 .client_arrives = td_client_arrives,
455 .client_departs = td_client_departs, 486 .client_departs = td_client_departs,
456 .replenish = td_replenish, 487 .replenish = td_replenish,