mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	perf: Simplify perf_event_free_task() wait
Simplify the code by moving the duplicated wakeup condition into put_ctx(). Notably, wait_var_event() is in perf_event_free_task() and will have set ctx->task = TASK_TOMBSTONE. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Ravi Bangoria <ravi.bangoria@amd.com> Link: https://lkml.kernel.org/r/20250307193723.044499344@infradead.org
This commit is contained in:
		
							parent
							
								
									0a00a43b8c
								
							
						
					
					
						commit
						59f3aa4a3e
					
				
					 1 changed files with 3 additions and 22 deletions
				
			
		| 
						 | 
					@ -1270,6 +1270,9 @@ static void put_ctx(struct perf_event_context *ctx)
 | 
				
			||||||
		if (ctx->task && ctx->task != TASK_TOMBSTONE)
 | 
							if (ctx->task && ctx->task != TASK_TOMBSTONE)
 | 
				
			||||||
			put_task_struct(ctx->task);
 | 
								put_task_struct(ctx->task);
 | 
				
			||||||
		call_rcu(&ctx->rcu_head, free_ctx);
 | 
							call_rcu(&ctx->rcu_head, free_ctx);
 | 
				
			||||||
 | 
						} else if (ctx->task == TASK_TOMBSTONE) {
 | 
				
			||||||
 | 
							smp_mb(); /* pairs with wait_var_event() */
 | 
				
			||||||
 | 
							wake_up_var(&ctx->refcount);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5729,8 +5732,6 @@ int perf_event_release_kernel(struct perf_event *event)
 | 
				
			||||||
again:
 | 
					again:
 | 
				
			||||||
	mutex_lock(&event->child_mutex);
 | 
						mutex_lock(&event->child_mutex);
 | 
				
			||||||
	list_for_each_entry(child, &event->child_list, child_list) {
 | 
						list_for_each_entry(child, &event->child_list, child_list) {
 | 
				
			||||||
		void *var = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Cannot change, child events are not migrated, see the
 | 
							 * Cannot change, child events are not migrated, see the
 | 
				
			||||||
		 * comment with perf_event_ctx_lock_nested().
 | 
							 * comment with perf_event_ctx_lock_nested().
 | 
				
			||||||
| 
						 | 
					@ -5765,40 +5766,20 @@ int perf_event_release_kernel(struct perf_event *event)
 | 
				
			||||||
		if (tmp == child) {
 | 
							if (tmp == child) {
 | 
				
			||||||
			perf_remove_from_context(child, DETACH_GROUP | DETACH_CHILD);
 | 
								perf_remove_from_context(child, DETACH_GROUP | DETACH_CHILD);
 | 
				
			||||||
			list_add(&child->child_list, &free_list);
 | 
								list_add(&child->child_list, &free_list);
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			var = &ctx->refcount;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mutex_unlock(&event->child_mutex);
 | 
							mutex_unlock(&event->child_mutex);
 | 
				
			||||||
		mutex_unlock(&ctx->mutex);
 | 
							mutex_unlock(&ctx->mutex);
 | 
				
			||||||
		put_ctx(ctx);
 | 
							put_ctx(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (var) {
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * If perf_event_free_task() has deleted all events from the
 | 
					 | 
				
			||||||
			 * ctx while the child_mutex got released above, make sure to
 | 
					 | 
				
			||||||
			 * notify about the preceding put_ctx().
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			smp_mb(); /* pairs with wait_var_event() */
 | 
					 | 
				
			||||||
			wake_up_var(var);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		goto again;
 | 
							goto again;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mutex_unlock(&event->child_mutex);
 | 
						mutex_unlock(&event->child_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry_safe(child, tmp, &free_list, child_list) {
 | 
						list_for_each_entry_safe(child, tmp, &free_list, child_list) {
 | 
				
			||||||
		void *var = &child->ctx->refcount;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		list_del(&child->child_list);
 | 
							list_del(&child->child_list);
 | 
				
			||||||
		/* Last reference unless ->pending_task work is pending */
 | 
							/* Last reference unless ->pending_task work is pending */
 | 
				
			||||||
		put_event(child);
 | 
							put_event(child);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Wake any perf_event_free_task() waiting for this event to be
 | 
					 | 
				
			||||||
		 * freed.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		smp_mb(); /* pairs with wait_var_event() */
 | 
					 | 
				
			||||||
		wake_up_var(var);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
no_ctx:
 | 
					no_ctx:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue