aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/rt_domain.h3
-rw-r--r--kernel/hrtimer.c2
-rw-r--r--litmus/rt_domain.c21
-rw-r--r--litmus/sched_gsn_edf.c26
4 files changed, 41 insertions, 11 deletions
diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h
index bde1e5a54812..c7c55bef3e42 100644
--- a/include/litmus/rt_domain.h
+++ b/include/litmus/rt_domain.h
@@ -28,6 +28,7 @@ typedef struct _rt_domain {
28 /* real-time tasks waiting for release are in here */ 28 /* real-time tasks waiting for release are in here */
29 spinlock_t release_lock; 29 spinlock_t release_lock;
30 struct release_queue release_queue; 30 struct release_queue release_queue;
31 int release_master;
31 32
32 /* for moving tasks to the release queue */ 33 /* for moving tasks to the release queue */
33 spinlock_t tobe_lock; 34 spinlock_t tobe_lock;
@@ -51,6 +52,8 @@ struct release_heap {
51 struct heap heap; 52 struct heap heap;
52 /* used to trigger the release */ 53 /* used to trigger the release */
53 struct hrtimer timer; 54 struct hrtimer timer;
55 /* used to delegate releases */
56 struct hrtimer_start_on_info info;
54 /* required for the timer callback */ 57 /* required for the timer callback */
55 rt_domain_t* dom; 58 rt_domain_t* dom;
56}; 59};
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 509ecaea3016..7b19403900ad 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1077,9 +1077,11 @@ int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info,
1077 /* start timer locally; we may get called 1077 /* start timer locally; we may get called
1078 * with rq->lock held, do not wake up anything 1078 * with rq->lock held, do not wake up anything
1079 */ 1079 */
1080 TRACE("hrtimer_start_on: starting on local CPU\n");
1080 __hrtimer_start_range_ns(info->timer, info->time, 1081 __hrtimer_start_range_ns(info->timer, info->time,
1081 0, info->mode, 0); 1082 0, info->mode, 0);
1082 } else { 1083 } else {
1084 TRACE("hrtimer_start_on: pulling to remote CPU\n");
1083 base = &per_cpu(hrtimer_bases, cpu); 1085 base = &per_cpu(hrtimer_bases, cpu);
1084 spin_lock_irqsave(&base->lock, flags); 1086 spin_lock_irqsave(&base->lock, flags);
1085 was_empty = list_empty(&base->to_pull); 1087 was_empty = list_empty(&base->to_pull);
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c
index 78e76421aeba..62c9fdcd22be 100644
--- a/litmus/rt_domain.c
+++ b/litmus/rt_domain.c
@@ -158,6 +158,7 @@ static void reinit_release_heap(struct task_struct* t)
158 158
159 /* initialize */ 159 /* initialize */
160 heap_init(&rh->heap); 160 heap_init(&rh->heap);
161 atomic_set(&rh->info.state, HRTIMER_START_ON_INACTIVE);
161} 162}
162/* arm_release_timer() - start local release timer or trigger 163/* arm_release_timer() - start local release timer or trigger
163 * remote timer (pull timer) 164 * remote timer (pull timer)
@@ -217,14 +218,18 @@ static void arm_release_timer(rt_domain_t *_rt)
217 TRACE_TASK(t, "arming timer 0x%p\n", &rh->timer); 218 TRACE_TASK(t, "arming timer 0x%p\n", &rh->timer);
218 /* we cannot arm the timer using hrtimer_start() 219 /* we cannot arm the timer using hrtimer_start()
219 * as it may deadlock on rq->lock 220 * as it may deadlock on rq->lock
221 *
222 * PINNED mode is ok on both local and remote CPU
220 */ 223 */
221 /* FIXME now only one cpu without pulling 224 if (rt->release_master == NO_CPU)
222 * later more cpus; hrtimer_pull should call 225 __hrtimer_start_range_ns(&rh->timer,
223 * __hrtimer_start... always with PINNED mode 226 ns_to_ktime(rh->release_time),
224 */ 227 0, HRTIMER_MODE_ABS_PINNED, 0);
225 __hrtimer_start_range_ns(&rh->timer, 228 else
226 ns_to_ktime(rh->release_time), 229 hrtimer_start_on(rt->release_master,
227 0, HRTIMER_MODE_ABS_PINNED, 0); 230 &rh->info, &rh->timer,
231 ns_to_ktime(rh->release_time),
232 HRTIMER_MODE_ABS_PINNED);
228 } else 233 } else
229 TRACE_TASK(t, "0x%p is not my timer\n", &rh->timer); 234 TRACE_TASK(t, "0x%p is not my timer\n", &rh->timer);
230 } 235 }
@@ -246,6 +251,8 @@ void rt_domain_init(rt_domain_t *rt,
246 if (!order) 251 if (!order)
247 order = dummy_order; 252 order = dummy_order;
248 253
254 rt->release_master = NO_CPU;
255
249 heap_init(&rt->ready_queue); 256 heap_init(&rt->ready_queue);
250 INIT_LIST_HEAD(&rt->tobe_released); 257 INIT_LIST_HEAD(&rt->tobe_released);
251 for (i = 0; i < RELEASE_QUEUE_SLOTS; i++) 258 for (i = 0; i < RELEASE_QUEUE_SLOTS; i++)
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index 69990805e16a..a223e69f2efb 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -393,6 +393,12 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
393 int out_of_time, sleep, preempt, np, exists, blocks; 393 int out_of_time, sleep, preempt, np, exists, blocks;
394 struct task_struct* next = NULL; 394 struct task_struct* next = NULL;
395 395
396 /* Bail out early if we are the release master.
397 * The release master never schedules any real-time tasks.
398 */
399 if (gsnedf.release_master == entry->cpu)
400 return NULL;
401
396 spin_lock(&gsnedf_lock); 402 spin_lock(&gsnedf_lock);
397 clear_will_schedule(); 403 clear_will_schedule();
398 404
@@ -515,8 +521,15 @@ static void gsnedf_task_new(struct task_struct * t, int on_rq, int running)
515 if (running) { 521 if (running) {
516 entry = &per_cpu(gsnedf_cpu_entries, task_cpu(t)); 522 entry = &per_cpu(gsnedf_cpu_entries, task_cpu(t));
517 BUG_ON(entry->scheduled); 523 BUG_ON(entry->scheduled);
518 entry->scheduled = t; 524
519 tsk_rt(t)->scheduled_on = task_cpu(t); 525 if (entry->cpu != gsnedf.release_master) {
526 entry->scheduled = t;
527 tsk_rt(t)->scheduled_on = task_cpu(t);
528 } else {
529 /* do not schedule on release master */
530 preempt(entry); /* force resched */
531 tsk_rt(t)->scheduled_on = NO_CPU;
532 }
520 } else { 533 } else {
521 t->rt_param.scheduled_on = NO_CPU; 534 t->rt_param.scheduled_on = NO_CPU;
522 } 535 }
@@ -758,6 +771,7 @@ static long gsnedf_activate_plugin(void)
758 cpu_entry_t *entry; 771 cpu_entry_t *entry;
759 772
760 heap_init(&gsnedf_cpu_heap); 773 heap_init(&gsnedf_cpu_heap);
774 gsnedf.release_master = atomic_read(&release_master_cpu);
761 775
762 for_each_online_cpu(cpu) { 776 for_each_online_cpu(cpu) {
763 entry = &per_cpu(gsnedf_cpu_entries, cpu); 777 entry = &per_cpu(gsnedf_cpu_entries, cpu);
@@ -765,8 +779,12 @@ static long gsnedf_activate_plugin(void)
765 atomic_set(&entry->will_schedule, 0); 779 atomic_set(&entry->will_schedule, 0);
766 entry->linked = NULL; 780 entry->linked = NULL;
767 entry->scheduled = NULL; 781 entry->scheduled = NULL;
768 TRACE("GSN-EDF: Initializing CPU #%d.\n", cpu); 782 if (cpu != gsnedf.release_master) {
769 update_cpu_position(entry); 783 TRACE("GSN-EDF: Initializing CPU #%d.\n", cpu);
784 update_cpu_position(entry);
785 } else {
786 TRACE("GSN-EDF: CPU %d is release master.\n", cpu);
787 }
770 } 788 }
771 return 0; 789 return 0;
772} 790}