diff options
-rw-r--r-- | litmus/sched_mc.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c index f3ace9fe560a..43b0731ab38a 100644 --- a/litmus/sched_mc.c +++ b/litmus/sched_mc.c | |||
@@ -4,6 +4,49 @@ | |||
4 | * Implementation of the Mixed Criticality scheduling algorithm. | 4 | * Implementation of the Mixed Criticality scheduling algorithm. |
5 | * | 5 | * |
6 | * (Per Mollison, Erickson, Anderson, Baruah, Scoredos 2010) | 6 | * (Per Mollison, Erickson, Anderson, Baruah, Scoredos 2010) |
7 | * | ||
8 | * Absolute first: relative time spent doing different parts of release | ||
9 | * and scheduling overhead needs to be measured and graphed. | ||
10 | * | ||
11 | * Domain locks should be more fine-grained. There is no reason to hold the | ||
12 | * ready-queue lock when adding a task to the release-queue. | ||
13 | * | ||
14 | * The levels should be converted to linked-lists so that they are more | ||
15 | * adaptable and need not be identical on all processors. | ||
16 | * | ||
17 | * The interaction between remove_from_all and other concurrent operations | ||
18 | * should be re-examined. If a job_completion and a preemption happen | ||
19 | * simultaneously, a task could be requeued, removed, then requeued again. | ||
20 | * | ||
21 | * Level-C tasks should be able to swap CPUs a-la GSN-EDF. They should also | ||
22 | * try and swap with the last CPU they were on. This could be complicated for | ||
23 | * ghost tasks. | ||
24 | * | ||
25 | * Locking for timer-merging could be infinitely more fine-grained. A second | ||
26 | * hash could select a lock to use based on queue slot. This approach might | ||
27 | * also help with add_release in rt_domains. | ||
28 | * | ||
29 | * It should be possible to reserve a CPU for ftdumping. | ||
30 | * | ||
31 | * The real_deadline business seems sloppy. | ||
32 | * | ||
33 | * The amount of data in the header file should be cut down. The use of the | ||
34 | * header file in general needs to be re-examined. | ||
35 | * | ||
36 | * The plugin needs to be modified so that it doesn't freeze when it is | ||
37 | * deactivated in a VM. | ||
38 | * | ||
39 | * The locking in check_for_preempt is not fine-grained enough. | ||
40 | * | ||
41 | * The size of the structures could be smaller. Debugging info might be | ||
42 | * excessive as things currently stand. | ||
43 | * | ||
44 | * The macro can_requeue has been expanded too much. Anything beyond | ||
45 | * scheduled_on is a hack! | ||
46 | * | ||
47 | * Domain names (rt_domain) are still clumsy. | ||
48 | * | ||
49 | * Should BE be moved into the kernel? This will require benchmarking. | ||
7 | */ | 50 | */ |
8 | 51 | ||
9 | #include <linux/spinlock.h> | 52 | #include <linux/spinlock.h> |
@@ -110,7 +153,7 @@ static int cpu_lower_prio(struct bheap_node *a, struct bheap_node *b) | |||
110 | } | 153 | } |
111 | 154 | ||
112 | /* | 155 | /* |
113 | * Return true if the domain has a higher priority ready task. The curr | 156 | * Return true if the domain has a higher priority ready task. The @curr |
114 | * task must belong to the domain. | 157 | * task must belong to the domain. |
115 | */ | 158 | */ |
116 | static int mc_preempt_needed(struct domain *dom, struct task_struct* curr) | 159 | static int mc_preempt_needed(struct domain *dom, struct task_struct* curr) |
@@ -381,6 +424,7 @@ static void link_task_to_cpu(struct cpu_entry *entry, struct task_struct *task) | |||
381 | set_rt_flags(task, RT_F_RUNNING); | 424 | set_rt_flags(task, RT_F_RUNNING); |
382 | } | 425 | } |
383 | entry->linked = task; | 426 | entry->linked = task; |
427 | |||
384 | /* Higher criticality crit entries are now usable */ | 428 | /* Higher criticality crit entries are now usable */ |
385 | for (; i < entry_level(entry) + 1; i++) { | 429 | for (; i < entry_level(entry) + 1; i++) { |
386 | ce = &entry->crit_entries[i]; | 430 | ce = &entry->crit_entries[i]; |
@@ -418,8 +462,7 @@ static void preempt(struct domain *dom, struct crit_entry *ce) | |||
418 | link_task_to_cpu(entry, task); | 462 | link_task_to_cpu(entry, task); |
419 | preempt_if_preemptable(entry->scheduled, entry->cpu); | 463 | preempt_if_preemptable(entry->scheduled, entry->cpu); |
420 | } else if (old && old == entry->linked) { | 464 | } else if (old && old == entry->linked) { |
421 | /* | 465 | /* Preempted a running task with a ghost job. Null needs to be |
422 | * Preempted a running task with a ghost job. Null needs to be | ||
423 | * running. | 466 | * running. |
424 | */ | 467 | */ |
425 | link_task_to_cpu(entry, NULL); | 468 | link_task_to_cpu(entry, NULL); |
@@ -444,7 +487,7 @@ static void update_crit_levels(struct cpu_entry *entry) | |||
444 | ce = &entry->crit_entries[i]; | 487 | ce = &entry->crit_entries[i]; |
445 | 488 | ||
446 | global_preempted = ce->linked && | 489 | global_preempted = ce->linked && |
447 | /* This task is running */ | 490 | /* This task is running on a cpu */ |
448 | ce->linked->rt_param.scheduled_on == entry->cpu && | 491 | ce->linked->rt_param.scheduled_on == entry->cpu && |
449 | /* But it was preempted */ | 492 | /* But it was preempted */ |
450 | ce->linked != entry->linked && | 493 | ce->linked != entry->linked && |
@@ -970,14 +1013,12 @@ static struct task_struct* mc_schedule(struct task_struct* prev) | |||
970 | raw_spin_unlock(&entry->lock); | 1013 | raw_spin_unlock(&entry->lock); |
971 | raw_spin_lock(dom->lock); | 1014 | raw_spin_lock(dom->lock); |
972 | 1015 | ||
973 | /* Peek at task here to avoid lock use */ | 1016 | /* Do domain stuff before grabbing CPU locks */ |
974 | dtask = dom->peek_ready(dom); | 1017 | dtask = dom->peek_ready(dom); |
1018 | fix_crit_position(ce); | ||
975 | 1019 | ||
976 | raw_spin_lock(&entry->lock); | 1020 | raw_spin_lock(&entry->lock); |
977 | 1021 | ||
978 | /* Now that we hold the domain lock...*/ | ||
979 | fix_crit_position(ce); | ||
980 | |||
981 | if (!entry->linked && !ce->linked && dtask && can_use(ce)) { | 1022 | if (!entry->linked && !ce->linked && dtask && can_use(ce)) { |
982 | dom->take_ready(dom); | 1023 | dom->take_ready(dom); |
983 | link_task_to_crit(ce, dtask); | 1024 | link_task_to_crit(ce, dtask); |