aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-08-20 17:28:55 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2012-08-20 17:28:55 -0400
commit8d687fc34b89fa1150a82f71fed35e21490df42b (patch)
tree06357623548599034573849279b4955cd1002964
parent9a19f35c9c287cb8abd5bcf276ae8d1a3e876907 (diff)
EDF priority tie-breaks by lateness.
Instead of tie-breaking by PID (which is a static priority tie-break), we can tie-break by lateness of a prior job. That is, if two jobs, J_{1,i} and J_{2,j} of tasks T_1 and T_2, respectively, have equal deadlines, we favor the job of the task that had the worst lateness for jobs J_{1,i-1} and J_{2,j-1}. In case of lateness ties, we fall back to PID comparisons. This later case will likely only kick in for initial jobs, when lateness of "prior" jobs is assumed to be 0. Note: Unlike tardiness, lateness may be less than zero. This occurs when a job finishes before its deadline.
-rw-r--r--include/litmus/litmus.h2
-rw-r--r--include/litmus/rt_param.h6
-rw-r--r--litmus/edf_common.c24
-rw-r--r--litmus/jobs.c8
4 files changed, 32 insertions, 8 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index 338245abd6ed..807b7888695a 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -63,7 +63,7 @@ void litmus_exit_task(struct task_struct *tsk);
63#define get_exec_time(t) (tsk_rt(t)->job_params.exec_time) 63#define get_exec_time(t) (tsk_rt(t)->job_params.exec_time)
64#define get_deadline(t) (tsk_rt(t)->job_params.deadline) 64#define get_deadline(t) (tsk_rt(t)->job_params.deadline)
65#define get_release(t) (tsk_rt(t)->job_params.release) 65#define get_release(t) (tsk_rt(t)->job_params.release)
66 66#define get_lateness(t) (tsk_rt(t)->job_params.lateness)
67 67
68#define is_hrt(t) \ 68#define is_hrt(t) \
69 (tsk_rt(t)->task_params.cls == RT_CLASS_HARD) 69 (tsk_rt(t)->task_params.cls == RT_CLASS_HARD)
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index 89ac0dda7d3d..fac939dbd33a 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -110,6 +110,12 @@ struct rt_job {
110 /* How much service has this job received so far? */ 110 /* How much service has this job received so far? */
111 lt_t exec_time; 111 lt_t exec_time;
112 112
113 /* By how much did the prior job miss its deadline by?
114 * Value differs from tardiness in that lateness may
115 * be negative (when job finishes before its deadline).
116 */
117 long long lateness;
118
113 /* Which job is this. This is used to let user space 119 /* Which job is this. This is used to let user space
114 * specify which job to wait for, which is important if jobs 120 * specify which job to wait for, which is important if jobs
115 * overrun. If we just call sys_sleep_next_period() then we 121 * overrun. If we just call sys_sleep_next_period() then we
diff --git a/litmus/edf_common.c b/litmus/edf_common.c
index 668737f0fbf9..54285aaa0405 100644
--- a/litmus/edf_common.c
+++ b/litmus/edf_common.c
@@ -78,17 +78,27 @@ int edf_higher_prio(struct task_struct* first,
78 else if (get_deadline(first_task) == get_deadline(second_task)) { 78 else if (get_deadline(first_task) == get_deadline(second_task)) {
79 /* Need to tie break */ 79 /* Need to tie break */
80 80
81 /* Tie break by pid */ 81 /* Tie break by lateness. Jobs with greater lateness get
82 if (first_task->pid < second_task->pid) { 82 * priority. This should spread tardiness across all tasks,
83 * especially in task sets where all tasks have the same
84 * period and relative deadlines.
85 */
86 if (get_lateness(first_task) > get_lateness(second_task)) {
83 return 1; 87 return 1;
84 } 88 }
85 else if (first_task->pid == second_task->pid) { 89 else if(get_lateness(first_task) == get_lateness(second_task)) {
86 /* If the PIDs are the same then the task with the 90 /* Tie break by pid */
87 * inherited priority wins. 91 if (first_task->pid < second_task->pid) {
88 */
89 if (!second_task->rt_param.inh_task) {
90 return 1; 92 return 1;
91 } 93 }
94 else if (first_task->pid == second_task->pid) {
95 /* If the PIDs are the same then the task with the
96 * inherited priority wins.
97 */
98 if (!second_task->rt_param.inh_task) {
99 return 1;
100 }
101 }
92 } 102 }
93 } 103 }
94 return 0; /* fall-through. prio(second_task) > prio(first_task) */ 104 return 0; /* fall-through. prio(second_task) > prio(first_task) */
diff --git a/litmus/jobs.c b/litmus/jobs.c
index bc8246572e54..fb093c03d53d 100644
--- a/litmus/jobs.c
+++ b/litmus/jobs.c
@@ -23,6 +23,14 @@ static inline void setup_release(struct task_struct *t, lt_t release)
23void prepare_for_next_period(struct task_struct *t) 23void prepare_for_next_period(struct task_struct *t)
24{ 24{
25 BUG_ON(!t); 25 BUG_ON(!t);
26
27 /* Record lateness before we set up the next job's
28 * release and deadline. Lateness may be negative.
29 */
30 t->rt_param.job_params.lateness =
31 (long long)litmus_clock() -
32 (long long)t->rt_param.job_params.deadline;
33
26 setup_release(t, get_release(t) + get_rt_period(t)); 34 setup_release(t, get_release(t) + get_rt_period(t));
27} 35}
28 36