diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2008-05-02 22:54:44 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2008-05-02 22:54:44 -0400 |
commit | 89908c1b2f22b19641f5cbc19805be7aed664a8e (patch) | |
tree | 933625bbb2454e3341cfbf6c172bb43425f5a1c7 | |
parent | ae9203a19764fd434ded1e4b16ce897566aba63c (diff) |
LITMUS: use no_rqlock_work to avoid ksoftirqd deadlock
We can't use tasklets from within the scheduler.
User no_rqlock_work instead.
-rw-r--r-- | include/litmus/litmus.h | 5 | ||||
-rw-r--r-- | include/litmus/rt_domain.h | 4 | ||||
-rw-r--r-- | include/litmus/rt_param.h | 14 | ||||
-rw-r--r-- | litmus/rt_domain.c | 15 |
4 files changed, 26 insertions, 12 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h index 8fc9f630c8..a4c49111aa 100644 --- a/include/litmus/litmus.h +++ b/include/litmus/litmus.h | |||
@@ -173,7 +173,10 @@ static inline lt_t litmus_clock(void) | |||
173 | #define ns_to_ktime(t) ktime_add_ns(ktime_set(0, 0), t) | 173 | #define ns_to_ktime(t) ktime_add_ns(ktime_set(0, 0), t) |
174 | 174 | ||
175 | /* The high-resolution release timer for a task. */ | 175 | /* The high-resolution release timer for a task. */ |
176 | #define release_timer(t) ((t)->rt_param.job_params.release_timer) | 176 | #define release_timer(t) ((t)->rt_param.release_timer) |
177 | |||
178 | /* The high-resolution release timer for a task. */ | ||
179 | #define get_domain(t) ((t)->rt_param.domain) | ||
177 | 180 | ||
178 | /* Honor the flag in the preempt_count variable that is set | 181 | /* Honor the flag in the preempt_count variable that is set |
179 | * when scheduling is in progress. | 182 | * when scheduling is in progress. |
diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h index 7b2a11c0f2..6489b0c0fd 100644 --- a/include/litmus/rt_domain.h +++ b/include/litmus/rt_domain.h | |||
@@ -5,7 +5,7 @@ | |||
5 | #ifndef __UNC_RT_DOMAIN_H__ | 5 | #ifndef __UNC_RT_DOMAIN_H__ |
6 | #define __UNC_RT_DOMAIN_H__ | 6 | #define __UNC_RT_DOMAIN_H__ |
7 | 7 | ||
8 | #include <linux/interrupt.h> | 8 | #include <litmus/norqlock.h> |
9 | 9 | ||
10 | struct _rt_domain; | 10 | struct _rt_domain; |
11 | 11 | ||
@@ -13,7 +13,7 @@ typedef int (*check_resched_needed_t)(struct _rt_domain *rt); | |||
13 | typedef void (*release_job_t)(struct task_struct *t, struct _rt_domain *rt); | 13 | typedef void (*release_job_t)(struct task_struct *t, struct _rt_domain *rt); |
14 | 14 | ||
15 | typedef struct _rt_domain { | 15 | typedef struct _rt_domain { |
16 | struct tasklet_struct release_tasklet; | 16 | struct no_rqlock_work arm_timers; |
17 | 17 | ||
18 | /* runnable rt tasks are in here */ | 18 | /* runnable rt tasks are in here */ |
19 | spinlock_t ready_lock; | 19 | spinlock_t ready_lock; |
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index 933c1961cb..76be2fe4be 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
@@ -38,17 +38,15 @@ struct rt_task { | |||
38 | /* don't export internal data structures to user space (liblitmus) */ | 38 | /* don't export internal data structures to user space (liblitmus) */ |
39 | #ifdef __KERNEL__ | 39 | #ifdef __KERNEL__ |
40 | 40 | ||
41 | struct _rt_domain; | ||
42 | |||
41 | struct rt_job { | 43 | struct rt_job { |
42 | /* Time instant the the job was or will be released. */ | 44 | /* Time instant the the job was or will be released. */ |
43 | lt_t release; | 45 | lt_t release; |
44 | /* What is the current deadline? */ | 46 | /* What is the current deadline? */ |
45 | lt_t deadline; | 47 | lt_t deadline; |
46 | 48 | ||
47 | /* The high-resolution timer used to control its release. */ | 49 | /* How much service has this job received so far? */ |
48 | struct hrtimer release_timer; | ||
49 | |||
50 | /* How much service has this job received so far? | ||
51 | */ | ||
52 | lt_t exec_time; | 50 | lt_t exec_time; |
53 | 51 | ||
54 | /* Which job is this. This is used to let user space | 52 | /* Which job is this. This is used to let user space |
@@ -125,6 +123,12 @@ struct rt_param { | |||
125 | */ | 123 | */ |
126 | int old_policy; | 124 | int old_policy; |
127 | int old_prio; | 125 | int old_prio; |
126 | |||
127 | /* The high-resolution timer used to control its release. */ | ||
128 | struct hrtimer release_timer; | ||
129 | |||
130 | /* ready queue for this task */ | ||
131 | struct _rt_domain* domain; | ||
128 | }; | 132 | }; |
129 | 133 | ||
130 | /* Possible RT flags */ | 134 | /* Possible RT flags */ |
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c index cbedbac1dc..47027b49bb 100644 --- a/litmus/rt_domain.c +++ b/litmus/rt_domain.c | |||
@@ -35,7 +35,13 @@ static void default_release_job(struct task_struct* t, rt_domain_t* rt) | |||
35 | 35 | ||
36 | static enum hrtimer_restart release_job_timer(struct hrtimer *timer) | 36 | static enum hrtimer_restart release_job_timer(struct hrtimer *timer) |
37 | { | 37 | { |
38 | /* call the current plugin */ | 38 | struct task_struct *t; |
39 | |||
40 | t = container_of(timer, struct task_struct, | ||
41 | rt_param.release_timer); | ||
42 | |||
43 | get_domain(t)->release_job(t, get_domain(t)); | ||
44 | |||
39 | return HRTIMER_NORESTART; | 45 | return HRTIMER_NORESTART; |
40 | } | 46 | } |
41 | 47 | ||
@@ -44,7 +50,7 @@ static void setup_job_release_timer(struct task_struct *task) | |||
44 | hrtimer_init(&release_timer(task), CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 50 | hrtimer_init(&release_timer(task), CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
45 | release_timer(task).function = release_job_timer; | 51 | release_timer(task).function = release_job_timer; |
46 | #ifdef CONFIG_HIGH_RES_TIMERS | 52 | #ifdef CONFIG_HIGH_RES_TIMERS |
47 | release_timer(task).cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; | 53 | release_timer(task).cb_mode = HRTIMER_CB_IRQSAFE_NO_RESTART; |
48 | #endif | 54 | #endif |
49 | /* Expiration time of timer is release time of task. */ | 55 | /* Expiration time of timer is release time of task. */ |
50 | release_timer(task).expires = ns_to_ktime(get_release(task)); | 56 | release_timer(task).expires = ns_to_ktime(get_release(task)); |
@@ -95,7 +101,7 @@ void rt_domain_init(rt_domain_t *rt, | |||
95 | rt->check_resched = check; | 101 | rt->check_resched = check; |
96 | rt->release_job = release; | 102 | rt->release_job = release; |
97 | rt->order = order; | 103 | rt->order = order; |
98 | tasklet_init(&rt->release_tasklet, arm_release_timers, (unsigned long) rt); | 104 | init_no_rqlock_work(&rt->arm_timers, arm_release_timers, (unsigned long) rt); |
99 | } | 105 | } |
100 | 106 | ||
101 | /* add_ready - add a real-time task to the rt ready queue. It must be runnable. | 107 | /* add_ready - add a real-time task to the rt ready queue. It must be runnable. |
@@ -135,6 +141,7 @@ struct task_struct* __peek_ready(rt_domain_t* rt) | |||
135 | void __add_release(rt_domain_t* rt, struct task_struct *task) | 141 | void __add_release(rt_domain_t* rt, struct task_struct *task) |
136 | { | 142 | { |
137 | list_add(&task->rt_list, &rt->release_queue); | 143 | list_add(&task->rt_list, &rt->release_queue); |
138 | tasklet_hi_schedule(&rt->release_tasklet); | 144 | task->rt_param.domain = rt; |
145 | do_without_rqlock(&rt->arm_timers); | ||
139 | } | 146 | } |
140 | 147 | ||