aboutsummaryrefslogtreecommitdiffstats
path: root/litmus
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-04-15 20:11:39 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2013-04-15 20:11:39 -0400
commitb7724735827a2e44bfea8863b66eba3d9c4a8d67 (patch)
tree064583fb530da6e6debe350df63b1c01f9d520f6 /litmus
parent4770feaf298591fc6751d135ed2ac4f5f7df44f0 (diff)
Cleanup budget tracking in wait_for_release.
Also added logic for real-time tasks to prevent worker threads (klmirqd and aux tasks) from inheriting from tasks waiting for release.
Diffstat (limited to 'litmus')
-rw-r--r--litmus/budget.c30
-rw-r--r--litmus/fifo_lock.c2
-rw-r--r--litmus/jobs.c52
-rw-r--r--litmus/locking.c57
-rw-r--r--litmus/sched_cedf.c16
-rw-r--r--litmus/sync.c38
6 files changed, 128 insertions, 67 deletions
diff --git a/litmus/budget.c b/litmus/budget.c
index 53fe08d341d0..4b464c4d8507 100644
--- a/litmus/budget.c
+++ b/litmus/budget.c
@@ -181,13 +181,20 @@ void sobliv_on_blocked(struct task_struct* t)
181 /* clear the exhausted flag so handle will re-run. this will not 181 /* clear the exhausted flag so handle will re-run. this will not
182 * trigger another exhaustion signal since signals are controled by 182 * trigger another exhaustion signal since signals are controled by
183 * BTF_SIG_BUDGET_SENT. */ 183 * BTF_SIG_BUDGET_SENT. */
184 int exhausted = bt_flag_test_and_clear(t, BTF_BUDGET_EXHAUSTED); 184 //int exhausted = bt_flag_test_and_clear(t, BTF_BUDGET_EXHAUSTED);
185 //BUG_ON(!exhausted); 185 //BUG_ON(!exhausted);
186 WARN_ON(!exhausted); 186 //WARN_ON(!exhausted);
187 bt_flag_clear(t, BTF_BUDGET_EXHAUSTED);
187 188
188 TRACE_TASK(t, "budget timer not armed. " 189 if (likely(!bt_flag_is_set(t, BTF_WAITING_FOR_RELEASE))) {
189 "Raced with exhaustion-resched? Re-arming.\n"); 190 TRACE_TASK(t, "budget timer not armed. "
190 arm_enforcement_timer(t, 1); 191 "Raced with exhaustion-resched? Re-arming.\n");
192 arm_enforcement_timer(t, 1);
193 }
194 else {
195 TRACE_TASK(t, "not arming timer because task is waiting "
196 "for release.\n");
197 }
191 } 198 }
192 } 199 }
193} 200}
@@ -199,11 +206,14 @@ void sobliv_on_wakeup(struct task_struct* t)
199 * suspended while draining in exec_cost. suspend_timestamp was 206 * suspended while draining in exec_cost. suspend_timestamp was
200 * either set when we entered top-m while asleep, or when we 207 * either set when we entered top-m while asleep, or when we
201 * blocked. */ 208 * blocked. */
202 lt_t suspend_cost; 209 if (tsk_rt(t)->budget.suspend_timestamp) {
203 BUG_ON(!tsk_rt(t)->budget.suspend_timestamp); 210 lt_t suspend_cost = litmus_clock() - tsk_rt(t)->budget.suspend_timestamp;
204 suspend_cost = litmus_clock() - tsk_rt(t)->budget.suspend_timestamp; 211 TRACE_TASK(t, "budget consumed while suspended: %llu\n", suspend_cost);
205 TRACE_TASK(t, "budget consumed while suspended: %llu\n", suspend_cost); 212 get_exec_time(t) += suspend_cost;
206 get_exec_time(t) += suspend_cost; 213 }
214 else {
215 WARN_ON(!bt_flag_is_set(t, BTF_WAITING_FOR_RELEASE));
216 }
207 } 217 }
208} 218}
209 219
diff --git a/litmus/fifo_lock.c b/litmus/fifo_lock.c
index 88f27a016b16..745472c30dfd 100644
--- a/litmus/fifo_lock.c
+++ b/litmus/fifo_lock.c
@@ -739,6 +739,8 @@ void fifo_mutex_budget_exhausted(struct litmus_lock* l, struct task_struct* t)
739 /* DGL lock must already be held on this code path if DGLs are enabled. */ 739 /* DGL lock must already be held on this code path if DGLs are enabled. */
740 lock_fine_irqsave(&mutex->lock, flags); 740 lock_fine_irqsave(&mutex->lock, flags);
741 741
742 TRACE_TASK(t, "handling budget exhaustion for FIFO lock %d\n", l->ident);
743
742 /* unlocks mutex->lock */ 744 /* unlocks mutex->lock */
743 __fifo_mutex_propagate_decrease_inheritance(&mutex->litmus_lock, t, flags, 1); 745 __fifo_mutex_propagate_decrease_inheritance(&mutex->litmus_lock, t, flags, 1);
744} 746}
diff --git a/litmus/jobs.c b/litmus/jobs.c
index 1479cddad9de..018b4982afb5 100644
--- a/litmus/jobs.c
+++ b/litmus/jobs.c
@@ -61,3 +61,55 @@ long complete_job(void)
61 schedule(); 61 schedule();
62 return 0; 62 return 0;
63} 63}
64
65
66#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
67
68void hide_from_workers(struct task_struct *t, worker_visibility_t *wv)
69{
70#ifdef CONFIG_REALTIME_AUX_TASKS
71 if (tsk_rt(t)->has_aux_tasks) {
72 if (wv) {
73 wv->aux_hide = tsk_rt(t)->hide_from_aux_tasks;
74 wv->do_aux_restore = 1;
75 }
76 tsk_rt(t)->hide_from_aux_tasks = 1;
77 }
78#endif
79#ifdef CONFIG_LITMUS_NVIDIA
80 if (tsk_rt(t)->held_gpus) {
81 if (wv) {
82 wv->gpu_hide = tsk_rt(t)->hide_from_gpu;
83 wv->do_gpu_restore = 1;
84 }
85 tsk_rt(t)->hide_from_gpu = 1;
86 }
87#endif
88}
89
90void show_to_workers(struct task_struct *t, worker_visibility_t *wv)
91{
92 if (wv) {
93#ifdef CONFIG_REALTIME_AUX_TASKS
94 if (wv->do_aux_restore)
95 tsk_rt(t)->hide_from_aux_tasks = wv->aux_hide;
96#endif
97#ifdef CONFIG_LITMUS_NVIDIA
98 if (wv->do_gpu_restore)
99 tsk_rt(t)->hide_from_gpu = wv->gpu_hide;
100#endif
101 }
102 else {
103#ifdef CONFIG_REALTIME_AUX_TASKS
104 if (tsk_rt(t)->has_aux_tasks)
105 tsk_rt(t)->hide_from_aux_tasks = 0;
106#endif
107#ifdef CONFIG_LITMUS_NVIDIA
108 if (tsk_rt(t)->held_gpus)
109 tsk_rt(t)->hide_from_gpu = 0;
110#endif
111 }
112}
113
114#endif
115
diff --git a/litmus/locking.c b/litmus/locking.c
index 43afa920d3f1..67f5fda590c0 100644
--- a/litmus/locking.c
+++ b/litmus/locking.c
@@ -20,6 +20,10 @@
20#include <litmus/gpu_affinity.h> 20#include <litmus/gpu_affinity.h>
21#endif 21#endif
22 22
23#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
24#include <litmus/jobs.h>
25#endif
26
23static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg); 27static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg);
24static int open_generic_lock(struct od_table_entry* entry, void* __user arg); 28static int open_generic_lock(struct od_table_entry* entry, void* __user arg);
25static int close_generic_lock(struct od_table_entry* entry); 29static int close_generic_lock(struct od_table_entry* entry);
@@ -767,66 +771,27 @@ void suspend_for_lock(void)
767 struct task_struct *t = current; 771 struct task_struct *t = current;
768#endif 772#endif
769 773
770#ifdef CONFIG_REALTIME_AUX_TASKS 774#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
771 unsigned int aux_restore = 0; 775 DECLARE_WORKER_VIS_FLAGS(vis_flags);
772 unsigned int aux_hide; 776 hide_from_workers(t, &vis_flags);
773#endif
774
775#ifdef CONFIG_LITMUS_NVIDIA
776 unsigned int gpu_restore = 0;
777 unsigned int gpu_hide;
778#endif
779
780#ifdef CONFIG_REALTIME_AUX_TASKS
781 if (tsk_rt(t)->has_aux_tasks) {
782 /* hide from aux tasks so they can't inherit our priority when we block
783 * for a litmus lock. inheritance is already going to a litmus lock
784 * holder. */
785 aux_hide = tsk_rt(t)->hide_from_aux_tasks;
786 aux_restore = 1;
787 tsk_rt(t)->hide_from_aux_tasks = 1;
788 }
789#endif
790
791#ifdef CONFIG_LITMUS_NVIDIA
792 if (tsk_rt(t)->held_gpus) {
793 gpu_hide = tsk_rt(t)->hide_from_gpu;
794 gpu_restore = 1;
795 tsk_rt(t)->hide_from_gpu = 1;
796 }
797#endif 777#endif
798 778
799#if defined(CONFIG_LITMUS_AFFINITY_LOCKING) && defined(CONFIG_LITMUS_NVIDIA) 779#if defined(CONFIG_LITMUS_AFFINITY_LOCKING) && defined(CONFIG_LITMUS_NVIDIA)
800 // disable tracking 780 // disable tracking
801 if(tsk_rt(t)->held_gpus) { 781 if(tsk_rt(t)->held_gpus)
802 tsk_rt(t)->suspend_gpu_tracker_on_block = 1; 782 tsk_rt(t)->suspend_gpu_tracker_on_block = 1;
803 }
804#endif 783#endif
805 784
806 schedule(); 785 schedule();
807 786
808
809 /* TODO: Move the following to wake_up_for_lock()? */
810
811#if defined(CONFIG_LITMUS_AFFINITY_LOCKING) && defined(CONFIG_LITMUS_NVIDIA) 787#if defined(CONFIG_LITMUS_AFFINITY_LOCKING) && defined(CONFIG_LITMUS_NVIDIA)
812 // re-enable tracking 788 // re-enable tracking
813 if(tsk_rt(t)->held_gpus) { 789 if(tsk_rt(t)->held_gpus)
814 tsk_rt(t)->suspend_gpu_tracker_on_block = 0; 790 tsk_rt(t)->suspend_gpu_tracker_on_block = 0;
815 }
816#endif 791#endif
817 792
818#ifdef CONFIG_LITMUS_NVIDIA 793#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
819 if (gpu_restore) { 794 show_to_workers(t, &vis_flags);
820 /* restore our state */
821 tsk_rt(t)->hide_from_gpu = gpu_hide;
822 }
823#endif
824
825#ifdef CONFIG_REALTIME_AUX_TASKS
826 if (aux_restore) {
827 /* restore our state */
828 tsk_rt(t)->hide_from_aux_tasks = aux_hide;
829 }
830#endif 795#endif
831} 796}
832 797
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c
index 9ec068e9fcf7..aab30a786515 100644
--- a/litmus/sched_cedf.c
+++ b/litmus/sched_cedf.c
@@ -222,6 +222,9 @@ static void cedf_track_in_top_m(struct task_struct *t)
222 222
223 return; 223 return;
224 } 224 }
225
226 BUG_ON(binheap_empty(&cluster->top_m));
227
225 bt = binheap_top_entry(&cluster->top_m, struct budget_tracker, top_m_node); 228 bt = binheap_top_entry(&cluster->top_m, struct budget_tracker, top_m_node);
226 mth_highest = 229 mth_highest =
227 container_of( 230 container_of(
@@ -230,7 +233,6 @@ static void cedf_track_in_top_m(struct task_struct *t)
230 rt_param); 233 rt_param);
231 234
232 if (__edf_higher_prio(t, BASE, mth_highest, BASE)) { 235 if (__edf_higher_prio(t, BASE, mth_highest, BASE)) {
233
234 TRACE_TASK(t, "adding to top-m (evicting %s/%d)\n", 236 TRACE_TASK(t, "adding to top-m (evicting %s/%d)\n",
235 mth_highest->comm, mth_highest->pid); 237 mth_highest->comm, mth_highest->pid);
236 238
@@ -266,7 +268,6 @@ static void cedf_untrack_in_top_m(struct task_struct *t)
266 } 268 }
267 269
268 if (bt_flag_is_set(t, BTF_IS_TOP_M)) { 270 if (bt_flag_is_set(t, BTF_IS_TOP_M)) {
269
270 TRACE_TASK(t, "removing task from top-m\n"); 271 TRACE_TASK(t, "removing task from top-m\n");
271 272
272 /* delete t's entry */ 273 /* delete t's entry */
@@ -1310,8 +1311,15 @@ static struct task_struct* cedf_schedule(struct task_struct * prev)
1310#endif 1311#endif
1311 1312
1312 /* Do budget stuff */ 1313 /* Do budget stuff */
1313 if (blocks) 1314 if (blocks) {
1314 budget_state_machine(prev,on_blocked); 1315 if (likely(!bt_flag_is_set(prev, BTF_WAITING_FOR_RELEASE)))
1316 budget_state_machine(prev,on_blocked);
1317 else {
1318 /* waiting for release. 'exit' the scheduler. */
1319 cedf_untrack_in_top_m(prev);
1320 budget_state_machine(prev,on_exit);
1321 }
1322 }
1315 else if (sleep) 1323 else if (sleep)
1316 budget_state_machine(prev,on_sleep); 1324 budget_state_machine(prev,on_sleep);
1317 else if (preempt) 1325 else if (preempt)
diff --git a/litmus/sync.c b/litmus/sync.c
index 749ae62c2b87..dfd9e40ab28d 100644
--- a/litmus/sync.c
+++ b/litmus/sync.c
@@ -15,6 +15,7 @@
15#include <litmus/jobs.h> 15#include <litmus/jobs.h>
16 16
17#include <litmus/sched_trace.h> 17#include <litmus/sched_trace.h>
18#include <litmus/budget.h>
18 19
19struct ts_release_wait { 20struct ts_release_wait {
20 struct list_head list; 21 struct list_head list;
@@ -39,6 +40,13 @@ static long do_wait_for_ts_release(struct timespec *wake)
39 40
40 long ret = -ERESTARTSYS; 41 long ret = -ERESTARTSYS;
41 42
43 struct task_struct *t = current;
44 int is_rt = is_realtime(t);
45
46#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
47 DECLARE_WORKER_VIS_FLAGS(vis_flags);
48#endif
49
42 if (mutex_lock_interruptible(&task_release_lock)) 50 if (mutex_lock_interruptible(&task_release_lock))
43 goto out; 51 goto out;
44 52
@@ -46,29 +54,45 @@ static long do_wait_for_ts_release(struct timespec *wake)
46 54
47 mutex_unlock(&task_release_lock); 55 mutex_unlock(&task_release_lock);
48 56
57 if (is_rt) {
58#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
59 hide_from_workers(t, &vis_flags);
60#endif
61 bt_flag_set(t, BTF_WAITING_FOR_RELEASE);
62 mb();
63 }
64
49 /* We are enqueued, now we wait for someone to wake us up. */ 65 /* We are enqueued, now we wait for someone to wake us up. */
50 ret = wait_for_completion_interruptible(&wait.completion); 66 ret = wait_for_completion_interruptible(&wait.completion);
51 67
68 if (is_rt) {
69 bt_flag_clear(t, BTF_WAITING_FOR_RELEASE);
70#if defined(CONFIG_REALTIME_AUX_TASKS) || defined(CONFIG_LITMUS_NVIDIA)
71 show_to_workers(t, &vis_flags);
72#endif
73 }
74
52 if (!ret) { 75 if (!ret) {
53 if (is_realtime(current)) { 76 if (is_rt) {
54 lt_t phasedRelease = wait.ts_release_time 77 lt_t phasedRelease = wait.ts_release_time
55 + current->rt_param.task_params.phase; 78 + t->rt_param.task_params.phase;
56 *wake = ns_to_timespec(phasedRelease); 79 *wake = ns_to_timespec(phasedRelease);
57 80
58 /* Setting this flag before releasing ensures that this CPU 81 /* Setting this flag before releasing ensures that this CPU
59 * will be the next CPU to requeue the task on a ready or 82 * will be the next CPU to requeue the task on a ready or
60 * release queue. 83 * release queue.
61 */ 84 */
62 tsk_rt(current)->completed = 1; 85 tsk_rt(t)->completed = 1;
63 tsk_rt(current)->job_params.backlog = 0; 86 tsk_rt(t)->job_params.backlog = 0;
64 bt_flags_reset(current); 87 tsk_rt(t)->job_params.is_backlogged_job = 0;
88 tsk_rt(t)->budget.suspend_timestamp = 0;
89 bt_flag_clear(t, BTF_BUDGET_EXHAUSTED);
65 mb(); 90 mb();
66 91
67 /* completion succeeded, set up release. subtract off 92 /* completion succeeded, set up release. subtract off
68 * period because schedule()->job_completion() will 93 * period because schedule()->job_completion() will
69 * advances us to the correct time */ 94 * advances us to the correct time */
70 litmus->release_at(current, 95 litmus->release_at(t, phasedRelease - t->rt_param.task_params.period);
71 phasedRelease - current->rt_param.task_params.period);
72 schedule(); 96 schedule();
73 } 97 }
74 else { 98 else {