diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-10 14:50:12 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-10 14:50:12 -0400 |
commit | f4260f81a68d170b1d3558b5447343224d918a45 (patch) | |
tree | 647b6490efe8a6157cf3a919ec62eb5c0784175a | |
parent | 893c8943ce5c5527f05ab7e9208d5a942d77d8b5 (diff) | |
parent | 6a225701acf7d79f292eeffcd99d6f00b02c180b (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.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 | 55 | ||||
-rw-r--r-- | litmus/sched_pfp.c | 40 | ||||
-rw-r--r-- | litmus/sched_psn_edf.c | 41 |
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. */ |
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 419ff0c88a65..a1f3613ebeed 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
@@ -32,9 +32,15 @@ typedef enum { | |||
32 | typedef enum { | 32 | typedef 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 | ||
38 | typedef 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 | ||
69 | union np_flag { | 76 | union 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 | |||
147 | struct pfair_param; | 161 | struct pfair_param; |
148 | 162 | ||
149 | enum klitirqd_sem_status | 163 | enum 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 | /* | ||
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 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 | */ |
434 | static void cedf_tick(struct task_struct* t) | 434 | static 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 | */ |
411 | static void gsnedf_tick(struct task_struct* t) | 411 | static 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, | |||
764 | static struct task_struct* gsnedf_schedule(struct task_struct * prev) | 772 | static 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) |