aboutsummaryrefslogtreecommitdiffstats
path: root/litmus
diff options
context:
space:
mode:
Diffstat (limited to 'litmus')
-rw-r--r--litmus/budget.c16
-rw-r--r--litmus/jobs.c2
-rw-r--r--litmus/litmus.c10
-rw-r--r--litmus/sched_cedf.c47
-rw-r--r--litmus/sched_gsn_edf.c54
-rw-r--r--litmus/sched_pfp.c40
-rw-r--r--litmus/sched_psn_edf.c41
7 files changed, 148 insertions, 62 deletions
diff --git a/litmus/budget.c b/litmus/budget.c
index f7712be29adb..518174a37a3b 100644
--- a/litmus/budget.c
+++ b/litmus/budget.c
@@ -1,11 +1,13 @@
1#include <linux/sched.h> 1#include <linux/sched.h>
2#include <linux/percpu.h> 2#include <linux/percpu.h>
3#include <linux/hrtimer.h> 3#include <linux/hrtimer.h>
4#include <linux/signal.h>
4 5
5#include <litmus/litmus.h> 6#include <litmus/litmus.h>
6#include <litmus/preempt.h> 7#include <litmus/preempt.h>
7 8
8#include <litmus/budget.h> 9#include <litmus/budget.h>
10#include <litmus/signal.h>
9 11
10struct enforcement_timer { 12struct enforcement_timer {
11 /* The enforcement timer is used to accurately police 13 /* The enforcement timer is used to accurately police
@@ -64,7 +66,7 @@ static void arm_enforcement_timer(struct enforcement_timer* et,
64 66
65 /* Calling this when there is no budget left for the task 67 /* Calling this when there is no budget left for the task
66 * makes no sense, unless the task is non-preemptive. */ 68 * makes no sense, unless the task is non-preemptive. */
67 BUG_ON(budget_exhausted(t) && (!is_np(t))); 69 BUG_ON(budget_exhausted(t) && !is_np(t));
68 70
69 /* __hrtimer_start_range_ns() cancels the timer 71 /* __hrtimer_start_range_ns() cancels the timer
70 * anyway, so we don't have to check whether it is still armed */ 72 * anyway, so we don't have to check whether it is still armed */
@@ -86,7 +88,7 @@ void update_enforcement_timer(struct task_struct* t)
86{ 88{
87 struct enforcement_timer* et = &__get_cpu_var(budget_timer); 89 struct enforcement_timer* et = &__get_cpu_var(budget_timer);
88 90
89 if (t && budget_precisely_enforced(t)) { 91 if (t && budget_precisely_tracked(t) && !sigbudget_sent(t)) {
90 /* Make sure we call into the scheduler when this budget 92 /* Make sure we call into the scheduler when this budget
91 * expires. */ 93 * expires. */
92 arm_enforcement_timer(et, t); 94 arm_enforcement_timer(et, t);
@@ -96,6 +98,16 @@ void update_enforcement_timer(struct task_struct* t)
96 } 98 }
97} 99}
98 100
101void send_sigbudget(struct task_struct* t)
102{
103 if (!test_and_set_bit(RT_JOB_SIG_BUDGET_SENT, &tsk_rt(t)->job_params.flags)) {
104 /* signal has not yet been sent and we are responsible for sending
105 * since we just set the sent-bit when it was previously 0. */
106
107 TRACE_TASK(t, "SIG_BUDGET being sent!\n");
108 send_sig(SIG_BUDGET, t, 1); /* '1' denotes signal sent from kernel */
109 }
110}
99 111
100static int __init init_budget_enforcement(void) 112static int __init init_budget_enforcement(void)
101{ 113{
diff --git a/litmus/jobs.c b/litmus/jobs.c
index bc8246572e54..4981665a37bf 100644
--- a/litmus/jobs.c
+++ b/litmus/jobs.c
@@ -13,6 +13,8 @@ static inline void setup_release(struct task_struct *t, lt_t release)
13 t->rt_param.job_params.deadline = release + get_rt_relative_deadline(t); 13 t->rt_param.job_params.deadline = release + get_rt_relative_deadline(t);
14 t->rt_param.job_params.exec_time = 0; 14 t->rt_param.job_params.exec_time = 0;
15 15
16 clear_bit(RT_JOB_SIG_BUDGET_SENT, &t->rt_param.job_params.flags);
17
16 /* update job sequence number */ 18 /* update job sequence number */
17 t->rt_param.job_params.job_no++; 19 t->rt_param.job_params.job_no++;
18 20
diff --git a/litmus/litmus.c b/litmus/litmus.c
index 81384327e850..3526749852aa 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -136,6 +136,16 @@ asmlinkage long sys_set_rt_task_param(pid_t pid, struct rt_task __user * param)
136 pid, tp.budget_policy); 136 pid, tp.budget_policy);
137 goto out_unlock; 137 goto out_unlock;
138 } 138 }
139 if (tp.budget_signal_policy != NO_SIGNALS &&
140 tp.budget_signal_policy != QUANTUM_SIGNALS &&
141 tp.budget_signal_policy != PRECISE_SIGNALS)
142 {
143 printk(KERN_INFO "litmus: real-time task %d rejected "
144 "because unsupported budget signalling policy "
145 "specified (%d)\n",
146 pid, tp.budget_signal_policy);
147 goto out_unlock;
148 }
139 149
140 target->rt_param.task_params = tp; 150 target->rt_param.task_params = tp;
141 151
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c
index b0c16e34d2c5..208f067934fc 100644
--- a/litmus/sched_cedf.c
+++ b/litmus/sched_cedf.c
@@ -371,21 +371,29 @@ static noinline void job_completion(struct task_struct *t, int forced)
371 */ 371 */
372static void cedf_tick(struct task_struct* t) 372static void cedf_tick(struct task_struct* t)
373{ 373{
374 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) { 374 if (is_realtime(t) && budget_exhausted(t))
375 if (!is_np(t)) { 375 {
376 /* np tasks will be preempted when they become 376 if (budget_signalled(t) && !sigbudget_sent(t)) {
377 * preemptable again 377 /* signal exhaustion */
378 */ 378 send_sigbudget(t);
379 litmus_reschedule_local(); 379 }
380 set_will_schedule(); 380
381 TRACE("cedf_scheduler_tick: " 381 if (budget_enforced(t)) {
382 "%d is preemptable " 382 if (!is_np(t)) {
383 " => FORCE_RESCHED\n", t->pid); 383 /* np tasks will be preempted when they become
384 } else if (is_user_np(t)) { 384 * preemptable again
385 TRACE("cedf_scheduler_tick: " 385 */
386 "%d is non-preemptable, " 386 litmus_reschedule_local();
387 "preemption delayed.\n", t->pid); 387 set_will_schedule();
388 request_exit_np(t); 388 TRACE("cedf_scheduler_tick: "
389 "%d is preemptable "
390 " => FORCE_RESCHED\n", t->pid);
391 } else if (is_user_np(t)) {
392 TRACE("cedf_scheduler_tick: "
393 "%d is non-preemptable, "
394 "preemption delayed.\n", t->pid);
395 request_exit_np(t);
396 }
389 } 397 }
390 } 398 }
391} 399}
@@ -415,7 +423,7 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
415{ 423{
416 cpu_entry_t* entry = &__get_cpu_var(cedf_cpu_entries); 424 cpu_entry_t* entry = &__get_cpu_var(cedf_cpu_entries);
417 cedf_domain_t *cluster = entry->cluster; 425 cedf_domain_t *cluster = entry->cluster;
418 int out_of_time, sleep, preempt, np, exists, blocks; 426 int out_of_time, signal_budget, sleep, preempt, np, exists, blocks;
419 struct task_struct* next = NULL; 427 struct task_struct* next = NULL;
420 428
421#ifdef CONFIG_RELEASE_MASTER 429#ifdef CONFIG_RELEASE_MASTER
@@ -442,6 +450,10 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
442 out_of_time = exists && 450 out_of_time = exists &&
443 budget_enforced(entry->scheduled) && 451 budget_enforced(entry->scheduled) &&
444 budget_exhausted(entry->scheduled); 452 budget_exhausted(entry->scheduled);
453 signal_budget = exists &&
454 budget_signalled(entry->scheduled) &&
455 budget_exhausted(entry->scheduled) &&
456 !sigbudget_sent(entry->scheduled);
445 np = exists && is_np(entry->scheduled); 457 np = exists && is_np(entry->scheduled);
446 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP; 458 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP;
447 preempt = entry->scheduled != entry->linked; 459 preempt = entry->scheduled != entry->linked;
@@ -460,6 +472,9 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
460 TRACE_TASK(prev, "will be preempted by %s/%d\n", 472 TRACE_TASK(prev, "will be preempted by %s/%d\n",
461 entry->linked->comm, entry->linked->pid); 473 entry->linked->comm, entry->linked->pid);
462 474
475 /* Send the signal that the budget has been exhausted */
476 if (signal_budget)
477 send_sigbudget(entry->scheduled);
463 478
464 /* If a task blocks we have no choice but to reschedule. 479 /* If a task blocks we have no choice but to reschedule.
465 */ 480 */
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index c3344b9d288f..c1f25b56e51e 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -362,20 +362,28 @@ static noinline void job_completion(struct task_struct *t, int forced)
362 */ 362 */
363static void gsnedf_tick(struct task_struct* t) 363static void gsnedf_tick(struct task_struct* t)
364{ 364{
365 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) { 365 if (is_realtime(t) && budget_exhausted(t))
366 if (!is_np(t)) { 366 {
367 /* np tasks will be preempted when they become 367 if (budget_signalled(t) && !sigbudget_sent(t)) {
368 * preemptable again 368 /* signal exhaustion */
369 */ 369 send_sigbudget(t);
370 litmus_reschedule_local(); 370 }
371 TRACE("gsnedf_scheduler_tick: " 371
372 "%d is preemptable " 372 if (budget_enforced(t)) {
373 " => FORCE_RESCHED\n", t->pid); 373 if (!is_np(t)) {
374 } else if (is_user_np(t)) { 374 /* np tasks will be preempted when they become
375 TRACE("gsnedf_scheduler_tick: " 375 * preemptable again
376 "%d is non-preemptable, " 376 */
377 "preemption delayed.\n", t->pid); 377 litmus_reschedule_local();
378 request_exit_np(t); 378 TRACE("gsnedf_scheduler_tick: "
379 "%d is preemptable "
380 " => FORCE_RESCHED\n", t->pid);
381 } else if (is_user_np(t)) {
382 TRACE("gsnedf_scheduler_tick: "
383 "%d is non-preemptable, "
384 "preemption delayed.\n", t->pid);
385 request_exit_np(t);
386 }
379 } 387 }
380 } 388 }
381} 389}
@@ -404,7 +412,7 @@ static void gsnedf_tick(struct task_struct* t)
404static struct task_struct* gsnedf_schedule(struct task_struct * prev) 412static struct task_struct* gsnedf_schedule(struct task_struct * prev)
405{ 413{
406 cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); 414 cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries);
407 int out_of_time, sleep, preempt, np, exists, blocks; 415 int out_of_time, signal_budget, sleep, preempt, np, exists, blocks;
408 struct task_struct* next = NULL; 416 struct task_struct* next = NULL;
409 417
410#ifdef CONFIG_RELEASE_MASTER 418#ifdef CONFIG_RELEASE_MASTER
@@ -427,8 +435,13 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
427 /* (0) Determine state */ 435 /* (0) Determine state */
428 exists = entry->scheduled != NULL; 436 exists = entry->scheduled != NULL;
429 blocks = exists && !is_running(entry->scheduled); 437 blocks = exists && !is_running(entry->scheduled);
430 out_of_time = exists && budget_enforced(entry->scheduled) 438 out_of_time = exists &&
431 && budget_exhausted(entry->scheduled); 439 budget_enforced(entry->scheduled) &&
440 budget_exhausted(entry->scheduled);
441 signal_budget = exists &&
442 budget_signalled(entry->scheduled) &&
443 budget_exhausted(entry->scheduled) &&
444 !sigbudget_sent(entry->scheduled);
432 np = exists && is_np(entry->scheduled); 445 np = exists && is_np(entry->scheduled);
433 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP; 446 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP;
434 preempt = entry->scheduled != entry->linked; 447 preempt = entry->scheduled != entry->linked;
@@ -439,14 +452,17 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
439 452
440 if (exists) 453 if (exists)
441 TRACE_TASK(prev, 454 TRACE_TASK(prev,
442 "blocks:%d out_of_time:%d np:%d sleep:%d preempt:%d " 455 "blocks:%d out_of_time:%d signal_budget: %d np:%d sleep:%d preempt:%d "
443 "state:%d sig:%d\n", 456 "state:%d sig:%d\n",
444 blocks, out_of_time, np, sleep, preempt, 457 blocks, out_of_time, signal_budget, np, sleep, preempt,
445 prev->state, signal_pending(prev)); 458 prev->state, signal_pending(prev));
446 if (entry->linked && preempt) 459 if (entry->linked && preempt)
447 TRACE_TASK(prev, "will be preempted by %s/%d\n", 460 TRACE_TASK(prev, "will be preempted by %s/%d\n",
448 entry->linked->comm, entry->linked->pid); 461 entry->linked->comm, entry->linked->pid);
449 462
463 /* Send the signal that the budget has been exhausted */
464 if (signal_budget)
465 send_sigbudget(entry->scheduled);
450 466
451 /* If a task blocks we have no choice but to reschedule. 467 /* If a task blocks we have no choice but to reschedule.
452 */ 468 */
diff --git a/litmus/sched_pfp.c b/litmus/sched_pfp.c
index 62be699629b1..6129eb94d3ea 100644
--- a/litmus/sched_pfp.c
+++ b/litmus/sched_pfp.c
@@ -135,17 +135,25 @@ static void pfp_tick(struct task_struct *t)
135 */ 135 */
136 BUG_ON(is_realtime(t) && t != pfp->scheduled); 136 BUG_ON(is_realtime(t) && t != pfp->scheduled);
137 137
138 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) { 138 if (is_realtime(t) && budget_exhausted(t))
139 if (!is_np(t)) { 139 {
140 litmus_reschedule_local(); 140 if (budget_signalled(t) && !sigbudget_sent(t)) {
141 TRACE("pfp_scheduler_tick: " 141 /* signal exhaustion */
142 "%d is preemptable " 142 send_sigbudget(t);
143 " => FORCE_RESCHED\n", t->pid); 143 }
144 } else if (is_user_np(t)) { 144
145 TRACE("pfp_scheduler_tick: " 145 if (budget_enforced(t)) {
146 "%d is non-preemptable, " 146 if (!is_np(t)) {
147 "preemption delayed.\n", t->pid); 147 litmus_reschedule_local();
148 request_exit_np(t); 148 TRACE("pfp_scheduler_tick: "
149 "%d is preemptable "
150 " => FORCE_RESCHED\n", t->pid);
151 } else if (is_user_np(t)) {
152 TRACE("pfp_scheduler_tick: "
153 "%d is non-preemptable, "
154 "preemption delayed.\n", t->pid);
155 request_exit_np(t);
156 }
149 } 157 }
150 } 158 }
151} 159}
@@ -155,7 +163,7 @@ static struct task_struct* pfp_schedule(struct task_struct * prev)
155 pfp_domain_t* pfp = local_pfp; 163 pfp_domain_t* pfp = local_pfp;
156 struct task_struct* next; 164 struct task_struct* next;
157 165
158 int out_of_time, sleep, preempt, np, exists, blocks, resched, migrate; 166 int out_of_time, signal_budget, sleep, preempt, np, exists, blocks, resched, migrate;
159 167
160 raw_spin_lock(&pfp->slock); 168 raw_spin_lock(&pfp->slock);
161 169
@@ -172,6 +180,10 @@ static struct task_struct* pfp_schedule(struct task_struct * prev)
172 out_of_time = exists && 180 out_of_time = exists &&
173 budget_enforced(pfp->scheduled) && 181 budget_enforced(pfp->scheduled) &&
174 budget_exhausted(pfp->scheduled); 182 budget_exhausted(pfp->scheduled);
183 signal_budget = exists &&
184 budget_signalled(pfp->scheduled) &&
185 budget_exhausted(pfp->scheduled) &&
186 !sigbudget_sent(pfp->scheduled);
175 np = exists && is_np(pfp->scheduled); 187 np = exists && is_np(pfp->scheduled);
176 sleep = exists && get_rt_flags(pfp->scheduled) == RT_F_SLEEP; 188 sleep = exists && get_rt_flags(pfp->scheduled) == RT_F_SLEEP;
177 migrate = exists && get_partition(pfp->scheduled) != pfp->cpu; 189 migrate = exists && get_partition(pfp->scheduled) != pfp->cpu;
@@ -183,6 +195,10 @@ static struct task_struct* pfp_schedule(struct task_struct * prev)
183 */ 195 */
184 resched = preempt; 196 resched = preempt;
185 197
198 /* Send the signal that the budget has been exhausted */
199 if (signal_budget)
200 send_sigbudget(pfp->scheduled);
201
186 /* If a task blocks we have no choice but to reschedule. 202 /* If a task blocks we have no choice but to reschedule.
187 */ 203 */
188 if (blocks) 204 if (blocks)
diff --git a/litmus/sched_psn_edf.c b/litmus/sched_psn_edf.c
index b0c8126bd44a..a5fda133bad9 100644
--- a/litmus/sched_psn_edf.c
+++ b/litmus/sched_psn_edf.c
@@ -169,17 +169,25 @@ static void psnedf_tick(struct task_struct *t)
169 */ 169 */
170 BUG_ON(is_realtime(t) && t != pedf->scheduled); 170 BUG_ON(is_realtime(t) && t != pedf->scheduled);
171 171
172 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) { 172 if (is_realtime(t) && budget_exhausted(t))
173 if (!is_np(t)) { 173 {
174 litmus_reschedule_local(); 174 if (budget_signalled(t) && !sigbudget_sent(t)) {
175 TRACE("psnedf_scheduler_tick: " 175 /* signal exhaustion */
176 "%d is preemptable " 176 send_sigbudget(t);
177 " => FORCE_RESCHED\n", t->pid); 177 }
178 } else if (is_user_np(t)) { 178
179 TRACE("psnedf_scheduler_tick: " 179 if (budget_enforced(t)) {
180 "%d is non-preemptable, " 180 if (!is_np(t)) {
181 "preemption delayed.\n", t->pid); 181 litmus_reschedule_local();
182 request_exit_np(t); 182 TRACE("psnedf_scheduler_tick: "
183 "%d is preemptable "
184 " => FORCE_RESCHED\n", t->pid);
185 } else if (is_user_np(t)) {
186 TRACE("psnedf_scheduler_tick: "
187 "%d is non-preemptable, "
188 "preemption delayed.\n", t->pid);
189 request_exit_np(t);
190 }
183 } 191 }
184 } 192 }
185} 193}
@@ -190,8 +198,7 @@ static struct task_struct* psnedf_schedule(struct task_struct * prev)
190 rt_domain_t* edf = &pedf->domain; 198 rt_domain_t* edf = &pedf->domain;
191 struct task_struct* next; 199 struct task_struct* next;
192 200
193 int out_of_time, sleep, preempt, 201 int out_of_time, signal_budget, sleep, preempt, np, exists, blocks, resched;
194 np, exists, blocks, resched;
195 202
196 raw_spin_lock(&pedf->slock); 203 raw_spin_lock(&pedf->slock);
197 204
@@ -208,6 +215,10 @@ static struct task_struct* psnedf_schedule(struct task_struct * prev)
208 out_of_time = exists && 215 out_of_time = exists &&
209 budget_enforced(pedf->scheduled) && 216 budget_enforced(pedf->scheduled) &&
210 budget_exhausted(pedf->scheduled); 217 budget_exhausted(pedf->scheduled);
218 signal_budget = exists &&
219 budget_signalled(pedf->scheduled) &&
220 budget_exhausted(pedf->scheduled) &&
221 !sigbudget_sent(pedf->scheduled);
211 np = exists && is_np(pedf->scheduled); 222 np = exists && is_np(pedf->scheduled);
212 sleep = exists && get_rt_flags(pedf->scheduled) == RT_F_SLEEP; 223 sleep = exists && get_rt_flags(pedf->scheduled) == RT_F_SLEEP;
213 preempt = edf_preemption_needed(edf, prev); 224 preempt = edf_preemption_needed(edf, prev);
@@ -218,6 +229,10 @@ static struct task_struct* psnedf_schedule(struct task_struct * prev)
218 */ 229 */
219 resched = preempt; 230 resched = preempt;
220 231
232 /* Send the signal that the budget has been exhausted */
233 if (signal_budget)
234 send_sigbudget(pedf->scheduled);
235
221 /* If a task blocks we have no choice but to reschedule. 236 /* If a task blocks we have no choice but to reschedule.
222 */ 237 */
223 if (blocks) 238 if (blocks)