diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-07 23:25:01 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-07 23:33:05 -0400 |
commit | 6a225701acf7d79f292eeffcd99d6f00b02c180b (patch) | |
tree | 6a7f538703a5a6460a0e53c62f0f952998840ea1 | |
parent | b53c479a0f44b8990ce106622412a3bf54809944 (diff) |
Infrastructure for Litmus signals.prop/litmus-signals
Added signals to Litmus. Specifcally, SIG_BUDGET signals
are delivered (when requested by real-time tasks) when
a budget is exceeded.
Note: pfair not currently supported (but it probably could be).
-rw-r--r-- | include/litmus/budget.h | 20 | ||||
-rw-r--r-- | include/litmus/rt_param.h | 16 | ||||
-rw-r--r-- | include/litmus/signal.h | 47 | ||||
-rw-r--r-- | litmus/budget.c | 16 | ||||
-rw-r--r-- | litmus/jobs.c | 2 | ||||
-rw-r--r-- | litmus/litmus.c | 10 | ||||
-rw-r--r-- | litmus/sched_cedf.c | 47 | ||||
-rw-r--r-- | litmus/sched_gsn_edf.c | 54 | ||||
-rw-r--r-- | litmus/sched_pfp.c | 40 | ||||
-rw-r--r-- | litmus/sched_psn_edf.c | 41 |
10 files changed, 227 insertions, 66 deletions
diff --git a/include/litmus/budget.h b/include/litmus/budget.h index 33344ee8d5f9..763b31c0e9f6 100644 --- a/include/litmus/budget.h +++ b/include/litmus/budget.h | |||
@@ -5,6 +5,9 @@ | |||
5 | * the next task. */ | 5 | * the next task. */ |
6 | void update_enforcement_timer(struct task_struct* t); | 6 | void update_enforcement_timer(struct task_struct* t); |
7 | 7 | ||
8 | /* Send SIG_BUDGET to a real-time task. */ | ||
9 | void send_sigbudget(struct task_struct* t); | ||
10 | |||
8 | inline static int budget_exhausted(struct task_struct* t) | 11 | inline static int budget_exhausted(struct task_struct* t) |
9 | { | 12 | { |
10 | return get_exec_time(t) >= get_exec_cost(t); | 13 | return get_exec_time(t) >= get_exec_cost(t); |
@@ -19,10 +22,21 @@ inline static lt_t budget_remaining(struct task_struct* t) | |||
19 | return 0; | 22 | return 0; |
20 | } | 23 | } |
21 | 24 | ||
22 | #define budget_enforced(t) (tsk_rt(t)->task_params.budget_policy != NO_ENFORCEMENT) | 25 | #define budget_enforced(t) (\ |
26 | tsk_rt(t)->task_params.budget_policy != NO_ENFORCEMENT) | ||
27 | |||
28 | #define budget_precisely_tracked(t) (\ | ||
29 | tsk_rt(t)->task_params.budget_policy == PRECISE_ENFORCEMENT || \ | ||
30 | tsk_rt(t)->task_params.budget_signal_policy == PRECISE_SIGNALS) | ||
31 | |||
32 | #define budget_signalled(t) (\ | ||
33 | tsk_rt(t)->task_params.budget_signal_policy != NO_SIGNALS) | ||
34 | |||
35 | #define budget_precisely_signalled(t) (\ | ||
36 | tsk_rt(t)->task_params.budget_policy == PRECISE_SIGNALS) | ||
23 | 37 | ||
24 | #define budget_precisely_enforced(t) (tsk_rt(t)->task_params.budget_policy \ | 38 | #define sigbudget_sent(t) (\ |
25 | == PRECISE_ENFORCEMENT) | 39 | test_bit(RT_JOB_SIG_BUDGET_SENT, &tsk_rt(t)->job_params.flags)) |
26 | 40 | ||
27 | static inline int requeue_preempted_job(struct task_struct* t) | 41 | static inline int requeue_preempted_job(struct task_struct* t) |
28 | { | 42 | { |
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index 89ac0dda7d3d..637fe6b84f9d 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
@@ -30,9 +30,15 @@ typedef enum { | |||
30 | typedef enum { | 30 | typedef enum { |
31 | NO_ENFORCEMENT, /* job may overrun unhindered */ | 31 | NO_ENFORCEMENT, /* job may overrun unhindered */ |
32 | QUANTUM_ENFORCEMENT, /* budgets are only checked on quantum boundaries */ | 32 | QUANTUM_ENFORCEMENT, /* budgets are only checked on quantum boundaries */ |
33 | PRECISE_ENFORCEMENT /* budgets are enforced with hrtimers */ | 33 | PRECISE_ENFORCEMENT, /* budgets are enforced with hrtimers */ |
34 | } budget_policy_t; | 34 | } budget_policy_t; |
35 | 35 | ||
36 | typedef enum { | ||
37 | NO_SIGNALS, /* job receives no signals when it exhausts its budget */ | ||
38 | QUANTUM_SIGNALS, /* budget signals are only sent on quantum boundaries */ | ||
39 | PRECISE_SIGNALS, /* budget signals are triggered with hrtimers */ | ||
40 | } budget_signal_policy_t; | ||
41 | |||
36 | /* We use the common priority interpretation "lower index == higher priority", | 42 | /* We use the common priority interpretation "lower index == higher priority", |
37 | * which is commonly used in fixed-priority schedulability analysis papers. | 43 | * which is commonly used in fixed-priority schedulability analysis papers. |
38 | * So, a numerically lower priority value implies higher scheduling priority, | 44 | * So, a numerically lower priority value implies higher scheduling priority, |
@@ -62,6 +68,7 @@ struct rt_task { | |||
62 | unsigned int priority; | 68 | unsigned int priority; |
63 | task_class_t cls; | 69 | task_class_t cls; |
64 | budget_policy_t budget_policy; /* ignored by pfair */ | 70 | budget_policy_t budget_policy; /* ignored by pfair */ |
71 | budget_signal_policy_t budget_signal_policy; /* currently ignored by pfair */ | ||
65 | }; | 72 | }; |
66 | 73 | ||
67 | union np_flag { | 74 | union np_flag { |
@@ -118,8 +125,15 @@ struct rt_job { | |||
118 | * Increase this sequence number when a job is released. | 125 | * Increase this sequence number when a job is released. |
119 | */ | 126 | */ |
120 | unsigned int job_no; | 127 | unsigned int job_no; |
128 | |||
129 | /* bits: | ||
130 | * 0th: Set if a budget exhaustion signal has already been sent for | ||
131 | * the current job. */ | ||
132 | unsigned long flags; | ||
121 | }; | 133 | }; |
122 | 134 | ||
135 | #define RT_JOB_SIG_BUDGET_SENT 0 | ||
136 | |||
123 | struct pfair_param; | 137 | struct pfair_param; |
124 | 138 | ||
125 | /* RT task parameters for scheduling extensions | 139 | /* RT task parameters for scheduling extensions |
diff --git a/include/litmus/signal.h b/include/litmus/signal.h new file mode 100644 index 000000000000..b3d82b294984 --- /dev/null +++ b/include/litmus/signal.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef LITMUS_SIGNAL_H | ||
2 | #define LITMUS_SIGNAL_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | #include <linux/signal.h> | ||
6 | #else | ||
7 | #include <signal.h> | ||
8 | #endif | ||
9 | |||
10 | /* Signals used by Litmus to asynchronously communicate events | ||
11 | * to real-time tasks. | ||
12 | * | ||
13 | * Signal values overlap with [SIGRTMIN, SIGRTMAX], so beware of | ||
14 | * application-level conflicts when dealing with COTS user-level | ||
15 | * code. | ||
16 | */ | ||
17 | |||
18 | /* Sent to a Litmus task when all of the following conditions are true: | ||
19 | * (1) The task has exhausted its budget. | ||
20 | * (2) budget_signal_policy is QUANTUM_SIGNALS or PRECISE_SIGNALS. | ||
21 | * | ||
22 | * Note: If a task does not have a registered handler for SIG_BUDGET, | ||
23 | * the signal will cause the task to terminate (default action). | ||
24 | */ | ||
25 | |||
26 | /* Assigned values start at SIGRTMAX and decrease, hopefully reducing | ||
27 | * likelihood of user-level conflicts. | ||
28 | */ | ||
29 | #define SIG_BUDGET (SIGRTMAX - 0) | ||
30 | |||
31 | /* | ||
32 | Future signals could include: | ||
33 | |||
34 | #define SIG_DEADLINE_MISS (SIGRTMAX - 1) | ||
35 | #define SIG_CRIT_LEVEL_CHANGE (SIGRTMAX - 2) | ||
36 | */ | ||
37 | |||
38 | #define SIGLITMUSMIN SIG_BUDGET | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | #if (SIGLITMUSMIN < SIGRTMIN) | ||
42 | /* no compile-time check in user-space since SIGRTMIN may be a variable. */ | ||
43 | #error "Too many LITMUS^RT signals!" | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | #endif | ||
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 | ||
10 | struct enforcement_timer { | 12 | struct 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 | ||
101 | void 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 | ||
100 | static int __init init_budget_enforcement(void) | 112 | static 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 | */ |
372 | static void cedf_tick(struct task_struct* t) | 372 | static 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 | */ |
363 | static void gsnedf_tick(struct task_struct* t) | 363 | static 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) | |||
404 | static struct task_struct* gsnedf_schedule(struct task_struct * prev) | 412 | static 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) |