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

workqueue: add queue_work and activate_work trace points

These two tracepoints allow tracking when and how a work is queued and
activated. This patch is based on Frederic's patch to add queue_work
trace point.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>

Tejun Heo cdadf009 97bd2347

+56
+53
include/trace/events/workqueue.h
··· 25 25 ); 26 26 27 27 /** 28 + * workqueue_queue_work - called when a work gets queued 29 + * @req_cpu: the requested cpu 30 + * @cwq: pointer to struct cpu_workqueue_struct 31 + * @work: pointer to struct work_struct 32 + * 33 + * This event occurs when a work is queued immediately or once a 34 + * delayed work is actually queued on a workqueue (ie: once the delay 35 + * has been reached). 36 + */ 37 + TRACE_EVENT(workqueue_queue_work, 38 + 39 + TP_PROTO(unsigned int req_cpu, struct cpu_workqueue_struct *cwq, 40 + struct work_struct *work), 41 + 42 + TP_ARGS(req_cpu, cwq, work), 43 + 44 + TP_STRUCT__entry( 45 + __field( void *, work ) 46 + __field( void *, function) 47 + __field( void *, workqueue) 48 + __field( unsigned int, req_cpu ) 49 + __field( unsigned int, cpu ) 50 + ), 51 + 52 + TP_fast_assign( 53 + __entry->work = work; 54 + __entry->function = work->func; 55 + __entry->workqueue = cwq->wq; 56 + __entry->req_cpu = req_cpu; 57 + __entry->cpu = cwq->gcwq->cpu; 58 + ), 59 + 60 + TP_printk("work struct=%p function=%pf workqueue=%p req_cpu=%u cpu=%u", 61 + __entry->work, __entry->function, __entry->workqueue, 62 + __entry->req_cpu, __entry->cpu) 63 + ); 64 + 65 + /** 66 + * workqueue_activate_work - called when a work gets activated 67 + * @work: pointer to struct work_struct 68 + * 69 + * This event occurs when a queued work is put on the active queue, 70 + * which happens immediately after queueing unless @max_active limit 71 + * is reached. 72 + */ 73 + DEFINE_EVENT(workqueue_work, workqueue_activate_work, 74 + 75 + TP_PROTO(struct work_struct *work), 76 + 77 + TP_ARGS(work) 78 + ); 79 + 80 + /** 28 81 * workqueue_execute_start - called immediately before the workqueue callback 29 82 * @work: pointer to struct work_struct 30 83 *
+3
kernel/workqueue.c
··· 997 997 998 998 /* gcwq determined, get cwq and queue */ 999 999 cwq = get_cwq(gcwq->cpu, wq); 1000 + trace_workqueue_queue_work(cpu, cwq, work); 1000 1001 1001 1002 BUG_ON(!list_empty(&work->entry)); 1002 1003 ··· 1005 1004 work_flags = work_color_to_flags(cwq->work_color); 1006 1005 1007 1006 if (likely(cwq->nr_active < cwq->max_active)) { 1007 + trace_workqueue_activate_work(work); 1008 1008 cwq->nr_active++; 1009 1009 worklist = gcwq_determine_ins_pos(gcwq, cwq); 1010 1010 } else { ··· 1681 1679 struct work_struct, entry); 1682 1680 struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); 1683 1681 1682 + trace_workqueue_activate_work(work); 1684 1683 move_linked_works(work, pos, NULL); 1685 1684 __clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work)); 1686 1685 cwq->nr_active++;