diff options
Diffstat (limited to 'litmus')
-rw-r--r-- | litmus/event_group.c | 8 | ||||
-rw-r--r-- | litmus/litmus.c | 3 | ||||
-rw-r--r-- | litmus/rt_domain.c | 10 | ||||
-rw-r--r-- | litmus/sched_mc.c | 22 | ||||
-rw-r--r-- | litmus/sched_mc_ce.c | 41 |
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) | |||
30 | static enum hrtimer_restart on_timer(struct hrtimer *timer) | 30 | static 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 | ||
241 | struct kmem_cache *event_list_cache, *event_cache; | 241 | struct kmem_cache *event_list_cache; |
242 | 242 | ||
243 | struct event_list* event_list_alloc(int gfp_flags) | 243 | struct 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 |
47 | extern struct kmem_cache *event_list_cache; | 47 | extern struct kmem_cache *event_list_cache; |
48 | #endif | 48 | #endif |
49 | |||
49 | #ifdef CONFIG_PLUGIN_MC | 50 | #ifdef CONFIG_PLUGIN_MC |
50 | static struct kmem_cache *mc_data_cache; | 51 | static 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 | ||
104 | extern struct kmem_cache *event_list_cache; | ||
105 | #endif | ||
106 | |||
103 | void release_heap_free(struct release_heap* rh) | 107 | void 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 | ||
55 | DEFINE_PER_CPU(struct cpu_entry, cpus); | 56 | DEFINE_PER_CPU(struct cpu_entry, cpus); |
@@ -141,7 +142,7 @@ static inline void cancel_ghost(struct crit_entry *ce) | |||
141 | static inline void arm_ghost(struct crit_entry *ce, lt_t fire) | 142 | static 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); | |||
79 | DEFINE_PER_CPU(struct ce_dom_data, _mc_ce_dom_data); | 79 | DEFINE_PER_CPU(struct ce_dom_data, _mc_ce_dom_data); |
80 | DEFINE_PER_CPU(raw_spinlock_t, _mc_ce_dom_locks); | 80 | DEFINE_PER_CPU(raw_spinlock_t, _mc_ce_dom_locks); |
81 | 81 | ||
82 | #ifdef CONFIG_PLUGIN_MC_RELEASE_MASTER | ||
83 | static int interrupt_cpu; | ||
84 | #endif | ||
85 | |||
82 | long mc_ce_set_domains(const int n, struct domain_data *domains_in[]) | 86 | long 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; |
672 | out: | ||
673 | return ret; | ||
651 | } | 674 | } |
652 | 675 | ||
653 | static long mc_ce_activate_plugin(void) | 676 | static long mc_ce_activate_plugin(void) |