diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2013-04-15 20:11:39 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2013-04-15 20:11:39 -0400 |
commit | b7724735827a2e44bfea8863b66eba3d9c4a8d67 (patch) | |
tree | 064583fb530da6e6debe350df63b1c01f9d520f6 /litmus | |
parent | 4770feaf298591fc6751d135ed2ac4f5f7df44f0 (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.c | 30 | ||||
-rw-r--r-- | litmus/fifo_lock.c | 2 | ||||
-rw-r--r-- | litmus/jobs.c | 52 | ||||
-rw-r--r-- | litmus/locking.c | 57 | ||||
-rw-r--r-- | litmus/sched_cedf.c | 16 | ||||
-rw-r--r-- | litmus/sync.c | 38 |
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 | |||
68 | void 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 | |||
90 | void 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 | |||
23 | static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg); | 27 | static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg); |
24 | static int open_generic_lock(struct od_table_entry* entry, void* __user arg); | 28 | static int open_generic_lock(struct od_table_entry* entry, void* __user arg); |
25 | static int close_generic_lock(struct od_table_entry* entry); | 29 | static 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 | ||
19 | struct ts_release_wait { | 20 | struct 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 { |