aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2014-09-08 12:24:18 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2014-09-08 12:24:18 -0400
commite18fc708a32b2ee6b48e648cd2ac767eb76be5e5 (patch)
tree86a5383d0c4d2f22c29d96a9c0936f42fbf99ba5
parent642d997fc6d6500e14f3c2fa72e481800d687cd1 (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,