diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-09-21 22:49:37 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-09-21 22:49:37 -0400 |
commit | 7b4a10031257415b0ff1c03a77ac33555eeed8fe (patch) | |
tree | 6cd27ad9b087b62494ed202beb54e6e11ccdb7dd | |
parent | 2554c82c261906350c606e70dc2bf566cefbb190 (diff) |
rt_domain_t: add add_release_on()
This API addition allows the calling code to override
the release master for a given rt_domain_t object. This
is particularly useful if a job is supposed to migrate
to a particular CPU. This need arises for example in semi-
partitioned schedulers.
-rw-r--r-- | include/litmus/rt_domain.h | 16 | ||||
-rw-r--r-- | litmus/rt_domain.c | 40 |
2 files changed, 49 insertions, 7 deletions
diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h index 59e6b54e9281..ac249292e866 100644 --- a/include/litmus/rt_domain.h +++ b/include/litmus/rt_domain.h | |||
@@ -143,12 +143,26 @@ static inline struct task_struct* take_ready(rt_domain_t* rt) | |||
143 | static inline void add_release(rt_domain_t* rt, struct task_struct *task) | 143 | static inline void add_release(rt_domain_t* rt, struct task_struct *task) |
144 | { | 144 | { |
145 | unsigned long flags; | 145 | unsigned long flags; |
146 | /* first we need the write lock for rt_ready_queue */ | ||
147 | raw_spin_lock_irqsave(&rt->tobe_lock, flags); | 146 | raw_spin_lock_irqsave(&rt->tobe_lock, flags); |
148 | __add_release(rt, task); | 147 | __add_release(rt, task); |
149 | raw_spin_unlock_irqrestore(&rt->tobe_lock, flags); | 148 | raw_spin_unlock_irqrestore(&rt->tobe_lock, flags); |
150 | } | 149 | } |
151 | 150 | ||
151 | #ifdef CONFIG_RELEASE_MASTER | ||
152 | void __add_release_on(rt_domain_t* rt, struct task_struct *task, | ||
153 | int target_cpu); | ||
154 | |||
155 | static inline void add_release_on(rt_domain_t* rt, | ||
156 | struct task_struct *task, | ||
157 | int target_cpu) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | raw_spin_lock_irqsave(&rt->tobe_lock, flags); | ||
161 | __add_release_on(rt, task, target_cpu); | ||
162 | raw_spin_unlock_irqrestore(&rt->tobe_lock, flags); | ||
163 | } | ||
164 | #endif | ||
165 | |||
152 | static inline int __jobs_pending(rt_domain_t* rt) | 166 | static inline int __jobs_pending(rt_domain_t* rt) |
153 | { | 167 | { |
154 | return !bheap_empty(&rt->ready_queue); | 168 | return !bheap_empty(&rt->ready_queue); |
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c index 8a3ff706c208..d27af48e0298 100644 --- a/litmus/rt_domain.c +++ b/litmus/rt_domain.c | |||
@@ -169,7 +169,12 @@ static void reinit_release_heap(struct task_struct* t) | |||
169 | * - tobe_lock taken | 169 | * - tobe_lock taken |
170 | * - IRQ disabled | 170 | * - IRQ disabled |
171 | */ | 171 | */ |
172 | static void arm_release_timer(rt_domain_t *_rt) | 172 | #ifdef CONFIG_RELEASE_MASTER |
173 | #define arm_release_timer(t) arm_release_timer_on((t), NO_CPU) | ||
174 | static void arm_release_timer_on(rt_domain_t *_rt , int target_cpu) | ||
175 | #else | ||
176 | static void arm_release_master(rt_domain_t *_rt) | ||
177 | #endif | ||
173 | { | 178 | { |
174 | rt_domain_t *rt = _rt; | 179 | rt_domain_t *rt = _rt; |
175 | struct list_head list; | 180 | struct list_head list; |
@@ -224,17 +229,21 @@ static void arm_release_timer(rt_domain_t *_rt) | |||
224 | * PINNED mode is ok on both local and remote CPU | 229 | * PINNED mode is ok on both local and remote CPU |
225 | */ | 230 | */ |
226 | #ifdef CONFIG_RELEASE_MASTER | 231 | #ifdef CONFIG_RELEASE_MASTER |
227 | if (rt->release_master == NO_CPU) | 232 | if (rt->release_master == NO_CPU && |
233 | target_cpu == NO_CPU) | ||
228 | #endif | 234 | #endif |
229 | __hrtimer_start_range_ns(&rh->timer, | 235 | __hrtimer_start_range_ns(&rh->timer, |
230 | ns_to_ktime(rh->release_time), | 236 | ns_to_ktime(rh->release_time), |
231 | 0, HRTIMER_MODE_ABS_PINNED, 0); | 237 | 0, HRTIMER_MODE_ABS_PINNED, 0); |
232 | #ifdef CONFIG_RELEASE_MASTER | 238 | #ifdef CONFIG_RELEASE_MASTER |
233 | else | 239 | else |
234 | hrtimer_start_on(rt->release_master, | 240 | hrtimer_start_on( |
235 | &rh->info, &rh->timer, | 241 | /* target_cpu overrides release master */ |
236 | ns_to_ktime(rh->release_time), | 242 | (target_cpu != NO_CPU ? |
237 | HRTIMER_MODE_ABS_PINNED); | 243 | target_cpu : rt->release_master), |
244 | &rh->info, &rh->timer, | ||
245 | ns_to_ktime(rh->release_time), | ||
246 | HRTIMER_MODE_ABS_PINNED); | ||
238 | #endif | 247 | #endif |
239 | } else | 248 | } else |
240 | TRACE_TASK(t, "0x%p is not my timer\n", &rh->timer); | 249 | TRACE_TASK(t, "0x%p is not my timer\n", &rh->timer); |
@@ -299,6 +308,25 @@ void __merge_ready(rt_domain_t* rt, struct bheap* tasks) | |||
299 | rt->check_resched(rt); | 308 | rt->check_resched(rt); |
300 | } | 309 | } |
301 | 310 | ||
311 | |||
312 | #ifdef CONFIG_RELEASE_MASTER | ||
313 | void __add_release_on(rt_domain_t* rt, struct task_struct *task, | ||
314 | int target_cpu) | ||
315 | { | ||
316 | TRACE_TASK(task, "add_release_on(), rel=%llu, target=%d\n", | ||
317 | get_release(task), target_cpu); | ||
318 | list_add(&tsk_rt(task)->list, &rt->tobe_released); | ||
319 | task->rt_param.domain = rt; | ||
320 | |||
321 | /* start release timer */ | ||
322 | TS_SCHED2_START(task); | ||
323 | |||
324 | arm_release_timer_on(rt, target_cpu); | ||
325 | |||
326 | TS_SCHED2_END(task); | ||
327 | } | ||
328 | #endif | ||
329 | |||
302 | /* add_release - add a real-time task to the rt release queue. | 330 | /* add_release - add a real-time task to the rt release queue. |
303 | * @task: the sleeping task | 331 | * @task: the sleeping task |
304 | */ | 332 | */ |