summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorleochanj105 <43393724+leochanj105@users.noreply.github.com>2021-01-21 11:20:28 -0500
committerGitHub <noreply@github.com>2021-01-21 11:20:28 -0500
commite7425c838eded1f89c39550fae06cda63d8a0e16 (patch)
treef4b588502ea9a2ed70add08b2da5ea5c46048419
parent3713d99f4b6a1fe6ec3bdf75ee67bf378ab325b0 (diff)
GSN-EDF: Make sleep_next_period() a no-op if already completed due to budget exhaustion
Vanilla LITMUS-RT (without reservations) does not distinguish between a period which voluntarily ends (via the complete_job() userspace call) and a period which is forced to complete due to budget exhaustion. This results in inconsistent behavior of the userspace API when budget enforcement is enabled. Say a task's budget is set slightly below its actual execution time. In this case, the task is suspended during its first job by budget enforcement. When the second period starts, the task immediately completes it's work and calls sleep_next_period(). From the perspective of the task, it should enter its second job after calling sleep_next_period(). From the perspective of LITMUS-RT, the task is already in its second period and will suspend the task until its _third_ period. This patch fixes that bug for GSN-EDF by only suspending the task on sleep_next_period() if the previous period was not force-completed by budget enforcement.
-rw-r--r--litmus/sched_gsn_edf.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index 76095cdb09a0..d4013aed6196 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -125,6 +125,9 @@ static struct bheap gsnedf_cpu_heap;
125static rt_domain_t gsnedf; 125static rt_domain_t gsnedf;
126#define gsnedf_lock (gsnedf.ready_lock) 126#define gsnedf_lock (gsnedf.ready_lock)
127 127
128/* use the untouched rt_params->plugin_state as the forced completion bit */
129#define get_forced_completion(t) t->rt_param.plugin_state
130#define set_forced_completion(t, forced) t->rt_param.plugin_state = forced
128 131
129/* Uncomment this if you want to see all scheduling decisions in the 132/* Uncomment this if you want to see all scheduling decisions in the
130 * TRACE() log. 133 * TRACE() log.
@@ -474,8 +477,27 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
474 * this. Don't do a job completion if we block (can't have timers running 477 * this. Don't do a job completion if we block (can't have timers running
475 * for blocked jobs). 478 * for blocked jobs).
476 */ 479 */
477 if (!np && (out_of_time || sleep)) 480 if (!np && (out_of_time || sleep)) {
478 curr_job_completion(!sleep); 481 if(sleep && get_forced_completion(entry->scheduled)) {
482 /* if we have a forced completion just before, simply
483 * set the completed flag to 0
484 */
485 TRACE_TASK(entry->scheduled,
486 "Task should complete normally, "
487 "but skipped due to a previous forced completion "
488 "caused by budget overrun\n");
489 /* used current as in curr_job_completion */
490 tsk_rt(current)->completed = 0;
491 } else {
492 /* if we have a forced completion now or a normal
493 * completion without previous forced completion,
494 * simply call curr_job_completion
495 */
496 curr_job_completion(!sleep);
497 }
498 /* record whether there is a forced completion */
499 set_forced_completion(entry->scheduled, out_of_time);
500 }
479 501
480 /* Link pending task if we became unlinked. 502 /* Link pending task if we became unlinked.
481 */ 503 */