aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-09-10 14:50:12 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2012-09-10 14:50:12 -0400
commitf4260f81a68d170b1d3558b5447343224d918a45 (patch)
tree647b6490efe8a6157cf3a919ec62eb5c0784175a
parent893c8943ce5c5527f05ab7e9208d5a942d77d8b5 (diff)
parent6a225701acf7d79f292eeffcd99d6f00b02c180b (diff)
Merge remote-tracking branch 'github/prop/litmus-signals' into wip-gpu-rtas12
Conflicts: litmus/sched_gsn_edf.c
-rw-r--r--include/litmus/budget.h20
-rw-r--r--include/litmus/rt_param.h16
-rw-r--r--include/litmus/signal.h47
-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.c55
-rw-r--r--litmus/sched_pfp.c40
-rw-r--r--litmus/sched_psn_edf.c41
10 files changed, 228 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. */
6void update_enforcement_timer(struct task_struct* t); 6void update_enforcement_timer(struct task_struct* t);
7 7
8/* Send SIG_BUDGET to a real-time task. */
9void send_sigbudget(struct task_struct* t);
10
8inline static int budget_exhausted(struct task_struct* t) 11inline 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
27static inline int requeue_preempted_job(struct task_struct* t) 41static 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 419ff0c88a65..a1f3613ebeed 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -32,9 +32,15 @@ typedef enum {
32typedef enum { 32typedef enum {
33 NO_ENFORCEMENT, /* job may overrun unhindered */ 33 NO_ENFORCEMENT, /* job may overrun unhindered */
34 QUANTUM_ENFORCEMENT, /* budgets are only checked on quantum boundaries */ 34 QUANTUM_ENFORCEMENT, /* budgets are only checked on quantum boundaries */
35 PRECISE_ENFORCEMENT /* budgets are enforced with hrtimers */ 35 PRECISE_ENFORCEMENT, /* budgets are enforced with hrtimers */
36} budget_policy_t; 36} budget_policy_t;
37 37
38typedef enum {
39 NO_SIGNALS, /* job receives no signals when it exhausts its budget */
40 QUANTUM_SIGNALS, /* budget signals are only sent on quantum boundaries */
41 PRECISE_SIGNALS, /* budget signals are triggered with hrtimers */
42} budget_signal_policy_t;
43
38/* We use the common priority interpretation "lower index == higher priority", 44/* We use the common priority interpretation "lower index == higher priority",
39 * which is commonly used in fixed-priority schedulability analysis papers. 45 * which is commonly used in fixed-priority schedulability analysis papers.
40 * So, a numerically lower priority value implies higher scheduling priority, 46 * So, a numerically lower priority value implies higher scheduling priority,
@@ -64,6 +70,7 @@ struct rt_task {
64 unsigned int priority; 70 unsigned int priority;
65 task_class_t cls; 71 task_class_t cls;
66 budget_policy_t budget_policy; /* ignored by pfair */ 72 budget_policy_t budget_policy; /* ignored by pfair */
73 budget_signal_policy_t budget_signal_policy; /* currently ignored by pfair */
67}; 74};
68 75
69union np_flag { 76union np_flag {
@@ -142,8 +149,15 @@ struct rt_job {
142 * Increase this sequence number when a job is released. 149 * Increase this sequence number when a job is released.
143 */ 150 */
144 unsigned int job_no; 151 unsigned int job_no;
152
153 /* bits:
154 * 0th: Set if a budget exhaustion signal has already been sent for
155 * the current job. */
156 unsigned long flags;
145}; 157};
146 158
159#define RT_JOB_SIG_BUDGET_SENT 0
160
147struct pfair_param; 161struct pfair_param;
148 162
149enum klitirqd_sem_status 163enum klitirqd_sem_status
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/*
32Future 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
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 fb093c03d53d..9fe4eb1fa168 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 83a860c52e17..53727d699915 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -162,6 +162,16 @@ asmlinkage long sys_set_rt_task_param(pid_t pid, struct rt_task __user * param)
162 pid, tp.budget_policy); 162 pid, tp.budget_policy);
163 goto out_unlock; 163 goto out_unlock;
164 } 164 }
165 if (tp.budget_signal_policy != NO_SIGNALS &&
166 tp.budget_signal_policy != QUANTUM_SIGNALS &&
167 tp.budget_signal_policy != PRECISE_SIGNALS)
168 {
169 printk(KERN_INFO "litmus: real-time task %d rejected "
170 "because unsupported budget signalling policy "
171 "specified (%d)\n",
172 pid, tp.budget_signal_policy);
173 goto out_unlock;
174 }
165 175
166 target->rt_param.task_params = tp; 176 target->rt_param.task_params = tp;
167 177
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c
index 0460e232d6e6..d98de4579394 100644
--- a/litmus/sched_cedf.c
+++ b/litmus/sched_cedf.c
@@ -433,21 +433,29 @@ static noinline void job_completion(struct task_struct *t, int forced)
433 */ 433 */
434static void cedf_tick(struct task_struct* t) 434static void cedf_tick(struct task_struct* t)
435{ 435{
436 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) { 436 if (is_realtime(t) && budget_exhausted(t))
437 if (!is_np(t)) { 437 {
438 /* np tasks will be preempted when they become 438 if (budget_signalled(t) && !sigbudget_sent(t)) {
439 * preemptable again 439 /* signal exhaustion */
440 */ 440 send_sigbudget(t);
441 litmus_reschedule_local(); 441 }
442 set_will_schedule(); 442
443 TRACE("cedf_scheduler_tick: " 443 if (budget_enforced(t)) {
444 "%d is preemptable " 444 if (!is_np(t)) {
445 " => FORCE_RESCHED\n", t->pid); 445 /* np tasks will be preempted when they become
446 } else if (is_user_np(t)) { 446 * preemptable again
447 TRACE("cedf_scheduler_tick: " 447 */
448 "%d is non-preemptable, " 448 litmus_reschedule_local();
449 "preemption delayed.\n", t->pid); 449 set_will_schedule();
450 request_exit_np(t); 450 TRACE("cedf_scheduler_tick: "
451 "%d is preemptable "
452 " => FORCE_RESCHED\n", t->pid);
453 } else if (is_user_np(t)) {
454 TRACE("cedf_scheduler_tick: "
455 "%d is non-preemptable, "
456 "preemption delayed.\n", t->pid);
457 request_exit_np(t);
458 }
451 } 459 }
452 } 460 }
453} 461}
@@ -785,7 +793,7 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
785{ 793{
786 cpu_entry_t* entry = &__get_cpu_var(cedf_cpu_entries); 794 cpu_entry_t* entry = &__get_cpu_var(cedf_cpu_entries);
787 cedf_domain_t *cluster = entry->cluster; 795 cedf_domain_t *cluster = entry->cluster;
788 int out_of_time, sleep, preempt, np, exists, blocks; 796 int out_of_time, signal_budget, sleep, preempt, np, exists, blocks;
789 struct task_struct* next = NULL; 797 struct task_struct* next = NULL;
790 798
791#ifdef CONFIG_RELEASE_MASTER 799#ifdef CONFIG_RELEASE_MASTER
@@ -812,6 +820,10 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
812 out_of_time = exists && 820 out_of_time = exists &&
813 budget_enforced(entry->scheduled) && 821 budget_enforced(entry->scheduled) &&
814 budget_exhausted(entry->scheduled); 822 budget_exhausted(entry->scheduled);
823 signal_budget = exists &&
824 budget_signalled(entry->scheduled) &&
825 budget_exhausted(entry->scheduled) &&
826 !sigbudget_sent(entry->scheduled);
815 np = exists && is_np(entry->scheduled); 827 np = exists && is_np(entry->scheduled);
816 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP; 828 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP;
817 preempt = entry->scheduled != entry->linked; 829 preempt = entry->scheduled != entry->linked;
@@ -830,6 +842,9 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
830 TRACE_TASK(prev, "will be preempted by %s/%d\n", 842 TRACE_TASK(prev, "will be preempted by %s/%d\n",
831 entry->linked->comm, entry->linked->pid); 843 entry->linked->comm, entry->linked->pid);
832 844
845 /* Send the signal that the budget has been exhausted */
846 if (signal_budget)
847 send_sigbudget(entry->scheduled);
833 848
834 /* If a task blocks we have no choice but to reschedule. 849 /* If a task blocks we have no choice but to reschedule.
835 */ 850 */
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index 11304d634661..83b2f04b1532 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -410,20 +410,28 @@ static noinline void job_completion(struct task_struct *t, int forced)
410 */ 410 */
411static void gsnedf_tick(struct task_struct* t) 411static void gsnedf_tick(struct task_struct* t)
412{ 412{
413 if (is_realtime(t) && budget_enforced(t) && budget_exhausted(t)) { 413 if (is_realtime(t) && budget_exhausted(t))
414 if (!is_np(t)) { 414 {
415 /* np tasks will be preempted when they become 415 if (budget_signalled(t) && !sigbudget_sent(t)) {
416 * preemptable again 416 /* signal exhaustion */
417 */ 417 send_sigbudget(t);
418 litmus_reschedule_local(); 418 }
419 TRACE("gsnedf_scheduler_tick: " 419
420 "%d is preemptable " 420 if (budget_enforced(t)) {
421 " => FORCE_RESCHED\n", t->pid); 421 if (!is_np(t)) {
422 } else if (is_user_np(t)) { 422 /* np tasks will be preempted when they become
423 TRACE("gsnedf_scheduler_tick: " 423 * preemptable again
424 "%d is non-preemptable, " 424 */
425 "preemption delayed.\n", t->pid); 425 litmus_reschedule_local();
426 request_exit_np(t); 426 TRACE("gsnedf_scheduler_tick: "
427 "%d is preemptable "
428 " => FORCE_RESCHED\n", t->pid);
429 } else if (is_user_np(t)) {
430 TRACE("gsnedf_scheduler_tick: "
431 "%d is non-preemptable, "
432 "preemption delayed.\n", t->pid);
433 request_exit_np(t);
434 }
427 } 435 }
428 } 436 }
429} 437}
@@ -764,7 +772,7 @@ static void gsnedf_change_prio_pai_tasklet(struct task_struct *old_prio,
764static struct task_struct* gsnedf_schedule(struct task_struct * prev) 772static struct task_struct* gsnedf_schedule(struct task_struct * prev)
765{ 773{
766 cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); 774 cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries);
767 int out_of_time, sleep, preempt, np, exists, blocks; 775 int out_of_time, signal_budget, sleep, preempt, np, exists, blocks;
768 struct task_struct* next = NULL; 776 struct task_struct* next = NULL;
769 777
770#ifdef CONFIG_RELEASE_MASTER 778#ifdef CONFIG_RELEASE_MASTER
@@ -787,8 +795,13 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
787 /* (0) Determine state */ 795 /* (0) Determine state */
788 exists = entry->scheduled != NULL; 796 exists = entry->scheduled != NULL;
789 blocks = exists && !is_running(entry->scheduled); 797 blocks = exists && !is_running(entry->scheduled);
790 out_of_time = exists && budget_enforced(entry->scheduled) 798 out_of_time = exists &&
791 && budget_exhausted(entry->scheduled); 799 budget_enforced(entry->scheduled) &&
800 budget_exhausted(entry->scheduled);
801 signal_budget = exists &&
802 budget_signalled(entry->scheduled) &&
803 budget_exhausted(entry->scheduled) &&
804 !sigbudget_sent(entry->scheduled);
792 np = exists && is_np(entry->scheduled); 805 np = exists && is_np(entry->scheduled);
793 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP; 806 sleep = exists && get_rt_flags(entry->scheduled) == RT_F_SLEEP;
794 preempt = entry->scheduled != entry->linked; 807 preempt = entry->scheduled != entry->linked;
@@ -800,9 +813,9 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
800 /* 813 /*
801 if (exists) 814 if (exists)
802 TRACE_TASK(prev, 815 TRACE_TASK(prev,
803 "blocks:%d out_of_time:%d np:%d sleep:%d preempt:%d " 816 "blocks:%d out_of_time:%d signal_budget: %d np:%d sleep:%d preempt:%d "
804 "state:%d sig:%d\n", 817 "state:%d sig:%d\n",
805 blocks, out_of_time, np, sleep, preempt, 818 blocks, out_of_time, signal_budget, np, sleep, preempt,
806 prev->state, signal_pending(prev)); 819 prev->state, signal_pending(prev));
807 */ 820 */
808 821
@@ -810,6 +823,10 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
810 TRACE_TASK(prev, "will be preempted by %s/%d\n", 823 TRACE_TASK(prev, "will be preempted by %s/%d\n",
811 entry->linked->comm, entry->linked->pid); 824 entry->linked->comm, entry->linked->pid);
812 825
826 /* Send the signal that the budget has been exhausted */
827 if (signal_budget)
828 send_sigbudget(entry->scheduled);
829
813 /* If a task blocks we have no choice but to reschedule. 830 /* If a task blocks we have no choice but to reschedule.
814 */ 831 */
815 if (blocks) { 832 if (blocks) {
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)