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) | ||||
| ); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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 | ||||
|  * @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 */ | ||||
| 	cwq = get_cwq(gcwq->cpu, wq); | ||||
| 	trace_workqueue_queue_work(cpu, cwq, work); | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	if (likely(cwq->nr_active < cwq->max_active)) { | ||||
| 		trace_workqueue_activate_work(work); | ||||
| 		cwq->nr_active++; | ||||
| 		worklist = gcwq_determine_ins_pos(gcwq, cwq); | ||||
| 	} else { | ||||
|  | @ -1679,6 +1681,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) | |||
| 						    struct work_struct, entry); | ||||
| 	struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); | ||||
| 
 | ||||
| 	trace_workqueue_activate_work(work); | ||||
| 	move_linked_works(work, pos, NULL); | ||||
| 	__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work)); | ||||
| 	cwq->nr_active++; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tejun Heo
				Tejun Heo