aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/litmus.h2
-rw-r--r--include/litmus/rt_domain.h6
-rw-r--r--litmus/Kconfig12
-rw-r--r--litmus/litmus.c14
-rw-r--r--litmus/rt_domain.c8
-rw-r--r--litmus/sched_gsn_edf.c12
6 files changed, 51 insertions, 3 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index d515d1af1096..674528eece14 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -9,7 +9,9 @@
9#include <linux/jiffies.h> 9#include <linux/jiffies.h>
10#include <litmus/sched_trace.h> 10#include <litmus/sched_trace.h>
11 11
12#ifdef CONFIG_RELEASE_MASTER
12extern atomic_t release_master_cpu; 13extern atomic_t release_master_cpu;
14#endif
13 15
14extern atomic_t __log_seq_no; 16extern atomic_t __log_seq_no;
15 17
diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h
index 9bf980713474..59e6b54e9281 100644
--- a/include/litmus/rt_domain.h
+++ b/include/litmus/rt_domain.h
@@ -28,7 +28,10 @@ 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 raw_spinlock_t release_lock; 29 raw_spinlock_t release_lock;
30 struct release_queue release_queue; 30 struct release_queue release_queue;
31
32#ifdef CONFIG_RELEASE_MASTER
31 int release_master; 33 int release_master;
34#endif
32 35
33 /* for moving tasks to the release queue */ 36 /* for moving tasks to the release queue */
34 raw_spinlock_t tobe_lock; 37 raw_spinlock_t tobe_lock;
@@ -52,8 +55,11 @@ struct release_heap {
52 struct bheap heap; 55 struct bheap heap;
53 /* used to trigger the release */ 56 /* used to trigger the release */
54 struct hrtimer timer; 57 struct hrtimer timer;
58
59#ifdef CONFIG_RELEASE_MASTER
55 /* used to delegate releases */ 60 /* used to delegate releases */
56 struct hrtimer_start_on_info info; 61 struct hrtimer_start_on_info info;
62#endif
57 /* required for the timer callback */ 63 /* required for the timer callback */
58 rt_domain_t* dom; 64 rt_domain_t* dom;
59}; 65};
diff --git a/litmus/Kconfig b/litmus/Kconfig
index cc49e1a7f9c7..614e1051fa49 100644
--- a/litmus/Kconfig
+++ b/litmus/Kconfig
@@ -1,6 +1,6 @@
1menu "LITMUS^RT" 1menu "LITMUS^RT"
2 2
3menu "Plugins" 3menu "Scheduling"
4 4
5config PLUGIN_CEDF 5config PLUGIN_CEDF
6 bool "Clustered-EDF" 6 bool "Clustered-EDF"
@@ -11,6 +11,16 @@ config PLUGIN_CEDF
11 On smaller platforms (e.g., ARM PB11MPCore), using C-EDF 11 On smaller platforms (e.g., ARM PB11MPCore), using C-EDF
12 makes little sense since there aren't any shared caches. 12 makes little sense since there aren't any shared caches.
13 13
14config RELEASE_MASTER
15 bool "Release-master Support"
16 default n
17 help
18 Allow one processor to act as a dedicated interrupt processor
19 that services all timer interrupts, but that does not schedule
20 real-time tasks. See RTSS'09 paper for details
21 (http://www.cs.unc.edu/~anderson/papers.html).
22 Currently only supported by GSN-EDF.
23
14endmenu 24endmenu
15 25
16menu "Real-Time Synchronization" 26menu "Real-Time Synchronization"
diff --git a/litmus/litmus.c b/litmus/litmus.c
index b71fc819eb51..c60423228607 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -30,8 +30,10 @@ atomic_t cannot_use_plugin = ATOMIC_INIT(0);
30/* Give log messages sequential IDs. */ 30/* Give log messages sequential IDs. */
31atomic_t __log_seq_no = ATOMIC_INIT(0); 31atomic_t __log_seq_no = ATOMIC_INIT(0);
32 32
33#ifdef CONFIG_RELEASE_MASTER
33/* current master CPU for handling timer IRQs */ 34/* current master CPU for handling timer IRQs */
34atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU); 35atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU);
36#endif
35 37
36static struct kmem_cache * bheap_node_cache; 38static struct kmem_cache * bheap_node_cache;
37extern struct kmem_cache * release_heap_cache; 39extern struct kmem_cache * release_heap_cache;
@@ -627,6 +629,7 @@ static int proc_write_cluster_size(struct file *file,
627 return len; 629 return len;
628} 630}
629 631
632#ifdef CONFIG_RELEASE_MASTER
630static int proc_read_release_master(char *page, char **start, 633static int proc_read_release_master(char *page, char **start,
631 off_t off, int count, 634 off_t off, int count,
632 int *eof, void *data) 635 int *eof, void *data)
@@ -676,13 +679,16 @@ static int proc_write_release_master(struct file *file,
676 } 679 }
677 } 680 }
678} 681}
682#endif
679 683
680static struct proc_dir_entry *litmus_dir = NULL, 684static struct proc_dir_entry *litmus_dir = NULL,
681 *curr_file = NULL, 685 *curr_file = NULL,
682 *stat_file = NULL, 686 *stat_file = NULL,
683 *plugs_file = NULL, 687 *plugs_file = NULL,
684 *clus_cache_idx_file = NULL, 688#ifdef CONFIG_RELEASE_MASTER
685 *release_master_file = NULL; 689 *release_master_file = NULL,
690#endif
691 *clus_cache_idx_file = NULL;
686 692
687static int __init init_litmus_proc(void) 693static int __init init_litmus_proc(void)
688{ 694{
@@ -702,6 +708,7 @@ static int __init init_litmus_proc(void)
702 curr_file->read_proc = proc_read_curr; 708 curr_file->read_proc = proc_read_curr;
703 curr_file->write_proc = proc_write_curr; 709 curr_file->write_proc = proc_write_curr;
704 710
711#ifdef CONFIG_RELEASE_MASTER
705 release_master_file = create_proc_entry("release_master", 712 release_master_file = create_proc_entry("release_master",
706 0644, litmus_dir); 713 0644, litmus_dir);
707 if (!release_master_file) { 714 if (!release_master_file) {
@@ -711,6 +718,7 @@ static int __init init_litmus_proc(void)
711 } 718 }
712 release_master_file->read_proc = proc_read_release_master; 719 release_master_file->read_proc = proc_read_release_master;
713 release_master_file->write_proc = proc_write_release_master; 720 release_master_file->write_proc = proc_write_release_master;
721#endif
714 722
715 clus_cache_idx_file = create_proc_entry("cluster_cache", 723 clus_cache_idx_file = create_proc_entry("cluster_cache",
716 0644, litmus_dir); 724 0644, litmus_dir);
@@ -741,8 +749,10 @@ static void exit_litmus_proc(void)
741 remove_proc_entry("active_plugin", litmus_dir); 749 remove_proc_entry("active_plugin", litmus_dir);
742 if (clus_cache_idx_file) 750 if (clus_cache_idx_file)
743 remove_proc_entry("cluster_cache", litmus_dir); 751 remove_proc_entry("cluster_cache", litmus_dir);
752#ifdef CONFIG_RELEASE_MASTER
744 if (release_master_file) 753 if (release_master_file)
745 remove_proc_entry("release_master", litmus_dir); 754 remove_proc_entry("release_master", litmus_dir);
755#endif
746 if (litmus_dir) 756 if (litmus_dir)
747 remove_proc_entry("litmus", NULL); 757 remove_proc_entry("litmus", NULL);
748} 758}
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c
index 8d5db6050723..26f1cc48f865 100644
--- a/litmus/rt_domain.c
+++ b/litmus/rt_domain.c
@@ -158,7 +158,9 @@ static void reinit_release_heap(struct task_struct* t)
158 158
159 /* initialize */ 159 /* initialize */
160 bheap_init(&rh->heap); 160 bheap_init(&rh->heap);
161#ifdef __ARCH_HAS_SEND_PULL_TIMERS
161 atomic_set(&rh->info.state, HRTIMER_START_ON_INACTIVE); 162 atomic_set(&rh->info.state, HRTIMER_START_ON_INACTIVE);
163#endif
162} 164}
163/* arm_release_timer() - start local release timer or trigger 165/* arm_release_timer() - start local release timer or trigger
164 * remote timer (pull timer) 166 * remote timer (pull timer)
@@ -221,15 +223,19 @@ static void arm_release_timer(rt_domain_t *_rt)
221 * 223 *
222 * PINNED mode is ok on both local and remote CPU 224 * PINNED mode is ok on both local and remote CPU
223 */ 225 */
226#ifdef CONFIG_RELEASE_MASTER
224 if (rt->release_master == NO_CPU) 227 if (rt->release_master == NO_CPU)
228#endif
225 __hrtimer_start_range_ns(&rh->timer, 229 __hrtimer_start_range_ns(&rh->timer,
226 ns_to_ktime(rh->release_time), 230 ns_to_ktime(rh->release_time),
227 0, HRTIMER_MODE_ABS_PINNED, 0); 231 0, HRTIMER_MODE_ABS_PINNED, 0);
232#ifdef CONFIG_RELEASE_MASTER
228 else 233 else
229 hrtimer_start_on(rt->release_master, 234 hrtimer_start_on(rt->release_master,
230 &rh->info, &rh->timer, 235 &rh->info, &rh->timer,
231 ns_to_ktime(rh->release_time), 236 ns_to_ktime(rh->release_time),
232 HRTIMER_MODE_ABS_PINNED); 237 HRTIMER_MODE_ABS_PINNED);
238#endif
233 } else 239 } else
234 TRACE_TASK(t, "0x%p is not my timer\n", &rh->timer); 240 TRACE_TASK(t, "0x%p is not my timer\n", &rh->timer);
235 } 241 }
@@ -251,7 +257,9 @@ void rt_domain_init(rt_domain_t *rt,
251 if (!order) 257 if (!order)
252 order = dummy_order; 258 order = dummy_order;
253 259
260#ifdef CONFIG_RELEASE_MASTER
254 rt->release_master = NO_CPU; 261 rt->release_master = NO_CPU;
262#endif
255 263
256 bheap_init(&rt->ready_queue); 264 bheap_init(&rt->ready_queue);
257 INIT_LIST_HEAD(&rt->tobe_released); 265 INIT_LIST_HEAD(&rt->tobe_released);
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index c0c63eba70ce..e101768740ad 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -382,11 +382,13 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev)
382 int out_of_time, sleep, preempt, np, exists, blocks; 382 int out_of_time, sleep, preempt, np, exists, blocks;
383 struct task_struct* next = NULL; 383 struct task_struct* next = NULL;
384 384
385#ifdef CONFIG_RELEASE_MASTER
385 /* Bail out early if we are the release master. 386 /* Bail out early if we are the release master.
386 * The release master never schedules any real-time tasks. 387 * The release master never schedules any real-time tasks.
387 */ 388 */
388 if (gsnedf.release_master == entry->cpu) 389 if (gsnedf.release_master == entry->cpu)
389 return NULL; 390 return NULL;
391#endif
390 392
391 raw_spin_lock(&gsnedf_lock); 393 raw_spin_lock(&gsnedf_lock);
392 clear_will_schedule(); 394 clear_will_schedule();
@@ -518,14 +520,18 @@ static void gsnedf_task_new(struct task_struct * t, int on_rq, int running)
518 entry = &per_cpu(gsnedf_cpu_entries, task_cpu(t)); 520 entry = &per_cpu(gsnedf_cpu_entries, task_cpu(t));
519 BUG_ON(entry->scheduled); 521 BUG_ON(entry->scheduled);
520 522
523#ifdef CONFIG_RELEASE_MASTER
521 if (entry->cpu != gsnedf.release_master) { 524 if (entry->cpu != gsnedf.release_master) {
525#endif
522 entry->scheduled = t; 526 entry->scheduled = t;
523 tsk_rt(t)->scheduled_on = task_cpu(t); 527 tsk_rt(t)->scheduled_on = task_cpu(t);
528#ifdef CONFIG_RELEASE_MASTER
524 } else { 529 } else {
525 /* do not schedule on release master */ 530 /* do not schedule on release master */
526 preempt(entry); /* force resched */ 531 preempt(entry); /* force resched */
527 tsk_rt(t)->scheduled_on = NO_CPU; 532 tsk_rt(t)->scheduled_on = NO_CPU;
528 } 533 }
534#endif
529 } else { 535 } else {
530 t->rt_param.scheduled_on = NO_CPU; 536 t->rt_param.scheduled_on = NO_CPU;
531 } 537 }
@@ -767,7 +773,9 @@ static long gsnedf_activate_plugin(void)
767 cpu_entry_t *entry; 773 cpu_entry_t *entry;
768 774
769 bheap_init(&gsnedf_cpu_heap); 775 bheap_init(&gsnedf_cpu_heap);
776#ifdef CONFIG_RELEASE_MASTER
770 gsnedf.release_master = atomic_read(&release_master_cpu); 777 gsnedf.release_master = atomic_read(&release_master_cpu);
778#endif
771 779
772 for_each_online_cpu(cpu) { 780 for_each_online_cpu(cpu) {
773 entry = &per_cpu(gsnedf_cpu_entries, cpu); 781 entry = &per_cpu(gsnedf_cpu_entries, cpu);
@@ -775,12 +783,16 @@ static long gsnedf_activate_plugin(void)
775 atomic_set(&entry->will_schedule, 0); 783 atomic_set(&entry->will_schedule, 0);
776 entry->linked = NULL; 784 entry->linked = NULL;
777 entry->scheduled = NULL; 785 entry->scheduled = NULL;
786#ifdef CONFIG_RELEASE_MASTER
778 if (cpu != gsnedf.release_master) { 787 if (cpu != gsnedf.release_master) {
788#endif
779 TRACE("GSN-EDF: Initializing CPU #%d.\n", cpu); 789 TRACE("GSN-EDF: Initializing CPU #%d.\n", cpu);
780 update_cpu_position(entry); 790 update_cpu_position(entry);
791#ifdef CONFIG_RELEASE_MASTER
781 } else { 792 } else {
782 TRACE("GSN-EDF: CPU %d is release master.\n", cpu); 793 TRACE("GSN-EDF: CPU %d is release master.\n", cpu);
783 } 794 }
795#endif
784 } 796 }
785 return 0; 797 return 0;
786} 798}