aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-03-02 12:04:55 -0500
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-04-12 14:58:40 -0400
commit5cdc24ae24b6517d594072b27873b1d46416eae3 (patch)
treebab9fcb6fde1bae2b5857cd4838fe5847f927de5
parentad92e346f66397c431b8856fb1eb15be29415b04 (diff)
Add preemption-and-migration overhead tracing supportwip-pm-ovd
Add per-task accounting (based on shared control page) of information needed to trace preemption and migration overheads from userspace
-rw-r--r--include/litmus/rt_param.h19
-rw-r--r--kernel/sched.c6
-rw-r--r--litmus/Kconfig10
-rw-r--r--litmus/sched_litmus.c54
4 files changed, 88 insertions, 1 deletions
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index 5b94d1a8eea7..31630d729dbb 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -50,13 +50,26 @@ struct rt_task {
50 * determining preemption/migration overheads). 50 * determining preemption/migration overheads).
51 */ 51 */
52struct control_page { 52struct control_page {
53 /* preemption and migration overheads measurement*/
54 /* execution start time */
55 lt_t preempt_end;
56 /* increased if last_rt != current */
57 unsigned long sched_count;
58 unsigned int cpu;
59 /* job number for this task */
60 unsigned long job_count;
61 /* last rt task before current one */
62 unsigned long last_rt_task;
63 /* execution stop time */
64 lt_t preempt_start;
65
53 /* Is the task currently in a non-preemptive section? */ 66 /* Is the task currently in a non-preemptive section? */
54 int np_flag; 67 int np_flag;
55 /* Should the task call into the kernel when it leaves 68 /* Should the task call into the kernel when it leaves
56 * its non-preemptive section? */ 69 * its non-preemptive section? */
57 int delayed_preemption; 70 int delayed_preemption;
58 71
59 /* to be extended */ 72 /* what do you want to share today ? */
60}; 73};
61 74
62/* don't export internal data structures to user space (liblitmus) */ 75/* don't export internal data structures to user space (liblitmus) */
@@ -175,6 +188,10 @@ struct rt_param {
175 */ 188 */
176 struct list_head list; 189 struct list_head list;
177 190
191 /* FIXME for overhead tracing it would be better
192 * having this page on top of rt_param and having rt_param
193 * closer to the top of task_struct
194 */
178 /* Pointer to the page shared between userspace and kernel. */ 195 /* Pointer to the page shared between userspace and kernel. */
179 struct control_page * ctrl_page; 196 struct control_page * ctrl_page;
180}; 197};
diff --git a/kernel/sched.c b/kernel/sched.c
index 1701eaebb79c..69fb86c87915 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -489,6 +489,9 @@ struct rt_rq {
489struct litmus_rq { 489struct litmus_rq {
490 unsigned long nr_running; 490 unsigned long nr_running;
491 struct task_struct *prev; 491 struct task_struct *prev;
492#ifdef CONFIG_PREEMPT_MIGRAT_OVD
493 unsigned int last_rt_task;
494#endif
492}; 495};
493 496
494#ifdef CONFIG_SMP 497#ifdef CONFIG_SMP
@@ -2766,8 +2769,11 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
2766 */ 2769 */
2767 prev_state = prev->state; 2770 prev_state = prev->state;
2768 finish_arch_switch(prev); 2771 finish_arch_switch(prev);
2772
2769 litmus->finish_switch(prev); 2773 litmus->finish_switch(prev);
2770 prev->rt_param.stack_in_use = NO_CPU; 2774 prev->rt_param.stack_in_use = NO_CPU;
2775 trace_preempt_migrat_ovd(prev, current, rq);
2776
2771 perf_event_task_sched_in(current, cpu_of(rq)); 2777 perf_event_task_sched_in(current, cpu_of(rq));
2772 finish_lock_switch(rq, prev); 2778 finish_lock_switch(rq, prev);
2773 2779
diff --git a/litmus/Kconfig b/litmus/Kconfig
index 874794f64af1..77f65e512136 100644
--- a/litmus/Kconfig
+++ b/litmus/Kconfig
@@ -67,6 +67,16 @@ config SCHED_OVERHEAD_TRACE
67 Export event stream for overhead tracing. 67 Export event stream for overhead tracing.
68 Say Yes for overhead tracing. 68 Say Yes for overhead tracing.
69 69
70config PREEMPT_MIGRAT_OVD
71 bool "Preemption and migration overhead measurements"
72 default n
73 help
74 Include support for tracing preemption and migration overheads
75 in userspace. Unless you know the mess you are going into,
76 the safe choice is No. If you _really_ want to have some fun,
77 than say Yes and have a look in the liblitmus2010 library for
78 some program examples.
79
70config SCHED_DEBUG_TRACE 80config SCHED_DEBUG_TRACE
71 bool "TRACE() debugging" 81 bool "TRACE() debugging"
72 default y 82 default y
diff --git a/litmus/sched_litmus.c b/litmus/sched_litmus.c
index c1fc7748e590..be29cbe15fc5 100644
--- a/litmus/sched_litmus.c
+++ b/litmus/sched_litmus.c
@@ -316,3 +316,57 @@ const struct sched_class litmus_sched_class = {
316 .prio_changed = prio_changed_litmus, 316 .prio_changed = prio_changed_litmus,
317 .switched_to = switched_to_litmus, 317 .switched_to = switched_to_litmus,
318}; 318};
319
320#ifdef CONFIG_PREEMPT_MIGRAT_OVD
321/* trace_preempt_migrat_ovd() executes during finish_task_switch()
322 * before (possibly) giving control back to userspace
323 * Using shared rw (FIXME ro?) ctrl page we keep the userspace
324 * monitoring program updated on what happened during our execution
325 */
326static void trace_preempt_migrat_ovd(struct task_struct *prev,
327 struct task_struct *curr,
328 struct rq *rq)
329{
330 struct control_page *ctrl;
331
332 /* Update bookkeeping variables that are shared with userspace
333 * to conduct appropriate benchmarking (preempt, migration)
334 */
335 if (is_realtime(prev) && tsk_rt(prev)->ctrl_page) {
336 rq->litmus.last_rt_task = prev->pid;
337 tsk_rt(prev)->ctrl_page->preempt_start = get_cycles();
338 }
339
340 if (is_realtime(current) && tsk_rt(current)->ctrl_page) {
341 ctrl = tsk_rt(current)->ctrl_page;
342 ctrl->preempt_end = get_cycles();
343
344 /* If the last RT task to be scheduled was not
345 * this task, then the preemption "counts", and
346 * we increment sched_count. Otherwise, we do
347 * not. On a migration this might not get
348 * incrememented, and we need to check for a cpu
349 * change in that case (cpu is always updated).
350 */
351 if (rq->litmus.last_rt_task != current->pid)
352 ctrl->sched_count++;
353
354 /* "our" userspace will be eventually awoke sometimes
355 * in the "near" future, we write on the shared page
356 * some information for it
357 */
358 ctrl->cpu = rq->cpu;
359 ctrl->job_count = tsk_rt(current)->job_params.job_no;
360 ctrl->last_rt_task = rq->litmus.last_rt_task;
361 /* userspace has all the information to compute the length
362 * of this preemption
363 */
364 }
365}
366#else
367static inline void trace_preempt_migrat_ovd(struct task_struct *prev,
368 struct task_struct *curr,
369 struct rq *rq)
370{
371}
372#endif