diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2011-09-21 18:48:49 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2011-09-21 18:48:49 -0400 |
| commit | 06051baff7db5e0c1b80d7b2a873b022191cdcec (patch) | |
| tree | 8f0a776714f91092f312bde90df9757291382d02 | |
| parent | 96b86e34ab2d7d49e3e6174935c0aca2828415f5 (diff) | |
Formatting
| -rw-r--r-- | litmus/sched_mc.c | 100 |
1 files changed, 35 insertions, 65 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c index 1f2b13c6a219..0ec03b3949d2 100644 --- a/litmus/sched_mc.c +++ b/litmus/sched_mc.c | |||
| @@ -4,10 +4,6 @@ | |||
| 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 | * This version uses the simple approach and serializes all scheduling | ||
| 9 | * decisions by the use of a queue lock. This is probably not the | ||
| 10 | * best way to do it, but it should suffice for now. | ||
| 11 | */ | 7 | */ |
| 12 | 8 | ||
| 13 | #include <linux/spinlock.h> | 9 | #include <linux/spinlock.h> |
| @@ -75,7 +71,6 @@ typedef struct { | |||
| 75 | } domain_data_t; | 71 | } domain_data_t; |
| 76 | 72 | ||
| 77 | static cpu_entry_t* cpus[NR_CPUS]; | 73 | static cpu_entry_t* cpus[NR_CPUS]; |
| 78 | static raw_spinlock_t global_lock; | ||
| 79 | 74 | ||
| 80 | #define domain_data(dom) (container_of(dom, domain_data_t, domain)) | 75 | #define domain_data(dom) (container_of(dom, domain_data_t, domain)) |
| 81 | #define is_global(dom) (domain_data(dom)->heap) | 76 | #define is_global(dom) (domain_data(dom)->heap) |
| @@ -86,8 +81,7 @@ static raw_spinlock_t global_lock; | |||
| 86 | (((e)->linked) ? tsk_mc_crit((e)->linked) : NUM_CRIT_LEVELS - 1) | 81 | (((e)->linked) ? tsk_mc_crit((e)->linked) : NUM_CRIT_LEVELS - 1) |
| 87 | #define crit_cpu(ce) \ | 82 | #define crit_cpu(ce) \ |
| 88 | (container_of((void*)((ce) - (ce)->level), cpu_entry_t, crit_entries)) | 83 | (container_of((void*)((ce) - (ce)->level), cpu_entry_t, crit_entries)) |
| 89 | 84 | /* Useful debug macros */ | |
| 90 | /* useful debug macros */ | ||
| 91 | #define TS "(%s/%d:%d:%s)" | 85 | #define TS "(%s/%d:%d:%s)" |
| 92 | #define TA(t) (t) ? (is_ghost(t)) ? "ghost" : t->comm : "NULL", (t) ? t->pid : 1, \ | 86 | #define TA(t) (t) ? (is_ghost(t)) ? "ghost" : t->comm : "NULL", (t) ? t->pid : 1, \ |
| 93 | (t) ? t->rt_param.job_params.job_no : 1, \ | 87 | (t) ? t->rt_param.job_params.job_no : 1, \ |
| @@ -115,7 +109,6 @@ static int cpu_lower_prio(struct bheap_node *a, struct bheap_node *b) | |||
| 115 | second = b->value; | 109 | second = b->value; |
| 116 | first_link = first->linked; | 110 | first_link = first->linked; |
| 117 | second_link = second->linked; | 111 | second_link = second->linked; |
| 118 | |||
| 119 | if (!first->usable || !second->usable) { | 112 | if (!first->usable || !second->usable) { |
| 120 | return second->usable && first->usable; | 113 | return second->usable && first->usable; |
| 121 | } else if (!first_link || !second_link) { | 114 | } else if (!first_link || !second_link) { |
| @@ -134,7 +127,6 @@ static int cpu_lower_prio(struct bheap_node *a, struct bheap_node *b) | |||
| 134 | static noinline int mc_preempt_needed(domain_t *dom, struct task_struct* curr) | 127 | static noinline int mc_preempt_needed(domain_t *dom, struct task_struct* curr) |
| 135 | { | 128 | { |
| 136 | struct task_struct *next = dom->peek_ready(dom); | 129 | struct task_struct *next = dom->peek_ready(dom); |
| 137 | |||
| 138 | if (!next || !curr) { | 130 | if (!next || !curr) { |
| 139 | return next && !curr; | 131 | return next && !curr; |
| 140 | } else { | 132 | } else { |
| @@ -150,8 +142,7 @@ static noinline int mc_preempt_needed(domain_t *dom, struct task_struct* curr) | |||
| 150 | static inline crit_entry_t* lowest_prio_cpu(domain_t *dom) | 142 | static inline crit_entry_t* lowest_prio_cpu(domain_t *dom) |
| 151 | { | 143 | { |
| 152 | struct bheap *heap = domain_data(dom)->heap; | 144 | struct bheap *heap = domain_data(dom)->heap; |
| 153 | struct bheap_node* hn; | 145 | struct bheap_node* hn = bheap_peek(cpu_lower_prio, heap); |
| 154 | hn = bheap_peek(cpu_lower_prio, heap); | ||
| 155 | return (hn) ? hn->value : NULL; | 146 | return (hn) ? hn->value : NULL; |
| 156 | } | 147 | } |
| 157 | 148 | ||
| @@ -161,11 +152,9 @@ static inline crit_entry_t* lowest_prio_cpu(domain_t *dom) | |||
| 161 | */ | 152 | */ |
| 162 | static void update_ghost_time(struct task_struct *p) | 153 | static void update_ghost_time(struct task_struct *p) |
| 163 | { | 154 | { |
| 164 | u64 delta, clock; | 155 | u64 clock = litmus_clock(); |
| 165 | 156 | u64 delta = clock - p->se.exec_start; | |
| 166 | BUG_ON(!is_ghost(p)); | 157 | BUG_ON(!is_ghost(p)); |
| 167 | clock = litmus_clock(); | ||
| 168 | delta = clock - p->se.exec_start; | ||
| 169 | if (unlikely ((s64)delta < 0)) { | 158 | if (unlikely ((s64)delta < 0)) { |
| 170 | delta = 0; | 159 | delta = 0; |
| 171 | TRACE_TASK(p, "WARNING: negative time delta"); | 160 | TRACE_TASK(p, "WARNING: negative time delta"); |
| @@ -236,7 +225,6 @@ static void link_task_to_crit(crit_entry_t *ce, | |||
| 236 | } | 225 | } |
| 237 | 226 | ||
| 238 | static void check_for_preempt(domain_t*); | 227 | static void check_for_preempt(domain_t*); |
| 239 | |||
| 240 | /** | 228 | /** |
| 241 | * job_arrival() - Called when a task re-enters the system. | 229 | * job_arrival() - Called when a task re-enters the system. |
| 242 | * Caller must hold no locks. | 230 | * Caller must hold no locks. |
| @@ -247,7 +235,6 @@ static void job_arrival(struct task_struct *task) | |||
| 247 | 235 | ||
| 248 | TRACE_TASK(task, "Job arriving"); | 236 | TRACE_TASK(task, "Job arriving"); |
| 249 | BUG_ON(!task); | 237 | BUG_ON(!task); |
| 250 | |||
| 251 | raw_spin_lock(dom->lock); | 238 | raw_spin_lock(dom->lock); |
| 252 | if (can_requeue(task)) { | 239 | if (can_requeue(task)) { |
| 253 | dom->requeue(dom, task); | 240 | dom->requeue(dom, task); |
| @@ -271,16 +258,16 @@ static void job_arrival(struct task_struct *task) | |||
| 271 | */ | 258 | */ |
| 272 | static void link_task_to_cpu(cpu_entry_t *entry, struct task_struct *task) | 259 | static void link_task_to_cpu(cpu_entry_t *entry, struct task_struct *task) |
| 273 | { | 260 | { |
| 274 | int i; | 261 | int i = entry_level(entry); |
| 275 | TRACE_TASK(task, "Linking to P%d", entry->cpu); | 262 | TRACE_TASK(task, "Linking to P%d", entry->cpu); |
| 276 | BUG_ON(task && tsk_rt(task)->linked_on != entry->cpu); | 263 | BUG_ON(task && tsk_rt(task)->linked_on != entry->cpu); |
| 277 | BUG_ON(task && is_ghost(task)); | 264 | BUG_ON(task && is_ghost(task)); |
| 278 | 265 | ||
| 279 | i = entry_level(entry); | ||
| 280 | if (task){ | 266 | if (task){ |
| 281 | set_rt_flags(task, RT_F_RUNNING); | 267 | set_rt_flags(task, RT_F_RUNNING); |
| 282 | } | 268 | } |
| 283 | entry->linked = task; | 269 | entry->linked = task; |
| 270 | /* Higher criticality crit entries are now usable */ | ||
| 284 | for (; i < entry_level(entry) + 1; i++) { | 271 | for (; i < entry_level(entry) + 1; i++) { |
| 285 | TRACE_CRIT_ENTRY(&entry->crit_entries[i], "now usable"); | 272 | TRACE_CRIT_ENTRY(&entry->crit_entries[i], "now usable"); |
| 286 | entry->crit_entries[i].usable = 1; | 273 | entry->crit_entries[i].usable = 1; |
| @@ -295,9 +282,8 @@ static void link_task_to_cpu(cpu_entry_t *entry, struct task_struct *task) | |||
| 295 | * Caller must hold the lock for @dom and @ce's CPU lock. Returns 1 if | 282 | * Caller must hold the lock for @dom and @ce's CPU lock. Returns 1 if |
| 296 | * a physically preemption occurred. | 283 | * a physically preemption occurred. |
| 297 | */ | 284 | */ |
| 298 | static int preempt(domain_t *dom, crit_entry_t *ce) | 285 | static void preempt(domain_t *dom, crit_entry_t *ce) |
| 299 | { | 286 | { |
| 300 | int rv = 0; | ||
| 301 | struct task_struct *task = dom->take_ready(dom); | 287 | struct task_struct *task = dom->take_ready(dom); |
| 302 | cpu_entry_t *entry = crit_cpu(ce); | 288 | cpu_entry_t *entry = crit_cpu(ce); |
| 303 | 289 | ||
| @@ -309,14 +295,11 @@ static int preempt(domain_t *dom, crit_entry_t *ce) | |||
| 309 | dom->requeue(dom, ce->linked); | 295 | dom->requeue(dom, ce->linked); |
| 310 | } | 296 | } |
| 311 | link_task_to_crit(ce, task); | 297 | link_task_to_crit(ce, task); |
| 312 | |||
| 313 | /* Preempt actual execution if this is a running task */ | 298 | /* Preempt actual execution if this is a running task */ |
| 314 | if (!is_ghost(task)) { | 299 | if (!is_ghost(task)) { |
| 315 | link_task_to_cpu(entry, task); | 300 | link_task_to_cpu(entry, task); |
| 316 | preempt_if_preemptable(entry->scheduled, entry->cpu); | 301 | preempt_if_preemptable(entry->scheduled, entry->cpu); |
| 317 | rv = 1; | ||
| 318 | } | 302 | } |
| 319 | return rv; | ||
| 320 | } | 303 | } |
| 321 | 304 | ||
| 322 | /** | 305 | /** |
| @@ -335,7 +318,6 @@ static void update_crit_levels(cpu_entry_t *entry) | |||
| 335 | for (i = level + 1; i < NUM_CRIT_LEVELS; i++) { | 318 | for (i = level + 1; i < NUM_CRIT_LEVELS; i++) { |
| 336 | ce = &entry->crit_entries[i]; | 319 | ce = &entry->crit_entries[i]; |
| 337 | tasks[i] = ce->linked; | 320 | tasks[i] = ce->linked; |
| 338 | TRACE_CRIT_ENTRY(ce, "not usable"); | ||
| 339 | ce->usable = 0; | 321 | ce->usable = 0; |
| 340 | if (ce->linked) { | 322 | if (ce->linked) { |
| 341 | link_task_to_crit(ce, NULL); | 323 | link_task_to_crit(ce, NULL); |
| @@ -380,7 +362,6 @@ static void check_for_preempt(domain_t *dom) | |||
| 380 | } else /* Partitioned */ { | 362 | } else /* Partitioned */ { |
| 381 | ce = domain_data(dom)->crit_entry; | 363 | ce = domain_data(dom)->crit_entry; |
| 382 | entry = crit_cpu(ce); | 364 | entry = crit_cpu(ce); |
| 383 | |||
| 384 | raw_spin_lock(&entry->lock); | 365 | raw_spin_lock(&entry->lock); |
| 385 | if (ce->usable && dom->preempt_needed(dom, ce->linked)) { | 366 | if (ce->usable && dom->preempt_needed(dom, ce->linked)) { |
| 386 | preempt(dom, ce); | 367 | preempt(dom, ce); |
| @@ -406,11 +387,12 @@ static void remove_from_all(struct task_struct* task) | |||
| 406 | BUG_ON(!task); | 387 | BUG_ON(!task); |
| 407 | 388 | ||
| 408 | raw_spin_lock(dom->lock); | 389 | raw_spin_lock(dom->lock); |
| 390 | |||
| 409 | if (task->rt_param.linked_on != NO_CPU) { | 391 | if (task->rt_param.linked_on != NO_CPU) { |
| 410 | entry = cpus[task->rt_param.linked_on]; | 392 | entry = cpus[task->rt_param.linked_on]; |
| 411 | |||
| 412 | raw_spin_lock(&entry->lock); | 393 | |
