diff options
Diffstat (limited to 'litmus')
-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 |
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 | ||
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) |