aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZelin Tong <ztong@ludwig.cs.unc.edu>2020-06-01 13:26:51 -0400
committerZelin Tong <ztong@ludwig.cs.unc.edu>2020-06-01 13:26:51 -0400
commite4c5fa6df346a78dfb683d601fd5ad34e6de3375 (patch)
tree90a7b4dcf891ec84c2f7ca4d32bb94d63cc12a2c
parent1394cfe730e1e5030decc9990b37011a4957a7c0 (diff)
Final Fixes
Fixed jobs sometimes disappearing due to mysterious path in gschedule where it is not requeued. This is done by first requeueing regardless, and letting unlink dequeue as necessary. Made container_boundary only try to stabilize when new tasks are removed/added to the systed
-rw-r--r--litmus/litmus_proc.c9
-rw-r--r--litmus/sched_edfsc.c129
2 files changed, 99 insertions, 39 deletions
diff --git a/litmus/litmus_proc.c b/litmus/litmus_proc.c
index de5e3f37fe88..ebea92da0a3d 100644
--- a/litmus/litmus_proc.c
+++ b/litmus/litmus_proc.c
@@ -31,13 +31,18 @@ static struct proc_dir_entry *litmus_dir = NULL,
31/* in litmus/sync.c */ 31/* in litmus/sync.c */
32int count_tasks_waiting_for_release(void); 32int count_tasks_waiting_for_release(void);
33 33
34/* in litmus/sched_edfsc.c */
35int count_migrating_tasks(void);
36
34static int litmus_stats_proc_show(struct seq_file *m, void *v) 37static int litmus_stats_proc_show(struct seq_file *m, void *v)
35{ 38{
36 seq_printf(m, 39 seq_printf(m,
37 "real-time tasks = %d\n" 40 "real-time tasks = %d\n"
38 "ready for release = %d\n", 41 "ready for release = %d\n"
42 "migrating tasks = %d\n",
39 atomic_read(&rt_task_count), 43 atomic_read(&rt_task_count),
40 count_tasks_waiting_for_release()); 44 count_tasks_waiting_for_release(),
45 count_migrating_tasks());
41 return 0; 46 return 0;
42} 47}
43 48
diff --git a/litmus/sched_edfsc.c b/litmus/sched_edfsc.c
index 8ae94f2dc1df..fae6feeac76f 100644
--- a/litmus/sched_edfsc.c
+++ b/litmus/sched_edfsc.c
@@ -68,6 +68,9 @@ static rt_domain_t gsched_domain;
68u64 m_util; 68u64 m_util;
69u64 sys_util; 69u64 sys_util;
70 70
71//only true when container_boundary needs to perform stabilization
72int sys_changed;
73
71#define is_container(task) ((task) && tsk_rt(task)->edfsc_params.domain != NULL && tsk_rt(task)->domain == &gsched_domain) 74#define is_container(task) ((task) && tsk_rt(task)->edfsc_params.domain != NULL && tsk_rt(task)->domain == &gsched_domain)
72#define is_fixed(task) ((task) && tsk_rt(task)->edfsc_params.container_task != NULL) 75#define is_fixed(task) ((task) && tsk_rt(task)->edfsc_params.container_task != NULL)
73#define is_migrating(task) ((task) && tsk_rt(task)->edfsc_params.domain == NULL && tsk_rt(task)->domain == &gsched_domain) 76#define is_migrating(task) ((task) && tsk_rt(task)->edfsc_params.domain == NULL && tsk_rt(task)->domain == &gsched_domain)
@@ -83,6 +86,21 @@ void release_heap_free(struct release_heap* rh);
83struct bheap_node* bheap_node_alloc(int gfp_flags); 86struct bheap_node* bheap_node_alloc(int gfp_flags);
84void bheap_node_free(struct bheap_node* hn); 87void bheap_node_free(struct bheap_node* hn);
85 88
89int count_migrating_tasks(void)
90{
91 int task_count = 0;
92 struct list_head *pos;
93 unsigned long flags;
94
95 raw_spin_lock_irqsave(&g_lock, flags);
96
97 list_for_each(pos, &migrating_tasks) {
98 task_count++;
99 }
100
101 raw_spin_unlock_irqrestore(&g_lock, flags);
102 return task_count;
103}
86 104
87/* Do a backwards comparison based on f_util so that heavier containers 105/* Do a backwards comparison based on f_util so that heavier containers
88 * will come first 106 * will come first
@@ -370,6 +388,7 @@ static void g_remove_task(struct task_struct *t)
370 BUG_ON(is_container(t)); 388 BUG_ON(is_container(t));
371 m_util -= get_rt_utilization(t); 389 m_util -= get_rt_utilization(t);
372 sys_util -= get_rt_utilization(t); 390 sys_util -= get_rt_utilization(t);
391 sys_changed = 1;
373} 392}
374 393
375static void c_remove_task(struct task_struct *t) 394static void c_remove_task(struct task_struct *t)
@@ -378,6 +397,7 @@ static void c_remove_task(struct task_struct *t)
378 tsk_rt(container_task)->edfsc_params.domain->f_util -= 397 tsk_rt(container_task)->edfsc_params.domain->f_util -=
379 get_rt_utilization(t); 398 get_rt_utilization(t);
380 sys_util -= get_rt_utilization(t); 399 sys_util -= get_rt_utilization(t);
400 sys_changed = 1;
381} 401}
382 402
383/** 403/**
@@ -400,6 +420,7 @@ static void migrate_task(struct task_struct *t)
400 tsk_rt(t)->edfsc_params.container_task = tsk_rt(t)->edfsc_params.move_to->container; 420 tsk_rt(t)->edfsc_params.container_task = tsk_rt(t)->edfsc_params.move_to->container;
401 requeue(t); 421 requeue(t);
402 tsk_rt(t)->edfsc_params.move_to = NULL; 422 tsk_rt(t)->edfsc_params.move_to = NULL;
423 sys_changed = 1;
403} 424}
404 425
405/** 426/**
@@ -492,6 +513,7 @@ static noinline void g_job_completion(struct task_struct* t, int forced)
492 * tardy case, then just immediately call c_release() on the container. 513 * tardy case, then just immediately call c_release() on the container.
493 */ 514 */
494 } else if (is_container(t)) { 515 } else if (is_container(t)) {
516 /*
495 struct task_struct** child = &tsk_rt(t)->edfsc_params.domain->scheduled; 517 struct task_struct** child = &tsk_rt(t)->edfsc_params.domain->scheduled;
496 // No need to handle fixed tasks, cschedule will do that when it runs next 518 // No need to handle fixed tasks, cschedule will do that when it runs next
497 if (*child && is_migrating(*child)) { 519 if (*child && is_migrating(*child)) {
@@ -509,6 +531,7 @@ static noinline void g_job_completion(struct task_struct* t, int forced)
509 // Regardless, we never "freeze" a migrating task in a container 531 // Regardless, we never "freeze" a migrating task in a container
510 *child = NULL; 532 *child = NULL;
511 } 533 }
534 */
512 // When a container job finishes late, release it immediately 535 // When a container job finishes late, release it immediately
513 if (tsk_rt(t)->edfsc_params.can_release) { 536 if (tsk_rt(t)->edfsc_params.can_release) {
514 tsk_rt(t)->edfsc_params.can_release = 0; 537 tsk_rt(t)->edfsc_params.can_release = 0;
@@ -543,7 +566,8 @@ static void g_finish_switch(struct task_struct *prev)
543 // members of entry multiple times, we have to lock. Otherwise we 566 // members of entry multiple times, we have to lock. Otherwise we
544 // may make an if branch based off entry->linked, and then have it 567 // may make an if branch based off entry->linked, and then have it
545 // change before we can set entry->scheduled. 568 // change before we can set entry->scheduled.
546 raw_spin_lock_irqsave(&g_lock, flags); 569 //raw_spin_lock_irqsave(&g_lock, flags);
570 preempt_disable();
547 entry->scheduled = is_realtime(current) ? current : NULL; 571 entry->scheduled = is_realtime(current) ? current : NULL;
548 // If we're scheduling a task in a container, set entry->scheduled to the container 572 // If we're scheduling a task in a container, set entry->scheduled to the container
549 if (entry->scheduled) { 573 if (entry->scheduled) {
@@ -557,13 +581,9 @@ static void g_finish_switch(struct task_struct *prev)
557 entry->scheduled = entry->linked; 581 entry->scheduled = entry->linked;
558 } 582 }
559 583
560 // This handles requeuing when a container is descheduled 584 BUG_ON(is_fixed(entry->scheduled));
561 // TODO: Move this to edfsc_gschedule() 585 //raw_spin_unlock_irqrestore(&g_lock, flags);
562 if (!is_container(entry->scheduled) && tsk_rt(container)->edfsc_params.domain->scheduled) { 586 preempt_enable();
563 requeue(tsk_rt(container)->edfsc_params.domain->scheduled);
564 tsk_rt(container)->edfsc_params.domain->scheduled = NULL;
565 }
566 raw_spin_unlock_irqrestore(&g_lock, flags);
567#ifdef WANT_ALL_SCHED_EVENTS 587#ifdef WANT_ALL_SCHED_EVENTS
568 TRACE_TASK(prev, "switched away from\n"); 588 TRACE_TASK(prev, "switched away from\n");
569#endif 589#endif
@@ -595,7 +615,7 @@ static void edfsc_cschedule(cont_domain_t* cedf, struct task_struct * prev)
595 * differently from gedf, when a task exits (dead) 615 * differently from gedf, when a task exits (dead)
596 * cedf->schedule may be null and prev _is_ realtime 616 * cedf->schedule may be null and prev _is_ realtime
597 */ 617 */
598 BUG_ON(cedf->scheduled && cedf->scheduled != prev && is_realtime(prev)); 618 //BUG_ON(cedf->scheduled && cedf->scheduled != prev && is_realtime(prev));
599 BUG_ON(cedf->scheduled && !is_realtime(cedf->scheduled)); 619 BUG_ON(cedf->scheduled && !is_realtime(cedf->scheduled));
600 620
601 /* (0) Determine state */ 621 /* (0) Determine state */
@@ -605,7 +625,8 @@ static void edfsc_cschedule(cont_domain_t* cedf, struct task_struct * prev)
605 && budget_exhausted(cedf->scheduled); 625 && budget_exhausted(cedf->scheduled);
606 np = exists && is_np(cedf->scheduled); 626 np = exists && is_np(cedf->scheduled);
607 sleep = exists && is_completed(cedf->scheduled); 627 sleep = exists && is_completed(cedf->scheduled);
608 preempt = (is_migrating(prev) && __peek_ready(edf)) || edf_preemption_needed(edf, prev); 628 preempt = (is_migrating(cedf->scheduled) && __peek_ready(edf)) ||
629 (exists && edf_preemption_needed(edf, cedf->scheduled));
609 630
610 /* If we need to preempt do so. 631 /* If we need to preempt do so.
611 * The following checks set resched to 1 in case of special 632 * The following checks set resched to 1 in case of special
@@ -632,7 +653,7 @@ static void edfsc_cschedule(cont_domain_t* cedf, struct task_struct * prev)
632 } 653 }
633 654
634 // Deschedule any background jobs if a fixed task is ready 655 // Deschedule any background jobs if a fixed task is ready
635 if (is_migrating(cedf->scheduled) && preempt) { 656 if (is_migrating(cedf->scheduled) || preempt) {
636 if (!sleep && !out_of_time && !blocks && !is_queued(cedf->scheduled)) 657 if (!sleep && !out_of_time && !blocks && !is_queued(cedf->scheduled))
637 requeue(cedf->scheduled); 658 requeue(cedf->scheduled);
638 resched = 1; 659 resched = 1;
@@ -644,6 +665,9 @@ static void edfsc_cschedule(cont_domain_t* cedf, struct task_struct * prev)
644 */ 665 */
645 next = NULL; 666 next = NULL;
646 if (blocks || !exists || (!np && resched)) { 667 if (blocks || !exists || (!np && resched)) {
668 /*if (exists && !out_of_time && !sleep && !is_queued(cedf->scheduled)) {
669 requeue(cedf->scheduled);
670 }*/
647 next = __take_ready(edf); 671 next = __take_ready(edf);
648 } else if (exists) { 672 } else if (exists) {
649 // This is safe when background scheduling, as we can only get here if 673 // This is safe when background scheduling, as we can only get here if
@@ -682,6 +706,7 @@ static struct task_struct *edfsc_gschedule(struct task_struct *prev)
682 int out_of_time, sleep, preempted, np, exists, blocks, is_cont; 706 int out_of_time, sleep, preempted, np, exists, blocks, is_cont;
683 unsigned long flags; 707 unsigned long flags;
684 struct task_struct* next = NULL; 708 struct task_struct* next = NULL;
709 struct task_struct* temp = NULL;
685 710