diff options
Diffstat (limited to 'litmus/sched_mc.c')
-rw-r--r-- | litmus/sched_mc.c | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c index 577e7d36faf5..bce25bc8822e 100644 --- a/litmus/sched_mc.c +++ b/litmus/sched_mc.c | |||
@@ -24,25 +24,7 @@ | |||
24 | #include <litmus/bheap.h> | 24 | #include <litmus/bheap.h> |
25 | 25 | ||
26 | #include <litmus/sched_mc.h> | 26 | #include <litmus/sched_mc.h> |
27 | 27 | #include <litmus/ce_domain.h> | |
28 | /** | ||
29 | * crit_entry_t - State of a CPU within each criticality level system. | ||
30 | * @level Criticality level of this entry | ||
31 | * @linked Logically running task, ghost or regular | ||
32 | * @domain Domain from which to draw tasks | ||
33 | * @usable False if a higher criticality task is running | ||
34 | * @timer For ghost task budget enforcement | ||
35 | * @node Used to sort crit_entries by preemptability in global domains | ||
36 | */ | ||
37 | typedef struct { | ||
38 | enum crit_level level; | ||
39 | struct task_struct* linked; | ||
40 | domain_t* domain; | ||
41 | int usable; | ||
42 | struct hrtimer timer; | ||
43 | struct bheap_node* node; | ||
44 | atomic_t dirty; | ||
45 | } crit_entry_t; | ||
46 | 28 | ||
47 | /** | 29 | /** |
48 | * cpu_entry_t - State of a CPU for the entire MC system | 30 | * cpu_entry_t - State of a CPU for the entire MC system |
@@ -64,18 +46,6 @@ typedef struct { | |||
64 | #endif | 46 | #endif |
65 | } cpu_entry_t; | 47 | } cpu_entry_t; |
66 | 48 | ||
67 | /** | ||
68 | * domain_data_t - Wrap domains with related CPU state | ||
69 | * @domain A domain for a criticality level | ||
70 | * @heap The preemptable heap of crit entries (for global domains) | ||
71 | * @crit_entry The crit entry for this domain (for partitioned domains) | ||
72 | */ | ||
73 | typedef struct { | ||
74 | domain_t domain; | ||
75 | struct bheap* heap; | ||
76 | crit_entry_t* crit_entry; | ||
77 | } domain_data_t; | ||
78 | |||
79 | static cpu_entry_t* cpus[NR_CPUS]; | 49 | static cpu_entry_t* cpus[NR_CPUS]; |
80 | #ifdef CONFIG_RELEASE_MASTER | 50 | #ifdef CONFIG_RELEASE_MASTER |
81 | static int interrupt_cpu; | 51 | static int interrupt_cpu; |
@@ -213,10 +183,14 @@ static void link_task_to_crit(crit_entry_t *ce, | |||
213 | ce->linked = task; | 183 | ce->linked = task; |
214 | if (task) { | 184 | if (task) { |
215 | task->rt_param.linked_on = crit_cpu(ce)->cpu; | 185 | task->rt_param.linked_on = crit_cpu(ce)->cpu; |
216 | if (is_ghost(task)) { | 186 | if (is_ghost(task) && CRIT_LEVEL_A != tsk_mc_crit(task)) { |
187 | /* There is a level-A timer that will force a | ||
188 | * preemption, so we don't set this for level-A | ||
189 | * tasks. | ||
190 | */ | ||
217 | /* Reset budget timer */ | 191 | /* Reset budget timer */ |
218 | task->se.exec_start = litmus_clock(); | 192 | task->se.exec_start = litmus_clock(); |
219 | when_to_fire = litmus_clock() + | 193 | when_to_fire = task->se.exec_start + |
220 | tsk_mc_data(task)->mc_job.ghost_budget; | 194 | tsk_mc_data(task)->mc_job.ghost_budget; |
221 | __hrtimer_start_range_ns(&ce->timer, | 195 | __hrtimer_start_range_ns(&ce->timer, |
222 | ns_to_ktime(when_to_fire), | 196 | ns_to_ktime(when_to_fire), |
@@ -659,6 +633,9 @@ static void mc_task_exit(struct task_struct *task) | |||
659 | tsk_rt(task)->scheduled_on = NO_CPU; | 633 | tsk_rt(task)->scheduled_on = NO_CPU; |
660 | } | 634 | } |
661 | 635 | ||
636 | if (CRIT_LEVEL_A == tsk_mc_crit(task)) | ||
637 | ce_task_exit(get_task_domain(task), task); | ||
638 | |||
662 | local_irq_restore(flags); | 639 | local_irq_restore(flags); |
663 | } | 640 | } |
664 | 641 | ||
@@ -797,7 +774,22 @@ static long mc_activate_plugin(void) | |||
797 | if (interrupt_cpu == NO_CPU) | 774 | if (interrupt_cpu == NO_CPU) |
798 | interrupt_cpu = 0; | 775 | interrupt_cpu = 0; |
799 | #endif | 776 | #endif |
800 | return 0; | 777 | return ce_activate_plugin(); |
778 | } | ||
779 | |||
780 | /* | ||
781 | * This is the plugin's release at function, called by the release task-set | ||
782 | * system call. Other places in the file use the generic LITMUS release_at(), | ||
783 | * which is not this. | ||
784 | */ | ||
785 | void mc_release_at(struct task_struct *ts, lt_t start) | ||
786 | { | ||
787 | ce_start(ts, start); | ||
788 | } | ||
789 | |||
790 | long mc_deactivate_plugin(void) | ||
791 | { | ||
792 | return ce_deactivate_plugin(); | ||
801 | } | 793 | } |
802 | 794 | ||
803 | /* ************************************************************************** | 795 | /* ************************************************************************** |
@@ -820,11 +812,6 @@ static rt_domain_t _mc_crit_c_rt; | |||
820 | struct bheap _mc_heap_c; | 812 | struct bheap _mc_heap_c; |
821 | struct bheap_node _mc_nodes_c[NR_CPUS]; | 813 | struct bheap_node _mc_nodes_c[NR_CPUS]; |
822 | 814 | ||
823 | /* | ||
824 | * XXX commented out because I think this was an obvious typo | ||
825 | */ | ||
826 | /* release_at)_ */ | ||
827 | |||
828 | static struct sched_plugin mc_plugin __cacheline_aligned_in_smp = { | 815 | static struct sched_plugin mc_plugin __cacheline_aligned_in_smp = { |
829 | .plugin_name = "MC", | 816 | .plugin_name = "MC", |
830 | .task_new = mc_task_new, | 817 | .task_new = mc_task_new, |
@@ -835,6 +822,8 @@ static struct sched_plugin mc_plugin __cacheline_aligned_in_smp = { | |||
835 | .task_block = mc_task_block, | 822 | .task_block = mc_task_block, |
836 | .admit_task = mc_admit_task, | 823 | .admit_task = mc_admit_task, |
837 | .activate_plugin = mc_activate_plugin, | 824 | .activate_plugin = mc_activate_plugin, |
825 | .release_at = mc_release_at, | ||
826 | .deactivate_plugin = mc_deactivate_plugin, | ||
838 | }; | 827 | }; |
839 | 828 | ||
840 | static void init_crit_entry(crit_entry_t *ce, enum crit_level level, | 829 | static void init_crit_entry(crit_entry_t *ce, enum crit_level level, |
@@ -888,12 +877,14 @@ static inline void init_edf_domain(domain_t *dom, rt_domain_t *rt) | |||
888 | edf_higher_prio); | 877 | edf_higher_prio); |
889 | } | 878 | } |
890 | 879 | ||
880 | domain_data_t *ce_domain_for(int); | ||
891 | static int __init init_mc(void) | 881 | static int __init init_mc(void) |
892 | { | 882 | { |
893 | int cpu; | 883 | int cpu; |
894 | cpu_entry_t *entry; | 884 | cpu_entry_t *entry; |
895 | rt_domain_t *rt; | 885 | rt_domain_t *rt; |
896 | domain_data_t *dom_data; | 886 | domain_data_t *dom_data; |
887 | domain_t *dom; | ||
897 | raw_spinlock_t *a_dom, *b_dom, *c_dom; /* For lock debugger */ | 888 | raw_spinlock_t *a_dom, *b_dom, *c_dom; /* For lock debugger */ |
898 | 889 | ||
899 | for_each_online_cpu(cpu) { | 890 | for_each_online_cpu(cpu) { |
@@ -911,13 +902,17 @@ static int __init init_mc(void) | |||
911 | #endif | 902 | #endif |
912 | 903 | ||
913 | /* CRIT_LEVEL_A */ | 904 | /* CRIT_LEVEL_A */ |
914 | dom_data = &per_cpu(_mc_crit_a, cpu); | 905 | dom_data = ce_domain_for(cpu); |
915 | rt = &per_cpu(_mc_crit_a_rt, cpu); | ||
916 | init_local_domain(entry, dom_data, CRIT_LEVEL_A); | 906 | init_local_domain(entry, dom_data, CRIT_LEVEL_A); |
917 | init_edf_domain(&dom_data->domain, rt); | ||
918 | a_dom = dom_data->domain.lock; | 907 | a_dom = dom_data->domain.lock; |
919 | raw_spin_lock_init(a_dom); | 908 | raw_spin_lock_init(a_dom); |
920 | dom_data->domain.name = "LVL-A"; | 909 | dom_data->domain.name = "LVL-A"; |
910 | /* Hook up the level A functions */ | ||
911 | dom = &dom_data->domain; | ||
912 | dom->requeue = ce_requeue; | ||
913 | dom->peek_ready = dom->take_ready = ce_peek_and_take_ready; | ||
914 | dom->higher_prio = ce_higher_prio; | ||
915 | dom->preempt_needed = mc_preempt_needed; | ||
921 | 916 | ||
922 | /* CRIT_LEVEL_B */ | 917 | /* CRIT_LEVEL_B */ |
923 | dom_data = &per_cpu(_mc_crit_b, cpu); | 918 | dom_data = &per_cpu(_mc_crit_b, cpu); |