diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-05-30 19:46:21 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-06-01 10:23:13 -0400 |
commit | cedc8df1cf1ff935af5455a9d565dac05192a47f (patch) | |
tree | 04771859bf08ff847894af6107e4b799a7a00cea | |
parent | 5b54b24c13b7c5dbaa06eae5e1a0075da354289c (diff) |
Make release master support optional
Introduces CONFIG_RELEASE_MASTER and makes release
master support dependent on the new symbol. This is
useful because dedicated interrupt handling only applies
to "large" multicore platforms. This will allow us to
not implement smp_send_pull_timers() for all platforms.
-rw-r--r-- | include/litmus/litmus.h | 2 | ||||
-rw-r--r-- | include/litmus/rt_domain.h | 6 | ||||
-rw-r--r-- | litmus/Kconfig | 12 | ||||
-rw-r--r-- | litmus/litmus.c | 14 | ||||
-rw-r--r-- | litmus/rt_domain.c | 8 | ||||
-rw-r--r-- | litmus/sched_gsn_edf.c | 12 |
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 | ||
12 | extern atomic_t release_master_cpu; | 13 | extern atomic_t release_master_cpu; |
14 | #endif | ||
13 | 15 | ||
14 | extern atomic_t __log_seq_no; | 16 | extern 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 @@ | |||
1 | menu "LITMUS^RT" | 1 | menu "LITMUS^RT" |
2 | 2 | ||
3 | menu "Plugins" | 3 | menu "Scheduling" |
4 | 4 | ||
5 | config PLUGIN_CEDF | 5 | config 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 | ||
14 | config 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 | |||
14 | endmenu | 24 | endmenu |
15 | 25 | ||
16 | menu "Real-Time Synchronization" | 26 | menu "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. */ |
31 | atomic_t __log_seq_no = ATOMIC_INIT(0); | 31 | atomic_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 */ |
34 | atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU); | 35 | atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU); |
36 | #endif | ||
35 | 37 | ||
36 | static struct kmem_cache * bheap_node_cache; | 38 | static struct kmem_cache * bheap_node_cache; |
37 | extern struct kmem_cache * release_heap_cache; | 39 | extern 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 | ||
630 | static int proc_read_release_master(char *page, char **start, | 633 | static 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 | ||
680 | static struct proc_dir_entry *litmus_dir = NULL, | 684 | static 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 | ||
687 | static int __init init_litmus_proc(void) | 693 | static 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 | } |