Re: [PATCH] kthread: Add kthread_work tracepoints
On Mon, 12 Oct 2020 08:14:50 -0700 Rob Clark wrote: > > DEFINE_EVENT(sched_kthread_work_execute_template, > > sched_kthread_work_execute_start, > > TP_PROTO(struct kthread_work *work), > > TP_ARGS(work)); > > > > DEFINE_EVENT(sched_kthread_work_execute_template, > > sched_kthread_work_execute_end, > > TP_PROTO(struct kthread_work *work), > > TP_ARGS(work)); > > > > As events are cheap, classes are expensive (size wise), and a TRACE_EVENT() > > is really just a CLASS and EVENT for a single instance. > > I think we cannot quite do this, because we should not rely on being Ah I missed seeing that one used work->func and the other passed in the function. > able to dereference work after it finishes. Although I suppose I > could just define it to explicitly pass the fxn ptr to both > tracepoints.. But yes, I would rather see that. It could save up to 5K in text and data. -- Steve
Re: [PATCH] kthread: Add kthread_work tracepoints
On Mon, Oct 12, 2020 at 6:59 AM Steven Rostedt wrote: > > On Sat, 10 Oct 2020 11:03:22 -0700 > Rob Clark wrote: > > > /** > > + * sched_kthread_work_execute_start - called immediately before the work > > callback > > + * @work:pointer to struct kthread_work > > + * > > + * Allows to track kthread work execution. > > + */ > > +TRACE_EVENT(sched_kthread_work_execute_start, > > + > > + TP_PROTO(struct kthread_work *work), > > + > > + TP_ARGS(work), > > + > > + TP_STRUCT__entry( > > + __field( void *,work) > > + __field( void *,function) > > + ), > > + > > + TP_fast_assign( > > + __entry->work = work; > > + __entry->function = work->func; > > + ), > > + > > + TP_printk("work struct %p: function %ps", __entry->work, > > __entry->function) > > +); > > + > > +/** > > + * sched_kthread_work_execute_end - called immediately after the work > > callback > > + * @work:pointer to struct work_struct > > + * @function: pointer to worker function > > + * > > + * Allows to track workqueue execution. > > + */ > > +TRACE_EVENT(sched_kthread_work_execute_end, > > + > > + TP_PROTO(struct kthread_work *work, kthread_work_func_t function), > > + > > + TP_ARGS(work, function), > > + > > + TP_STRUCT__entry( > > + __field( void *,work) > > + __field( void *,function) > > + ), > > + > > + TP_fast_assign( > > + __entry->work = work; > > + __entry->function = function; > > + ), > > + > > + TP_printk("work struct %p: function %ps", __entry->work, > > __entry->function) > > +); > > + > > > Please combine the above into: > > DECLARE_EVENT_CLASS(sched_kthread_work_execute_template, > > TP_PROTO(struct kthread_work *work), > > TP_ARGS(work), > > TP_STRUCT__entry( > __field( void *,work) > __field( void *,function) > ), > > TP_fast_assign( > __entry->work = work; > __entry->function = work->func; > ), > > TP_printk("work struct %p: function %ps", __entry->work, > __entry->function) > ); > > DEFINE_EVENT(sched_kthread_work_execute_template, > sched_kthread_work_execute_start, > TP_PROTO(struct kthread_work *work), > TP_ARGS(work)); > > DEFINE_EVENT(sched_kthread_work_execute_template, > sched_kthread_work_execute_end, > TP_PROTO(struct kthread_work *work), > TP_ARGS(work)); > > As events are cheap, classes are expensive (size wise), and a TRACE_EVENT() > is really just a CLASS and EVENT for a single instance. I think we cannot quite do this, because we should not rely on being able to dereference work after it finishes. Although I suppose I could just define it to explicitly pass the fxn ptr to both tracepoints.. BR, -R
Re: [PATCH] kthread: Add kthread_work tracepoints
On Sat, 10 Oct 2020 11:03:22 -0700 Rob Clark wrote: > /** > + * sched_kthread_work_execute_start - called immediately before the work > callback > + * @work:pointer to struct kthread_work > + * > + * Allows to track kthread work execution. > + */ > +TRACE_EVENT(sched_kthread_work_execute_start, > + > + TP_PROTO(struct kthread_work *work), > + > + TP_ARGS(work), > + > + TP_STRUCT__entry( > + __field( void *,work) > + __field( void *,function) > + ), > + > + TP_fast_assign( > + __entry->work = work; > + __entry->function = work->func; > + ), > + > + TP_printk("work struct %p: function %ps", __entry->work, > __entry->function) > +); > + > +/** > + * sched_kthread_work_execute_end - called immediately after the work > callback > + * @work:pointer to struct work_struct > + * @function: pointer to worker function > + * > + * Allows to track workqueue execution. > + */ > +TRACE_EVENT(sched_kthread_work_execute_end, > + > + TP_PROTO(struct kthread_work *work, kthread_work_func_t function), > + > + TP_ARGS(work, function), > + > + TP_STRUCT__entry( > + __field( void *,work) > + __field( void *,function) > + ), > + > + TP_fast_assign( > + __entry->work = work; > + __entry->function = function; > + ), > + > + TP_printk("work struct %p: function %ps", __entry->work, > __entry->function) > +); > + Please combine the above into: DECLARE_EVENT_CLASS(sched_kthread_work_execute_template, TP_PROTO(struct kthread_work *work), TP_ARGS(work), TP_STRUCT__entry( __field( void *,work) __field( void *,function) ), TP_fast_assign( __entry->work = work; __entry->function = work->func; ), TP_printk("work struct %p: function %ps", __entry->work, __entry->function) ); DEFINE_EVENT(sched_kthread_work_execute_template, sched_kthread_work_execute_start, TP_PROTO(struct kthread_work *work), TP_ARGS(work)); DEFINE_EVENT(sched_kthread_work_execute_template, sched_kthread_work_execute_end, TP_PROTO(struct kthread_work *work), TP_ARGS(work)); As events are cheap, classes are expensive (size wise), and a TRACE_EVENT() is really just a CLASS and EVENT for a single instance. -- Steve
[PATCH] kthread: Add kthread_work tracepoints
From: Rob Clark While migrating some code from wq to kthread_worker, I found that I missed the execute_start/end tracepoints. So add similar tracepoints for kthread_work. And for completeness, queue_work tracepoint (although this one differs slightly from the matching workqueue tracepoint). Signed-off-by: Rob Clark --- include/trace/events/sched.h | 84 kernel/kthread.c | 9 2 files changed, 93 insertions(+) diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index fec25b9cfbaf..349d9872e807 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -5,6 +5,7 @@ #if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_SCHED_H +#include #include #include #include @@ -51,6 +52,89 @@ TRACE_EVENT(sched_kthread_stop_ret, TP_printk("ret=%d", __entry->ret) ); +/** + * sched_kthread_work_queue_work - called when a work gets queued + * @worker:pointer to the kthread_worker + * @work: pointer to struct kthread_work + * + * This event occurs when a work is queued immediately or once a + * delayed work is actually queued (ie: once the delay has been + * reached). + */ +TRACE_EVENT(sched_kthread_work_queue_work, + + TP_PROTO(struct kthread_worker *worker, +struct kthread_work *work), + + TP_ARGS(worker, work), + + TP_STRUCT__entry( + __field( void *,work) + __field( void *,function) + __field( void *,worker) + ), + + TP_fast_assign( + __entry->work = work; + __entry->function = work->func; + __entry->worker = worker; + ), + + TP_printk("work struct=%p function=%ps worker=%p", + __entry->work, __entry->function, __entry->worker) +); + +/** + * sched_kthread_work_execute_start - called immediately before the work callback + * @work: pointer to struct kthread_work + * + * Allows to track kthread work execution. + */ +TRACE_EVENT(sched_kthread_work_execute_start, + + TP_PROTO(struct kthread_work *work), + + TP_ARGS(work), + + TP_STRUCT__entry( + __field( void *,work) + __field( void *,function) + ), + + TP_fast_assign( + __entry->work = work; + __entry->function = work->func; + ), + + TP_printk("work struct %p: function %ps", __entry->work, __entry->function) +); + +/** + * sched_kthread_work_execute_end - called immediately after the work callback + * @work: pointer to struct work_struct + * @function: pointer to worker function + * + * Allows to track workqueue execution. + */ +TRACE_EVENT(sched_kthread_work_execute_end, + + TP_PROTO(struct kthread_work *work, kthread_work_func_t function), + + TP_ARGS(work, function), + + TP_STRUCT__entry( + __field( void *,work) + __field( void *,function) + ), + + TP_fast_assign( + __entry->work = work; + __entry->function = function; + ), + + TP_printk("work struct %p: function %ps", __entry->work, __entry->function) +); + /* * Tracepoint for waking up a task: */ diff --git a/kernel/kthread.c b/kernel/kthread.c index 3edaa380dc7b..c1e59d6bf802 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -704,8 +704,15 @@ int kthread_worker_fn(void *worker_ptr) raw_spin_unlock_irq(>lock); if (work) { + kthread_work_func_t func = work->func; __set_current_state(TASK_RUNNING); + trace_sched_kthread_work_execute_start(work); work->func(work); + /* +* Avoid dereferencing work after this point. The trace +* event only cares about the address. +*/ + trace_sched_kthread_work_execute_end(work, func); } else if (!freezing(current)) schedule(); @@ -834,6 +841,8 @@ static void kthread_insert_work(struct kthread_worker *worker, { kthread_insert_work_sanity_check(worker, work); + trace_sched_kthread_work_queue_work(worker, work); + list_add_tail(>node, pos); work->worker = worker; if (!worker->current_work && likely(worker->task)) -- 2.26.2