aboutsummaryrefslogtreecommitdiffstats
path: root/litmus
diff options
context:
space:
mode:
Diffstat (limited to 'litmus')
-rw-r--r--litmus/event_group.c8
-rw-r--r--litmus/litmus.c3
-rw-r--r--litmus/rt_domain.c10
-rw-r--r--litmus/sched_mc.c22
-rw-r--r--litmus/sched_mc_ce.c41
5 files changed, 61 insertions, 23 deletions
diff --git a/litmus/event_group.c b/litmus/event_group.c
index 3b50e15bd354..a130a68c731a 100644
--- a/litmus/event_group.c
+++ b/litmus/event_group.c
@@ -30,7 +30,7 @@ static unsigned int time2slot(lt_t time)
30static enum hrtimer_restart on_timer(struct hrtimer *timer) 30static enum hrtimer_restart on_timer(struct hrtimer *timer)
31{ 31{
32 unsigned long flags; 32 unsigned long flags;
33 int num = 0; 33 unsigned long num = 0;
34 struct event_list *el; 34 struct event_list *el;
35 struct rt_event *e; 35 struct rt_event *e;
36 struct list_head *pos, *safe, list; 36 struct list_head *pos, *safe, list;
@@ -50,7 +50,7 @@ static enum hrtimer_restart on_timer(struct hrtimer *timer)
50 list_for_each_safe(pos, safe, &list) { 50 list_for_each_safe(pos, safe, &list) {
51 num++; 51 num++;
52 e = list_entry(pos, struct rt_event, list); 52 e = list_entry(pos, struct rt_event, list);
53 TRACE("Dequeueing event 0x%p with prio %d from 0x%p\n", 53 VTRACE("Dequeueing event 0x%p with prio %d from 0x%p\n",
54 e, e->prio, el); 54 e, e->prio, el);
55 list_del_init(pos); 55 list_del_init(pos);
56 e->function(e); 56 e->function(e);
@@ -238,7 +238,7 @@ void cancel_event(struct rt_event *e)
238 } 238 }
239} 239}
240 240
241struct kmem_cache *event_list_cache, *event_cache; 241struct kmem_cache *event_list_cache;
242 242
243struct event_list* event_list_alloc(int gfp_flags) 243struct event_list* event_list_alloc(int gfp_flags)
244{ 244{
@@ -249,6 +249,8 @@ struct event_list* event_list_alloc(int gfp_flags)
249 el->timer.function = on_timer; 249 el->timer.function = on_timer;
250 } else { 250 } else {
251 VTRACE("Failed to allocate event list!"); 251 VTRACE("Failed to allocate event list!");
252 printk(KERN_CRIT "Failed to allocate event list.\n");
253 BUG();
252 } 254 }
253 return el; 255 return el;
254} 256}
diff --git a/litmus/litmus.c b/litmus/litmus.c
index deaaee3b3f20..f4d676c17d5f 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -46,6 +46,7 @@ extern struct kmem_cache *release_heap_cache;
46#ifdef CONFIG_MERGE_TIMERS 46#ifdef CONFIG_MERGE_TIMERS
47extern struct kmem_cache *event_list_cache; 47extern struct kmem_cache *event_list_cache;
48#endif 48#endif
49
49#ifdef CONFIG_PLUGIN_MC 50#ifdef CONFIG_PLUGIN_MC
50static struct kmem_cache *mc_data_cache; 51static struct kmem_cache *mc_data_cache;
51#endif 52#endif
@@ -574,7 +575,7 @@ void exit_litmus(struct task_struct *dead_tsk)
574 * Check and free it here. 575 * Check and free it here.
575 */ 576 */
576 if (tsk_rt(dead_tsk)->mc_data) 577 if (tsk_rt(dead_tsk)->mc_data)
577 kfree(tsk_rt(dead_tsk)->mc_data); 578 kmem_cache_free(mc_data_cache, tsk_rt(dead_tsk)->mc_data);
578#endif 579#endif
579 580
580 /* main cleanup only for RT tasks */ 581 /* main cleanup only for RT tasks */
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c
index fbd91c829619..ffb3cab9cffd 100644
--- a/litmus/rt_domain.c
+++ b/litmus/rt_domain.c
@@ -100,12 +100,18 @@ struct release_heap* release_heap_alloc(int gfp_flags)
100 return rh; 100 return rh;
101} 101}
102 102
103#ifdef CONFIG_MERGE_TIMERS
104extern struct kmem_cache *event_list_cache;
105#endif
106
103void release_heap_free(struct release_heap* rh) 107void release_heap_free(struct release_heap* rh)
104{ 108{
105 /* make sure timer is no longer in use */ 109 /* make sure timer is no longer in use */
106#ifdef CONFIG_MERGE_TIMERS 110#ifdef CONFIG_MERGE_TIMERS
107 /* if (rh->dom) */ 111 if (rh->dom) {
108 /* cancel_event(&rh->event); */ 112 cancel_event(&rh->event);
113 kmem_cache_free(event_list_cache, rh->event.event_list);
114 }
109#else 115#else
110 hrtimer_cancel(&rh->timer); 116 hrtimer_cancel(&rh->timer);
111#endif 117#endif
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c
index 17f84c9eba79..e20e97810847 100644
--- a/litmus/sched_mc.c
+++ b/litmus/sched_mc.c
@@ -27,8 +27,6 @@
27#include <litmus/sched_mc.h> 27#include <litmus/sched_mc.h>
28#include <litmus/ce_domain.h> 28#include <litmus/ce_domain.h>
29 29
30/* XXX TODO Do we ever want to move level-A timers? */
31
32/** 30/**
33 * struct cpu_entry - State of a CPU for the entire MC system 31 * struct cpu_entry - State of a CPU for the entire MC system
34 * @cpu CPU id 32 * @cpu CPU id
@@ -50,6 +48,9 @@ struct cpu_entry {
50 struct list_head redir; 48 struct list_head redir;
51 raw_spinlock_t redir_lock; 49 raw_spinlock_t redir_lock;
52#endif 50#endif
51#ifdef CONFIG_MERGE_TIMERS
52 struct event_group *event_group;
53#endif
53}; 54};
54 55
55DEFINE_PER_CPU(struct cpu_entry, cpus); 56DEFINE_PER_CPU(struct cpu_entry, cpus);
@@ -141,7 +142,7 @@ static inline void cancel_ghost(struct crit_entry *ce)
141static inline void arm_ghost(struct crit_entry *ce, lt_t fire) 142static inline void arm_ghost(struct crit_entry *ce, lt_t fire)
142{ 143{
143#ifdef CONFIG_MERGE_TIMERS 144#ifdef CONFIG_MERGE_TIMERS
144 add_event(get_event_group_for(crit_cpu(ce)->cpu), &ce->event, fire); 145 add_event(crit_cpu(ce)->event_group, &ce->event, fire);
145#else 146#else
146 __hrtimer_start_range_ns(&ce->timer, 147 __hrtimer_start_range_ns(&ce->timer,
147 ns_to_ktime(fire), 148 ns_to_ktime(fire),
@@ -298,7 +299,7 @@ static void fix_global_levels(void)
298 struct list_head *pos, *safe; 299 struct list_head *pos, *safe;
299 struct task_struct *t; 300 struct task_struct *t;
300 301
301 STRACE("Fixing global levels"); 302 STRACE("Fixing global levels\n");
302 for_each_online_cpu(c) { 303 for_each_online_cpu(c) {
303 e = &per_cpu(cpus, c); 304 e = &per_cpu(cpus, c);
304 raw_spin_lock(&e->redir_lock); 305 raw_spin_lock(&e->redir_lock);
@@ -621,13 +622,12 @@ static void ce_timer_function(struct rt_event *e)
621{ 622{
622 struct ce_dom_data *ce_data = 623 struct ce_dom_data *ce_data =
623 container_of(e, struct ce_dom_data, event); 624 container_of(e, struct ce_dom_data, event);
624 struct event_group *event_group = get_event_group_for(ce_data->cpu);
625 unsigned long flags; 625 unsigned long flags;
626 lt_t next_timer_abs; 626 lt_t next_timer_abs;
627 627
628 local_irq_save(flags); 628 local_irq_save(flags);
629 next_timer_abs = __ce_timer_function(ce_data); 629 next_timer_abs = __ce_timer_function(ce_data);
630 add_event(event_group, e, next_timer_abs); 630 add_event(per_cpu(cpus, ce_data->cpu).event_group, e, next_timer_abs);
631 local_irq_restore(flags); 631 local_irq_restore(flags);
632} 632}
633#else /* else to CONFIG_MERGE_TIMERS */ 633#else /* else to CONFIG_MERGE_TIMERS */
@@ -945,13 +945,13 @@ static long mc_activate_plugin(void)
945 struct domain_data *dom_data; 945 struct domain_data *dom_data;
946 struct domain *dom; 946 struct domain *dom;
947 struct domain_data *our_domains[NR_CPUS]; 947 struct domain_data *our_domains[NR_CPUS];
948 struct event_group *event_group;
948 int cpu, n = 0; 949 int cpu, n = 0;
949 long ret; 950 long ret;
950 951
951#ifdef CONFIG_RELEASE_MASTER 952#ifdef CONFIG_RELEASE_MASTER
952 interrupt_cpu = atomic_read(&release_master_cpu); 953 interrupt_cpu = atomic_read(&release_master_cpu);
953#if defined(CONFIG_PLUGIN_MC_REDIRECT) || \ 954#if defined(CONFIG_PLUGIN_MC_REDIRECT) || defined(CONFIG_PLUGIN_MC_RELEASE_MASTER)
954 (defined(CONFIG_PLUGIN_MC_RELEASE_MASTER) && defined(CONFIG_MERGE_TIMERS))
955 if (NO_CPU == interrupt_cpu) { 955 if (NO_CPU == interrupt_cpu) {
956 printk(KERN_ERR "LITMUS-MC: need a release master\n"); 956 printk(KERN_ERR "LITMUS-MC: need a release master\n");
957 ret = -EINVAL; 957 ret = -EINVAL;
@@ -965,6 +965,12 @@ static long mc_activate_plugin(void)
965 dom = per_cpu(cpus, cpu).crit_entries[CRIT_LEVEL_A].domain; 965 dom = per_cpu(cpus, cpu).crit_entries[CRIT_LEVEL_A].domain;
966 dom_data = domain_data(dom); 966 dom_data = domain_data(dom);
967 our_domains[cpu] = dom_data; 967 our_domains[cpu] = dom_data;
968#if defined(CONFIG_MERGE_TIMERS) && defined(CONFIG_PLUGIN_MC_RELEASE_MASTER)
969 event_group = get_event_group_for(interrupt_cpu);
970#elif defined(CONFIG_MERGE_TIMERS) && !defined(CONFIG_PLUGIN_MC_RELEASE_MASTER)
971 event_group = get_event_group_for(cpu);
972#endif
973 per_cpu(cpus, cpu).event_group = event_group;
968 n++; 974 n++;
969 } 975 }
970 ret = mc_ce_set_domains(n, our_domains); 976 ret = mc_ce_set_domains(n, our_domains);
diff --git a/litmus/sched_mc_ce.c b/litmus/sched_mc_ce.c
index c5066918f282..5125df9572ba 100644
--- a/litmus/sched_mc_ce.c
+++ b/litmus/sched_mc_ce.c
@@ -79,6 +79,10 @@ DEFINE_PER_CPU(struct domain_data, _mc_ce_doms);
79DEFINE_PER_CPU(struct ce_dom_data, _mc_ce_dom_data); 79DEFINE_PER_CPU(struct ce_dom_data, _mc_ce_dom_data);
80DEFINE_PER_CPU(raw_spinlock_t, _mc_ce_dom_locks); 80DEFINE_PER_CPU(raw_spinlock_t, _mc_ce_dom_locks);
81 81
82#ifdef CONFIG_PLUGIN_MC_RELEASE_MASTER
83static int interrupt_cpu;
84#endif
85
82long mc_ce_set_domains(const int n, struct domain_data *domains_in[]) 86long mc_ce_set_domains(const int n, struct domain_data *domains_in[])
83{ 87{
84 const int max = (NR_CPUS < n) ? NR_CPUS : n; 88 const int max = (NR_CPUS < n) ? NR_CPUS : n;
@@ -520,8 +524,9 @@ static enum hrtimer_restart mc_ce_timer_callback(struct hrtimer *timer)
520#ifdef CONFIG_MERGE_TIMERS 524#ifdef CONFIG_MERGE_TIMERS
521 struct event_group *event_group; 525 struct event_group *event_group;
522 ce_data = container_of(e, struct ce_dom_data, event); 526 ce_data = container_of(e, struct ce_dom_data, event);
523 event_group = get_event_group_for(ce_data->cpu); 527 /* use the same CPU the callbacking is executing on by passing NO_CPU */
524#else 528 event_group = get_event_group_for(NO_CPU);
529#else /* CONFIG_MERGE_TIMERS */
525 ce_data = container_of(timer, struct ce_dom_data, timer); 530 ce_data = container_of(timer, struct ce_dom_data, timer);
526#endif 531#endif
527 dom = get_domain_for(ce_data->cpu); 532 dom = get_domain_for(ce_data->cpu);
@@ -588,7 +593,7 @@ static void arm_all_timers(void)
588 struct domain *dom; 593 struct domain *dom;
589 struct ce_dom_data *ce_data; 594 struct ce_dom_data *ce_data;
590 struct ce_pid_table *pid_table; 595 struct ce_pid_table *pid_table;
591 int cpu, idx; 596 int cpu, idx, cpu_for_timer;
592 const lt_t start = atomic64_read(&start_time); 597 const lt_t start = atomic64_read(&start_time);
593 598
594 TRACE("arm all timers\n"); 599 TRACE("arm all timers\n");
@@ -602,13 +607,19 @@ static void arm_all_timers(void)
602 for (idx = 0; idx < pid_table->num_pid_entries; idx++) { 607 for (idx = 0; idx < pid_table->num_pid_entries; idx++) {
603 pid_table->entries[idx].expected_job = 0; 608 pid_table->entries[idx].expected_job = 0;
604 } 609 }
610#ifdef CONFIG_PLUGIN_MC_RELEASE_MASTER
611 cpu_for_timer = interrupt_cpu;
612#else
613 cpu_for_timer = cpu;
614#endif
615
605#ifdef CONFIG_MERGE_TIMERS 616#ifdef CONFIG_MERGE_TIMERS
606 TRACE("adding event for CPU %d\n", cpu); 617 add_event(get_event_group_for(cpu_for_timer),
607 add_event(get_event_group_for(cpu), &ce_data->event, start); 618 &ce_data->event, start);
608#else 619#else
609 TRACE("arming timer for CPU %d\n", cpu); 620 hrtimer_start_on(cpu_for_timer, &ce_data->timer_info,
610 hrtimer_start_on(cpu, &ce_data->timer_info, &ce_data->timer, 621 &ce_data->timer, ns_to_ktime(start),
611 ns_to_ktime(start), HRTIMER_MODE_ABS_PINNED); 622 HRTIMER_MODE_ABS_PINNED);
612#endif 623#endif
613 } 624 }
614} 625}
@@ -634,8 +645,18 @@ long mc_ce_activate_plugin_common(void)
634{ 645{
635 struct ce_dom_data *ce_data; 646 struct ce_dom_data *ce_data;
636 struct domain *dom; 647 struct domain *dom;
648 long ret;
637 int cpu; 649 int cpu;
638 650
651#ifdef CONFIG_PLUGIN_MC_RELEASE_MASTER
652 interrupt_cpu = atomic_read(&release_master_cpu);
653 if (NO_CPU == interrupt_cpu) {
654 printk(KERN_ERR "LITMUS: MC-CE needs a release master\n");
655 ret = -EINVAL;
656 goto out;
657 }
658#endif
659
639 for_each_online_cpu(cpu) { 660 for_each_online_cpu(cpu) {
640 dom = get_domain_for(cpu); 661 dom = get_domain_for(cpu);
641 ce_data = dom->data; 662 ce_data = dom->data;
@@ -647,7 +668,9 @@ long mc_ce_activate_plugin_common(void)
647 atomic64_set(&start_time, litmus_clock()); 668 atomic64_set(&start_time, litmus_clock());
648 /* may not want to arm timers on activation, just after release */ 669 /* may not want to arm timers on activation, just after release */
649 arm_all_timers(); 670 arm_all_timers();
650 return 0; 671 ret = 0;
672out:
673 return ret;
651} 674}
652 675
653static long mc_ce_activate_plugin(void) 676static long mc_ce_activate_plugin(void)