diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-08-20 17:28:55 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-08-20 17:28:55 -0400 |
commit | 8d687fc34b89fa1150a82f71fed35e21490df42b (patch) | |
tree | 06357623548599034573849279b4955cd1002964 | |
parent | 9a19f35c9c287cb8abd5bcf276ae8d1a3e876907 (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.h | 2 | ||||
-rw-r--r-- | include/litmus/rt_param.h | 6 | ||||
-rw-r--r-- | litmus/edf_common.c | 24 | ||||
-rw-r--r-- | litmus/jobs.c | 8 |
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) | |||
23 | void prepare_for_next_period(struct task_struct *t) | 23 | void 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 | ||