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>
This commit is contained in:
		
					parent
					
						
							
								97bd234701
							
						
					
				
			
			
				commit
				
					
						cdadf0097c
					
				
			
		
					 2 changed files with 56 additions and 0 deletions
				
			
		|  | @ -24,6 +24,59 @@ DECLARE_EVENT_CLASS(workqueue_work, | ||||||
| 	TP_printk("work struct %p", __entry->work) | 	TP_printk("work struct %p", __entry->work) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * workqueue_queue_work - called when a work gets queued | ||||||
|  |  * @req_cpu:	the requested cpu | ||||||
|  |  * @cwq:	pointer to struct cpu_workqueue_struct | ||||||
|  |  * @work:	pointer to struct work_struct | ||||||
|  |  * | ||||||
|  |  * This event occurs when a work is queued immediately or once a | ||||||
|  |  * delayed work is actually queued on a workqueue (ie: once the delay | ||||||
|  |  * has been reached). | ||||||
|  |  */ | ||||||
|  | TRACE_EVENT(workqueue_queue_work, | ||||||
|  | 
 | ||||||
|  | 	TP_PROTO(unsigned int req_cpu, struct cpu_workqueue_struct *cwq, | ||||||
|  | 		 struct work_struct *work), | ||||||
|  | 
 | ||||||
|  | 	TP_ARGS(req_cpu, cwq, work), | ||||||
|  | 
 | ||||||
|  | 	TP_STRUCT__entry( | ||||||
|  | 		__field( void *,	work	) | ||||||
|  | 		__field( void *,	function) | ||||||
|  | 		__field( void *,	workqueue) | ||||||
|  | 		__field( unsigned int,	req_cpu	) | ||||||
|  | 		__field( unsigned int,	cpu	) | ||||||
|  | 	), | ||||||
|  | 
 | ||||||
|  | 	TP_fast_assign( | ||||||
|  | 		__entry->work		= work; | ||||||
|  | 		__entry->function	= work->func; | ||||||
|  | 		__entry->workqueue	= cwq->wq; | ||||||
|  | 		__entry->req_cpu	= req_cpu; | ||||||
|  | 		__entry->cpu		= cwq->gcwq->cpu; | ||||||
|  | 	), | ||||||
|  | 
 | ||||||
|  | 	TP_printk("work struct=%p function=%pf workqueue=%p req_cpu=%u cpu=%u", | ||||||
|  | 		  __entry->work, __entry->function, __entry->workqueue, | ||||||
|  | 		  __entry->req_cpu, __entry->cpu) | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * workqueue_activate_work - called when a work gets activated | ||||||
|  |  * @work:	pointer to struct work_struct | ||||||
|  |  * | ||||||
|  |  * This event occurs when a queued work is put on the active queue, | ||||||
|  |  * which happens immediately after queueing unless @max_active limit | ||||||
|  |  * is reached. | ||||||
|  |  */ | ||||||
|  | DEFINE_EVENT(workqueue_work, workqueue_activate_work, | ||||||
|  | 
 | ||||||
|  | 	TP_PROTO(struct work_struct *work), | ||||||
|  | 
 | ||||||
|  | 	TP_ARGS(work) | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * workqueue_execute_start - called immediately before the workqueue callback |  * workqueue_execute_start - called immediately before the workqueue callback | ||||||
|  * @work:	pointer to struct work_struct |  * @work:	pointer to struct work_struct | ||||||
|  |  | ||||||
|  | @ -997,6 +997,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, | ||||||
| 
 | 
 | ||||||
| 	/* gcwq determined, get cwq and queue */ | 	/* gcwq determined, get cwq and queue */ | ||||||
| 	cwq = get_cwq(gcwq->cpu, wq); | 	cwq = get_cwq(gcwq->cpu, wq); | ||||||
|  | 	trace_workqueue_queue_work(cpu, cwq, work); | ||||||
| 
 | 
 | ||||||
| 	BUG_ON(!list_empty(&work->entry)); | 	BUG_ON(!list_empty(&work->entry)); | ||||||
| 
 | 
 | ||||||
|  | @ -1004,6 +1005,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, | ||||||
| 	work_flags = work_color_to_flags(cwq->work_color); | 	work_flags = work_color_to_flags(cwq->work_color); | ||||||
| 
 | 
 | ||||||
| 	if (likely(cwq->nr_active < cwq->max_active)) { | 	if (likely(cwq->nr_active < cwq->max_active)) { | ||||||
|  | 		trace_workqueue_activate_work(work); | ||||||
| 		cwq->nr_active++; | 		cwq->nr_active++; | ||||||
| 		worklist = gcwq_determine_ins_pos(gcwq, cwq); | 		worklist = gcwq_determine_ins_pos(gcwq, cwq); | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -1679,6 +1681,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) | ||||||
| 						    struct work_struct, entry); | 						    struct work_struct, entry); | ||||||
| 	struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); | 	struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); | ||||||
| 
 | 
 | ||||||
|  | 	trace_workqueue_activate_work(work); | ||||||
| 	move_linked_works(work, pos, NULL); | 	move_linked_works(work, pos, NULL); | ||||||
| 	__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work)); | 	__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work)); | ||||||
| 	cwq->nr_active++; | 	cwq->nr_active++; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tejun Heo
				Tejun Heo