Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

workqueue: Add basic tracepoints to track workqueue execution

With the introduction of the new unified work queue thread pools,
we lost one feature: It's no longer possible to know which worker
is causing the CPU to wake out of idle. The result is that PowerTOP
now reports a lot of "kworker/a:b" instead of more readable results.

This patch adds a pair of tracepoints to the new workqueue code,
similar in style to the timer/hrtimer tracepoints.

With this pair of tracepoints, the next PowerTOP can correctly
report which work item caused the wakeup (and how long it took):

Interrupt (43) i915 time 3.51ms wakeups 141
Work ieee80211_iface_work time 0.81ms wakeups 29
Work do_dbs_timer time 0.55ms wakeups 24
Process Xorg time 21.36ms wakeups 4
Timer sched_rt_period_timer time 0.01ms wakeups 1

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Arjan van de Ven and committed by
Linus Torvalds
e36c886a 69b26c7a

+71
+62
include/trace/events/workqueue.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM workqueue 3 + 4 + #if !defined(_TRACE_WORKQUEUE_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_WORKQUEUE_H 6 + 7 + #include <linux/tracepoint.h> 8 + #include <linux/workqueue.h> 9 + 10 + /** 11 + * workqueue_execute_start - called immediately before the workqueue callback 12 + * @work: pointer to struct work_struct 13 + * 14 + * Allows to track workqueue execution. 15 + */ 16 + TRACE_EVENT(workqueue_execute_start, 17 + 18 + TP_PROTO(struct work_struct *work), 19 + 20 + TP_ARGS(work), 21 + 22 + TP_STRUCT__entry( 23 + __field( void *, work ) 24 + __field( void *, function) 25 + ), 26 + 27 + TP_fast_assign( 28 + __entry->work = work; 29 + __entry->function = work->func; 30 + ), 31 + 32 + TP_printk("work struct %p: function %pf", __entry->work, __entry->function) 33 + ); 34 + 35 + /** 36 + * workqueue_execute_end - called immediately before the workqueue callback 37 + * @work: pointer to struct work_struct 38 + * 39 + * Allows to track workqueue execution. 40 + */ 41 + TRACE_EVENT(workqueue_execute_end, 42 + 43 + TP_PROTO(struct work_struct *work), 44 + 45 + TP_ARGS(work), 46 + 47 + TP_STRUCT__entry( 48 + __field( void *, work ) 49 + ), 50 + 51 + TP_fast_assign( 52 + __entry->work = work; 53 + ), 54 + 55 + TP_printk("work struct %p", __entry->work) 56 + ); 57 + 58 + 59 + #endif /* _TRACE_WORKQUEUE_H */ 60 + 61 + /* This part must be outside protection */ 62 + #include <trace/define_trace.h>
+9
kernel/workqueue.c
··· 35 35 #include <linux/lockdep.h> 36 36 #include <linux/idr.h> 37 37 38 + #define CREATE_TRACE_POINTS 39 + #include <trace/events/workqueue.h> 40 + 38 41 #include "workqueue_sched.h" 39 42 40 43 enum { ··· 1793 1790 work_clear_pending(work); 1794 1791 lock_map_acquire(&cwq->wq->lockdep_map); 1795 1792 lock_map_acquire(&lockdep_map); 1793 + trace_workqueue_execute_start(work); 1796 1794 f(work); 1795 + /* 1796 + * While we must be careful to not use "work" after this, the trace 1797 + * point will only record its address. 1798 + */ 1799 + trace_workqueue_execute_end(work); 1797 1800 lock_map_release(&lockdep_map); 1798 1801 lock_map_release(&cwq->wq->lockdep_map); 1799 1802