syzbot


ID Workflow Result Correct Bug Created Started Finished Revision Error
ce604440-bd95-40b9-8efd-cd19f2458118 assessment-kcsan 💥 KCSAN: data-race in perf_event_set_state / perf_mmap_rb 2026/01/14 12:50 2026/01/14 12:50 2026/01/14 13:12 a9d6a79219801d2130df3b1a792c57f0e5428e9f LLM did not call tool to set outputs

Crash report:
==================================================================
BUG: KCSAN: data-race in perf_event_set_state / perf_mmap_rb

write to 0xffff88812279f1a0 of 8 bytes by task 12011 on cpu 1:
 perf_event_update_time kernel/events/core.c:737 [inline]
 perf_mmap_rb+0x71c/0x910 kernel/events/core.c:7037
 perf_mmap+0x1ce/0x2f0 kernel/events/core.c:7164
 vfs_mmap include/linux/fs.h:2053 [inline]
 mmap_file mm/internal.h:167 [inline]
 __mmap_new_file_vma mm/vma.c:2421 [inline]
 __mmap_new_vma mm/vma.c:2484 [inline]
 __mmap_region mm/vma.c:2708 [inline]
 mmap_region+0x1045/0x1410 mm/vma.c:2786
 do_mmap+0x9b3/0xbe0 mm/mmap.c:558
 vm_mmap_pgoff+0x17a/0x2e0 mm/util.c:581
 ksys_mmap_pgoff+0x268/0x310 mm/mmap.c:604
 x64_sys_call+0x16bb/0x3000 arch/x86/include/generated/asm/syscalls_64.h:10
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xca/0x2b0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

read to 0xffff88812279f1a0 of 8 bytes by task 12005 on cpu 0:
 __perf_update_times kernel/events/core.c:720 [inline]
 perf_event_update_time kernel/events/core.c:735 [inline]
 perf_event_set_state+0x153/0x440 kernel/events/core.c:754
 event_sched_out+0x2d4/0x4d0 kernel/events/core.c:2391
 group_sched_out kernel/events/core.c:2415 [inline]
 __pmu_ctx_sched_out+0x3e7/0x530 kernel/events/core.c:3458
 ctx_sched_out+0x273/0x2d0 kernel/events/core.c:3539
 task_ctx_sched_out+0x4d/0x70 kernel/events/core.c:2859
 perf_event_context_sched_out kernel/events/core.c:3746 [inline]
 __perf_event_task_sched_out+0x286/0x370 kernel/events/core.c:3846
 perf_event_task_sched_out include/linux/perf_event.h:1654 [inline]
 prepare_task_switch kernel/sched/core.c:5045 [inline]
 context_switch kernel/sched/core.c:5201 [inline]
 __schedule+0xbf0/0xcd0 kernel/sched/core.c:6863
 __schedule_loop kernel/sched/core.c:6945 [inline]
 schedule+0x5f/0xd0 kernel/sched/core.c:6960
 schedule_preempt_disabled+0x10/0x20 kernel/sched/core.c:7017
 __mutex_lock_common kernel/locking/mutex.c:692 [inline]
 __mutex_lock+0x4ff/0xe20 kernel/locking/mutex.c:776
 __mutex_lock_slowpath+0xa/0x10 kernel/locking/mutex.c:1065
 mutex_lock+0x89/0x90 kernel/locking/mutex.c:290
 perf_poll+0x180/0x1f0 kernel/events/core.c:6150
 vfs_poll include/linux/poll.h:82 [inline]
 select_poll_one fs/select.c:480 [inline]
 do_select+0x8f1/0xf40 fs/select.c:536
 core_sys_select+0x3dc/0x6e0 fs/select.c:677
 do_pselect fs/select.c:759 [inline]
 __do_sys_pselect6 fs/select.c:798 [inline]
 __se_sys_pselect6+0x213/0x280 fs/select.c:789
 __x64_sys_pselect6+0x78/0x90 fs/select.c:789
 x64_sys_call+0x2e98/0x3000 arch/x86/include/generated/asm/syscalls_64.h:271
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xca/0x2b0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

value changed: 0x000000000038c145 -> 0x00000000003929d3

Reported by Kernel Concurrency Sanitizer on:
CPU: 0 UID: 0 PID: 12005 Comm: syz.4.2772 Tainted: G        W           syzkaller #0 PREEMPT(voluntary) 
Tainted: [W]=WARN
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
==================================================================

Trajectory:
Seq Timestamp Type Name Duration
0/0 2026/01/14 12:50 flow assessment-kcsan
22m Model:
unknown

Error:
LLM did not call tool to set outputs

1/1 2026/01/14 12:50 action kernel-checkouter
0m Model:
unknown

Results:
map[KernelSrc:/usr/local/google/home/dvyukov/syzkaller/agent/workdir/cache/src/45e88afe9f77e1065fe073226d73bb1a7b8fcd49]

2/1 2026/01/14 12:51 action kernel-builder
3m Model:
unknown

Results:
map[KernelObj:/usr/local/google/home/dvyukov/syzkaller/agent/workdir/cache/build/cd032fae0a4a355202951678faca55c2ed45746d]

3/1 2026/01/14 12:55 action codesearch-prepare
13m Model:
unknown

Results:
map[Index:codesearch-index]

4/1 2026/01/14 13:09 agent expert
3m Model:
unknown

Error:
LLM did not call tool to set outputs

Instruction:
You are an experienced Linux kernel developer tasked with determining if the given kernel
data race is benign or not. The data race report is from KCSAN tool.
It contains 2 stack traces of the memory accesses that constitute a data race.

A "benign" data races are on a simple int/bool variable or similar field,
and the accesses are not supposed to be protected by any mutual exclusion primitives.
Common examples of such "benign" data races are accesses to various flags fields,
statistics counters, and similar. A "benign" data race does not lead to memory corruption/crash
with a conservative compiler that compiles memory accesses to primitive types
effectively as atomic.

A non-benign (or "harmful" data race) can lead to corruption/crash even with
a conservative compiler that compiles memory accesses to primitive types
effectively as atomic. A common example of a "harmful" data races is race on
a complex container (list/hashmap/etc), where accesses are supposed to be protected
by a mutual exclusion primitive.

In the final reply explain why you think the given data race is benign or is harmful.

Use the provided tools to confirm any assumptions, variables/fields being accessed, etc.
In particular, don't make assumptions about the kernel source code,
use codesearch tools to read the actual source code.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
The data race report is:

==================================================================
BUG: KCSAN: data-race in perf_event_set_state / perf_mmap_rb

write to 0xffff88812279f1a0 of 8 bytes by task 12011 on cpu 1:
 perf_event_update_time kernel/events/core.c:737 [inline]
 perf_mmap_rb+0x71c/0x910 kernel/events/core.c:7037
 perf_mmap+0x1ce/0x2f0 kernel/events/core.c:7164
 vfs_mmap include/linux/fs.h:2053 [inline]
 mmap_file mm/internal.h:167 [inline]
 __mmap_new_file_vma mm/vma.c:2421 [inline]
 __mmap_new_vma mm/vma.c:2484 [inline]
 __mmap_region mm/vma.c:2708 [inline]
 mmap_region+0x1045/0x1410 mm/vma.c:2786
 do_mmap+0x9b3/0xbe0 mm/mmap.c:558
 vm_mmap_pgoff+0x17a/0x2e0 mm/util.c:581
 ksys_mmap_pgoff+0x268/0x310 mm/mmap.c:604
 x64_sys_call+0x16bb/0x3000 arch/x86/include/generated/asm/syscalls_64.h:10
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xca/0x2b0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

read to 0xffff88812279f1a0 of 8 bytes by task 12005 on cpu 0:
 __perf_update_times kernel/events/core.c:720 [inline]
 perf_event_update_time kernel/events/core.c:735 [inline]
 perf_event_set_state+0x153/0x440 kernel/events/core.c:754
 event_sched_out+0x2d4/0x4d0 kernel/events/core.c:2391
 group_sched_out kernel/events/core.c:2415 [inline]
 __pmu_ctx_sched_out+0x3e7/0x530 kernel/events/core.c:3458
 ctx_sched_out+0x273/0x2d0 kernel/events/core.c:3539
 task_ctx_sched_out+0x4d/0x70 kernel/events/core.c:2859
 perf_event_context_sched_out kernel/events/core.c:3746 [inline]
 __perf_event_task_sched_out+0x286/0x370 kernel/events/core.c:3846
 perf_event_task_sched_out include/linux/perf_event.h:1654 [inline]
 prepare_task_switch kernel/sched/core.c:5045 [inline]
 context_switch kernel/sched/core.c:5201 [inline]
 __schedule+0xbf0/0xcd0 kernel/sched/core.c:6863
 __schedule_loop kernel/sched/core.c:6945 [inline]
 schedule+0x5f/0xd0 kernel/sched/core.c:6960
 schedule_preempt_disabled+0x10/0x20 kernel/sched/core.c:7017
 __mutex_lock_common kernel/locking/mutex.c:692 [inline]
 __mutex_lock+0x4ff/0xe20 kernel/locking/mutex.c:776
 __mutex_lock_slowpath+0xa/0x10 kernel/locking/mutex.c:1065
 mutex_lock+0x89/0x90 kernel/locking/mutex.c:290
 perf_poll+0x180/0x1f0 kernel/events/core.c:6150
 vfs_poll include/linux/poll.h:82 [inline]
 select_poll_one fs/select.c:480 [inline]
 do_select+0x8f1/0xf40 fs/select.c:536
 core_sys_select+0x3dc/0x6e0 fs/select.c:677
 do_pselect fs/select.c:759 [inline]
 __do_sys_pselect6 fs/select.c:798 [inline]
 __se_sys_pselect6+0x213/0x280 fs/select.c:789
 __x64_sys_pselect6+0x78/0x90 fs/select.c:789
 x64_sys_call+0x2e98/0x3000 arch/x86/include/generated/asm/syscalls_64.h:271
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xca/0x2b0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

value changed: 0x000000000038c145 -> 0x00000000003929d3

Reported by Kernel Concurrency Sanitizer on:
CPU: 0 UID: 0 PID: 12005 Comm: syz.4.2772 Tainted: G        W           syzkaller #0 PREEMPT(voluntary) 
Tainted: [W]=WARN
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
==================================================================


5/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
**Initial Analysis of a Data Race in the Perf Subsystem**

Okay, so this report is highlighting a potential data race within the performance monitoring subsystem, specifically involving `perf_mmap_rb` and `perf_event_set_state`. They're both accessing the same memory address, `0xffff88812279f1a0`, which is always a red flag. The fact that the value changed from `0x000000000038c145` to `0x00000000003929d3` strongly suggests we're dealing with either timestamps or some kind of counter, likely related to event accumulation or time tracking, within the `perf` framework. That's a classic scenario for synchronization issues.

The provided stack traces are revealing. The write path is `perf_mmap_rb -> perf_event_update_time` (with an inline expansion). The read path is `perf_event_set_state -> perf_event_update_time (inline) -> __perf_update_times` (also inline). Both paths converge on `perf_event_update_time`, which immediately catches my attention. I need to understand what this function is doing and how it's being accessed concurrently.

My next step is clear: I need to dig into the `kernel/events/core.c` file and zero in on the relevant code around these functions. I’ll start by identifying exactly what data is at that memory address, `0xffff88812279f1a0`. I'll use `codesearch-definition-source` to get the source definition and see where and how `perf_event_update_time` is defined. This should quickly give me the necessary information to diagnose the issue further.



6/2 2026/01/14 13:09 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_update_time SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode: 730:	static void perf_event_update_time(struct perf_event *event)
 731:	{
 732:		u64 now = perf_event_time(event);
 733:	
 734:		__perf_update_times(event, now, &event->total_time_enabled,
 735:						&event->total_time_running);
 736:		event->tstamp = now;
 737:	}
 SourceFile:kernel/events/core.c]

7/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
Here's the summary, tailored to an expert like you:

**Diving into the Timestamp Synchronization**

Okay, so I'm digging into this performance event timestamping issue again. I've pinpointed the write operation – the actual setting of the timestamp – right at line 737: `event->tstamp = now;`.  This is where the `now` value, presumably representing the current time, is being assigned. The crucial read, where we're likely using this timestamp later, is located inside `__perf_update_times`, specifically at line 735. This falls within the broader context of `perf_event_update_time`, which is what I'm most interested in. Now, let's drill down into `__perf_update_times` and understand exactly *how* and *when* this timestamp is being used and what potential race conditions or synchronization issues exist. I suspect this is where the core of the problem lies.



8/2 2026/01/14 13:09 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:__perf_update_times SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode: 715:	static __always_inline void
 716:	__perf_update_times(struct perf_event *event, u64 now, u64 *enabled, u64 *running)
 717:	{
 718:		enum perf_event_state state = __perf_effective_state(event);
 719:		u64 delta = now - event->tstamp;
 720:	
 721:		*enabled = event->total_time_enabled;
 722:		if (state >= PERF_EVENT_STATE_INACTIVE)
 723:			*enabled += delta;
 724:	
 725:		*running = event->total_time_running;
 726:		if (state >= PERF_EVENT_STATE_ACTIVE)
 727:			*running += delta;
 728:	}
 SourceFile:kernel/events/core.c]

9/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
**Tracing the Timestamp Update in the Performance Monitoring Code**

Okay, so the report points me to a read of the timestamp happening within `__perf_update_times` at line 720, specifically calculating `u64 delta = now - event->tstamp;`.  I need to double-check that line number against the source code; it seems like there might be a slight offset, but the key element is definitely accessing `event->tstamp`. The report's corresponding write happens in `perf_event_update_time` at line 737, where `event->tstamp = now;` is performed.

Right, so the memory address `0xffff88812279f1a0` is undoubtedly the address of `event->tstamp`.

Now, I want to trace where these updates are happening. Let's see, the write side involves `perf_event_update_time` being called from `perf_mmap_rb` at offset `0x71c` within the function and `perf_mmap` at offset `0x1ce`. On the read side, `perf_event_set_state` is calling it at offset `0x153` and `event_sched_out` at offset `0x2d4`.

I need to understand what's happening within `perf_mmap_rb` and `perf_event_set_state` to truly grasp the context of these timestamp operations.



10/2 2026/01/14 13:09 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_mmap_rb SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6977:	static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
6978:				unsigned long nr_pages)
6979:	{
6980:		long extra = 0, user_extra = nr_pages;
6981:		struct perf_buffer *rb;
6982:		int rb_flags = 0;
6983:	
6984:		nr_pages -= 1;
6985:	
6986:		/*
6987:		 * If we have rb pages ensure they're a power-of-two number, so we
6988:		 * can do bitmasks instead of modulo.
6989:		 */
6990:		if (nr_pages != 0 && !is_power_of_2(nr_pages))
6991:			return -EINVAL;
6992:	
6993:		WARN_ON_ONCE(event->ctx->parent_ctx);
6994:	
6995:		if (event->rb) {
6996:			if (data_page_nr(event->rb) != nr_pages)
6997:				return -EINVAL;
6998:	
6999:			if (refcount_inc_not_zero(&event->rb->mmap_count)) {
7000:				/*
7001:				 * Success -- managed to mmap() the same buffer
7002:				 * multiple times.
7003:				 */
7004:				perf_mmap_account(vma, user_extra, extra);
7005:				refcount_inc(&event->mmap_count);
7006:				return 0;
7007:			}
7008:	
7009:			/*
7010:			 * Raced against perf_mmap_close()'s
7011:			 * refcount_dec_and_mutex_lock() remove the
7012:			 * event and continue as if !event->rb
7013:			 */
7014:			ring_buffer_attach(event, NULL);
7015:		}
7016:	
7017:		if (!perf_mmap_calc_limits(vma, &user_extra, &extra))
7018:			return -EPERM;
7019:	
7020:		if (vma->vm_flags & VM_WRITE)
7021:			rb_flags |= RING_BUFFER_WRITABLE;
7022:	
7023:		rb = rb_alloc(nr_pages,
7024:			      event->attr.watermark ? event->attr.wakeup_watermark : 0,
7025:			      event->cpu, rb_flags);
7026:	
7027:		if (!rb)
7028:			return -ENOMEM;
7029:	
7030:		refcount_set(&rb->mmap_count, 1);
7031:		rb->mmap_user = get_current_user();
7032:		rb->mmap_locked = extra;
7033:	
7034:		ring_buffer_attach(event, rb);
7035:	
7036:		perf_event_update_time(event);
7037:		perf_event_init_userpage(event);
7038:		perf_event_update_userpage(event);
7039:	
7040:		perf_mmap_account(vma, user_extra, extra);
7041:		refcount_set(&event->mmap_count, 1);
7042:	
7043:		return 0;
7044:	}
 SourceFile:kernel/events/core.c]

11/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
Okay, here's my interpretation of that thought process, summarized as a first-person expert analysis:

**Delving into `perf_event_set_state`**

Alright, so we're looking at `perf_event_set_state`. This function is fundamental to managing the lifecycle of performance monitoring events within the kernel. My understanding is that this is where we control the active or inactive state of these events. Specifically, it seems like we're enabling or disabling the collection of performance data from a given event. Think of it as the on/off switch for the instrumentation.

This function probably interacts heavily with the hardware performance counters, or at least, the abstraction layer that interfaces with them. It likely involves programming the counters, setting up interrupt handlers if necessary, and probably manipulating some internal data structures related to the `perf_event` itself. My immediate instinct is to look at how it interacts with the broader `perf` infrastructure. What locks are involved? What's the context switching overhead? And importantly, how does it handle errors or conflicting requests? I'd want to know how this function ensures data integrity when an event is started or stopped mid-execution. A deeper dive is definitely required.



12/2 2026/01/14 13:09 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_set_state SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode: 747:	static void
 748:	perf_event_set_state(struct perf_event *event, enum perf_event_state state)
 749:	{
 750:		if (event->state == state)
 751:			return;
 752:	
 753:		perf_event_update_time(event);
 754:		/*
 755:		 * If a group leader gets enabled/disabled all its siblings
 756:		 * are affected too.
 757:		 */
 758:		if ((event->state < 0) ^ (state < 0))
 759:			perf_event_update_sibling_time(event);
 760:	
 761:		WRITE_ONCE(event->state, state);
 762:	}
 SourceFile:kernel/events/core.c]

13/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
**Race Condition in perf_event_update_time**

Okay, so I've got two threads that are both calling `perf_event_update_time(event)`. Looking at the code, it seems the core issue is around the shared access to `event->tstamp`, `event->total_time_enabled`, and `event->total_time_running` without any explicit synchronization.

Specifically, `perf_event_update_time` first calls `__perf_update_times`, which reads `event->tstamp` to calculate a `delta`. Then, it updates `event->tstamp` to the current time (`now`).

The first thread, which I'll call the "write" thread, is coming from `perf_mmap_rb`, where it's part of writing to the ring buffer, which eventually updates `event->tstamp`. The second thread, or the "read" thread, is part of `perf_event_set_state` via the scheduler, which reads this `event->tstamp` when it is running.

If these two threads are running concurrently, and the read thread executes `__perf_update_times` while the write thread updates `event->tstamp`, we're staring at a classic data race. Since `event->tstamp` is a `u64`, the write *should* be atomic on x86_64, which is the architecture I'm assuming from the stack trace. The read can therefore see either the old value of `tstamp` or the new value, potentially resulting in an incorrect delta calculation.

Initially, I was worried about torn writes, but the architecture means that should be okay. My primary concern, and the heart of the issue, is in how `__perf_update_times` works. It *overwrites* the `total_time_enabled` and `total_time_running` values with the new calculated values, not increments.

If two threads are updating the time concurrently, they can both calculate a `delta` based on an old `tstamp`, then *both* write these delta values, completely overwriting the values from the other thread, leading to lost updates.

Now, I was looking at how this is being protected; and, at first, it seems there are no locks protecting the calls in `perf_mmap_rb`. However, `perf_mmap_rb` is actually protected by `event->mmap_mutex`. So, any `perf_event_update_time` calls coming from `perf_mmap_rb` should be serialized through that mutex.

But, the other thread comes from a different part of the kernel, specifically through the scheduler, via `perf_event_set_state`, which doesn't seem to be protected by the `mmap_mutex`. So, if the threads are context switching, then it seems that the reads can happen at any time.

Therefore, since the `perf_event_update_time` that is triggered by `perf_event_set_state` isn't protected, there's the possibility of a data race; and since the values are overwritten, not incremented, the time updates are incorrect.



14/2 2026/01/14 13:09 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:event_sched_out SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:2357:	static void
2358:	event_sched_out(struct perf_event *event, struct perf_event_context *ctx)
2359:	{
2360:		struct perf_event_pmu_context *epc = event->pmu_ctx;
2361:		struct perf_cpu_pmu_context *cpc = this_cpc(epc->pmu);
2362:		enum perf_event_state state = PERF_EVENT_STATE_INACTIVE;
2363:	
2364:		// XXX cpc serialization, probably per-cpu IRQ disabled
2365:	
2366:		WARN_ON_ONCE(event->ctx != ctx);
2367:		lockdep_assert_held(&ctx->lock);
2368:	
2369:		if (event->state != PERF_EVENT_STATE_ACTIVE)
2370:			return;
2371:	
2372:		/*
2373:		 * Asymmetry; we only schedule events _IN_ through ctx_sched_in(), but
2374:		 * we can schedule events _OUT_ individually through things like
2375:		 * __perf_remove_from_context().
2376:		 */
2377:		list_del_init(&event->active_list);
2378:	
2379:		perf_pmu_disable(event->pmu);
2380:	
2381:		event->pmu->del(event, 0);
2382:		event->oncpu = -1;
2383:	
2384:		if (event->pending_disable) {
2385:			event->pending_disable = 0;
2386:			perf_cgroup_event_disable(event, ctx);
2387:			state = PERF_EVENT_STATE_OFF;
2388:		}
2389:	
2390:		perf_event_set_state(event, state);
2391:	
2392:		if (!is_software_event(event))
2393:			cpc->active_oncpu--;
2394:		if (is_event_in_freq_mode(event)) {
2395:			ctx->nr_freq--;
2396:			epc->nr_freq--;
2397:		}
2398:		if (event->attr.exclusive || !cpc->active_oncpu)
2399:			cpc->exclusive = 0;
2400:	
2401:		perf_pmu_enable(event->pmu);
2402:	}
 SourceFile:kernel/events/core.c]

15/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
**Diving into the Perf Event Concurrency Model**

Okay, so `event_sched_out` calls `lockdep_assert_held(&ctx->lock)`, which means `perf_event_set_state` is definitely protected by that `ctx->lock`. I'm trying to figure out how this plays with `perf_mmap_rb`, which I know is protected by `mmap_mutex`.

The question is, does `perf_mmap_rb` *also* hold `ctx->lock`? Let's trace back to `perf_mmap`. I see the `mmap_mutex` being locked and unlocked there, around the call to `perf_mmap_rb`, but I don't see anything explicitly locking `ctx->lock`. So, I'm not seeing any direct evidence of `ctx->lock` being held in that code path.

To be absolutely sure, I should check the functions that are called by `perf_mmap_rb`, to look for that lock being acquired. Inside `perf_mmap_rb`, there are a few key calls: `ring_buffer_attach` and `perf_event_update_time`. I think `ring_buffer_attach` is the most interesting one to examine, given the context. I'll start there.



16/2 2026/01/14 13:09 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:ring_buffer_attach SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:5169:	static void ring_buffer_attach(struct perf_event *event,
5170:				       struct perf_buffer *rb);
 SourceFile:kernel/events/core.c]

17/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
Okay, here's the summary, assuming I'm an expert in my field:

**Initial Assessment**

Right, okay, I see this… or rather, I *think* I see this. My initial gut reaction is, "Wait a minute, is this just a prototype, or is there a fundamental definition I'm missing here?" I need to quickly determine if what I'm looking at is a finished product that simply needs fine tuning, or if there's a more basic conceptual misunderstanding at play. Time to dig deeper, before making any assumptions.



18/2 2026/01/14 13:09 tool codesearch-file-index
0m Model:
unknown

Args:
map[SourceFile:kernel/events/core.c]

Results:
map[Entities:[map[Kind:function Name:___perf_sw_event] map[Kind:function Name:__cond_set] map[Kind:function Name:__ctx_time_update] map[Kind:function Name:__detach_global_ctx_data] map[Kind:function Name:__detach_global_ctx_data] map[Kind:function Name:__do_sys_perf_event_open] map[Kind:function Name:__do_sys_perf_event_open] map[Kind:function Name:__event_disable] map[Kind:function Name:__event_disable] map[Kind:function Name:__find_swevent_head] map[Kind:function Name:__free___free_event] map[Kind:function Name:__free_event] map[Kind:function Name:__free_perf_ctx_data_rcu] map[Kind:function Name:__free_pmu_unregister] map[Kind:function Name:__group_cmp] map[Kind:function Name:__group_cmp_ignore_cgroup] map[Kind:function Name:__group_less] map[Kind:function Name:__heap_add] map[Kind:function Name:__ia32_sys_perf_event_open] map[Kind:function Name:__link_epc] map[Kind:function Name:__perf_addr_filters_adjust] map[Kind:function Name:__perf_cgroup_move] map[Kind:function Name:__perf_ctx_lock] map[Kind:function Name:__perf_ctx_unlock] map[Kind:function Name:__perf_effective_state] map[Kind:function Name:__perf_event__output_id_sample] map[Kind:function Name:__perf_event_account_interrupt] map[Kind:function Name:__perf_event_aux_pause] map[Kind:function Name:__perf_event_disable] map[Kind:function Name:__perf_event_enable] map[Kind:function Name:__perf_event_exit_context] map[Kind:function Name:__perf_event_header__init_id] map[Kind:function Name:__perf_event_header_size] map[Kind:function Name:__perf_event_init_context] map[Kind:function Name:__perf_event_output] map[Kind:function Name:__perf_event_output_stop] map[Kind:function Name:__perf_event_overflow] map[Kind:function Name:__perf_event_period] map[Kind:function Name:__perf_event_read] map[Kind:function Name:__perf_event_read_cpu] map[Kind:function Name:__perf_event_read_size] map[Kind:function Name:__perf_event_read_value] map[Kind:function Name:__perf_event_set_bpf_prog] map[Kind:function Name:__perf_event_set_bpf_prog] map[Kind:function Name:__perf_event_stop] map[Kind:function Name:__perf_event_sync_stat] map[Kind:function Name:__perf_event_task_sched_in] map[Kind:function Name:__perf_event_task_sched_out] map[Kind:function Name:__perf_init_event_pmu_context] map[Kind:function Name:__perf_install_in_context] map[Kind:function Name:__perf_mux_hrtimer_init] map[Kind:function Name:__perf_pending_disable] map[Kind:function Name:__perf_pmu_install] map[Kind:function Name:__perf_pmu_install_event] map[Kind:function Name:__perf_pmu_output_stop] map[Kind:function Name:__perf_pmu_remove] map[Kind:function Name:__perf_pmu_sched_task] map[Kind:function Name:__perf_read] map[Kind:function Name:__perf_read_group_add] map[Kind:function Name:__perf_remove_from_context] map[Kind:function Name:__perf_sw_event] map[Kind:function Name:__perf_tp_event_target_task] map[Kind:function Name:__perf_update_times] map[Kind:function Name:__pmu_ctx_sched_in] map[Kind:function Name:__pmu_ctx_sched_out] map[Kind:function Name:__pmu_detach_event] map[Kind:function Name:__se_sys_perf_event_open] map[Kind:function Name:__update_cgrp_time] map[Kind:function Name:__update_context_time] map[Kind:function Name:__x64_sys_perf_event_open] map[Kind:function Name:_free_event] map[Kind:function Name:_perf_event_disable] map[Kind:function Name:_perf_event_enable] map[Kind:function Name:_perf_event_period] map[Kind:function Name:_perf_event_refresh] map[Kind:function Name:_perf_event_reset] map[Kind:function Name:_perf_ioctl] map[Kind:function Name:account_event] map[Kind:function Name:account_freq_event] map[Kind:function Name:account_freq_event_nohz] map[Kind:function Name:account_pmu_sb_event] map[Kind:function Name:add_event_to_ctx] map[Kind:function Name:add_event_to_groups] map[Kind:function Name:alloc_perf_context] map[Kind:function Name:alloc_perf_ctx_data] map[Kind:function Name:arch_perf_update_userpage] map[Kind:function Name:attach_global_ctx_data] map[Kind:function Name:attach_perf_ctx_data] map[Kind:function Name:attach_sb_event] map[Kind:function Name:attach_task_ctx_data] map[Kind:function Name:bpf_overflow_handler] map[Kind:function Name:calc_timer_values] map[Kind:function Name:class_perf_ctx_lock_constructor] map[Kind:function Name:class_perf_ctx_lock_destructor] map[Kind:function Name:context_equiv] map[Kind:function Name:cpu_clock_event_add] map[Kind:function Name:cpu_clock_event_del] map[Kind:function Name:cpu_clock_event_init] map[Kind:function Name:cpu_clock_event_read] map[Kind:function Name:cpu_clock_event_start] map[Kind:function Name:cpu_clock_event_stop] map[Kind:function Name:cpu_clock_event_update] map[Kind:function Name:cpu_function_call] map[Kind:function Name:cpumask_show] map[Kind:function Name:ctx_event_to_rotate] map[Kind:function Name:ctx_resched] map[Kind:function Name:ctx_sched_in] map[Kind:function Name:ctx_sched_in] map[Kind:function Name:ctx_sched_out] map[Kind:function Name:ctx_sched_out] map[Kind:function Name:ctx_time_freeze] map[Kind:function Name:ctx_time_update] map[Kind:function Name:ctx_time_update_event] map[Kind:function Name:del_event_from_groups] map[Kind:function Name:detach_global_ctx_data] map[Kind:function Name:detach_perf_ctx_data] map[Kind:function Name:detach_sb_event] map[Kind:function Name:detach_task_ctx_data] map[Kind:function Name:do_perf_sw_event] map[Kind:function Name:event_cgroup] map[Kind:function Name:event_enable_on_exec] map[Kind:function Name:event_filter_match] map[Kind:function Name:event_function] map[Kind:function Name:event_function_call] map[Kind:function Name:event_function_local] map[Kind:function Name:event_sched_in] map[Kind:function Name:event_sched_out] map[Kind:function Name:event_update_userpage] map[Kind:function Name:exclusive_event_destroy] map[Kind:function Name:exclusive_event_init] map[Kind:function Name:exclusive_event_installable] map[Kind:function Name:exclusive_event_installable] map[Kind:function Name:exclusive_event_match] map[Kind:function Name:find_get_context] map[Kind:function Name:find_get_pmu_context] map[Kind:function Name:find_lively_task_by_vpid] map[Kind:function Name:find_swevent_head] map[Kind:function Name:find_swevent_head_rcu] map[Kind:function Name:free_cpc_rcu] map[Kind:function Name:free_ctx] map[Kind:function Name:free_epc_rcu] map[Kind:function Name:free_event] map[Kind:function Name:free_event_rcu] map[Kind:function Name:free_filters_list] map[Kind:function Name:free_perf_ctx_data] map[Kind:function Name:get_ctx] map[Kind:function Name:get_event_groups] map[Kind:function Name:get_event_list] map[Kind:function Name:get_event_type] map[Kind:function Name:get_pmu_ctx] map[Kind:function Name:group_can_go_on] map[Kind:function Name:group_sched_in] map[Kind:function Name:group_sched_out] map[Kind:function Name:group_update_userpage] map[Kind:function Name:has_extended_regs] map[Kind:function Name:has_inherit_and_sample_read] map[Kind:function Name:idr_cmpxchg] map[Kind:function Name:inherit_event] map[Kind:function Name:inherit_group] map[Kind:function Name:inherit_task_group] map[Kind:function Name:init_event_group] map[Kind:function Name:init_events_core_sysctls] map[Kind:function Name:is_cgroup_event] map[Kind:function Name:is_event_hup] map[Kind:function Name:is_event_in_freq_mode] map[Kind:function Name:is_kernel_event] map[Kind:function Name:is_orphaned_event] map[Kind:function Name:is_perf_file] map[Kind:function Name:is_sb_event] map[Kind:function Name:list_add_event] map[Kind:function Name:list_del_event] map[Kind:function Name:map_range] map[Kind:function Name:merge_sched_in] map[Kind:function Name:mutex_lock_double] map[Kind:function Name:nr_addr_filters_show] map[Kind:function Name:perf_addr_filter_apply] map[Kind:function Name:perf_addr_filter_match] map[Kind:function Name:perf_addr_filter_new] map[Kind:function Name:perf_addr_filter_vma_adjust] map[Kind:function Name:perf_addr_filters_adjust] map[Kind:function Name:perf_addr_filters_splice] map[Kind:function Name:perf_adjust_freq_unthr_context] map[Kind:function Name:perf_adjust_freq_unthr_events] map[Kind:function Name:perf_adjust_period] map[Kind:function Name:perf_allow_kernel] map[Kind:function Name:perf_allow_kernel] map[Kind:function Name:perf_assert_pmu_disabled] map[Kind:function Name:perf_aux_output_match] map[Kind:function Name:perf_aux_sample_output] map[Kind:function Name:perf_bp_event] map[Kind:function Name:perf_calculate_period] map[Kind:function Name:perf_callchain] map[Kind:function Name:perf_callchain_deferred_output] map[Kind:function Name:perf_cgroup_attach] map[Kind:function Name:perf_cgroup_connect] map[Kind:function Name:perf_cgroup_css_alloc] map[Kind:function Name:perf_cgroup_css_free] map[Kind:function Name:perf_cgroup_css_online] map[Kind:function Name:perf_cgroup_ensure_storage] map[Kind:function Name:perf_cgroup_event_disable] map[Kind:function Name:perf_cgroup_event_enable] map[Kind:function Name:perf_cgroup_event_time] map[Kind:function Name:perf_cgroup_event_time_now] map[Kind:function Name:perf_cgroup_match] map[Kind:function Name:perf_cgroup_set_timestamp] map[Kind:function Name:perf_cgroup_switch] map[Kind:function Name:perf_check_permission] map[Kind:function Name:perf_child_detach] map[Kind:function Name:perf_clock] map[Kind:function Name:perf_compat_ioctl] map[Kind:function Name:perf_copy_attr] map[Kind:function Name:perf_copy_attr] map[Kind:function Name:perf_cpu_task_ctx] map[Kind:function Name:perf_cpu_time_max_percent_handler] map[Kind:function Name:perf_ctx_disable] map[Kind:function Name:perf_ctx_enable] map[Kind:function Name:perf_ctx_lock] map[Kind:function Name:perf_ctx_sched_task_cb] map[Kind:function Name:perf_ctx_unlock] map[Kind:function Name:perf_detach_cgroup] map[Kind:function Name:perf_duration_warn] map[Kind:function Name:perf_event__header_size] map[Kind:function Name:perf_event__id_header_size] map[Kind:function Name:perf_event__output_id_sample] map[Kind:function Name:perf_event__state_init] map[Kind:function Name:perf_event_account_interrupt] map[Kind:function Name:perf_event_addr_filters_apply] map[Kind:function Name:perf_event_addr_filters_exec] map[Kind:function Name:perf_event_addr_filters_sync] map[Kind:function Name:perf_event_addr_filters_sync] map[Kind:function Name:perf_event_alloc] map[Kind:function Name:perf_event_alloc_task_data] map[Kind:function Name:perf_event_attrs] map[Kind:function Name:perf_event_aux_event] map[Kind:function Name:perf_event_aux_pause] map[Kind:function Name:perf_event_bpf_emit_ksymbols] map[Kind:function Name:perf_event_bpf_event] map[Kind:function Name:perf_event_bpf_match] map[Kind:function Name:perf_event_bpf_output] map[Kind:function Name:perf_event_cgroup] map[Kind:function Name:perf_event_cgroup_match] map[Kind:function Name:perf_event_cgroup_output] map[Kind:function Name:perf_event_check_period] map[Kind:function Name:perf_event_clear_cpumask] map[Kind:function Name:perf_event_clock] map[Kind:function Name:perf_event_comm] map[Kind:function Name:perf_event_comm_event] map[Kind:function Name:perf_event_comm_match] map[Kind:function Name:perf_event_comm_output] map[Kind:function Name:perf_event_context_sched_in] map[Kind:function Name:perf_event_context_sched_out] map[Kind:function Name:perf_event_count] map[Kind:function Name:perf_event_create_kernel_counter] map[Kind:function Name:perf_event_create_kernel_counter] map[Kind:function Name:perf_event_ctx_lock] map[Kind:function Name:perf_event_ctx_lock_nested] map[Kind:function Name:perf_event_ctx_unlock] map[Kind:function Name:perf_event_delayed_put] map[Kind:function Name:perf_event_disable] map[Kind:function Name:perf_event_disable] map[Kind:function Name:perf_event_disable_inatomic] map[Kind:function Name:perf_event_disable_local] map[Kind:function Name:perf_event_enable] map[Kind:function Name:perf_event_enable] map[Kind:function Name:perf_event_enable_on_exec] map[Kind:function Name:perf_event_exec] map[Kind:function Name:perf_event_exit_cpu] map[Kind:function Name:perf_event_exit_cpu_context] map[Kind:function Name:perf_event_exit_event] map[Kind:function Name:perf_event_exit_event] map[Kind:function Name:perf_event_exit_task] map[Kind:function Name:perf_event_exit_task_context] map[Kind:function Name:perf_event_for_each] map[Kind:function Name:perf_event_for_each_child] map[Kind:function Name:perf_event_fork] map[Kind:function Name:perf_event_free_bpf_handler] map[Kind:function Name:perf_event_free_bpf_prog] map[Kind:function Name:perf_event_free_filter] map[Kind:function Name:perf_event_free_filter] map[Kind:function Name:perf_event_free_task] map[Kind:function Name:perf_event_get] map[Kind:function Name:perf_event_groups_cmp] map[Kind:function Name:perf_event_groups_delete] map[Kind:function Name:perf_event_groups_first] map[Kind:function Name:perf_event_groups_init] map[Kind:function Name:perf_event_groups_insert] map[Kind:function Name:perf_event_groups_next] map[Kind:function Name:perf_event_header__init_id] map[Kind:function Name:perf_event_idx_default] map[Kind:function Name:perf_event_index] map[Kind:function Name:perf_event_init] map[Kind:function Name:perf_event_init_all_cpus] map[Kind:function Name:perf_event_init_context] map[Kind:function Name:perf_event_init_cpu] map[Kind:function Name:perf_event_init_task] map[Kind:function Name:perf_event_init_userpage] map[Kind:function Name:perf_event_is_tracing] map[Kind:function Name:perf_event_itrace_started] map[Kind:function Name:perf_event_ksymbol] map[Kind:function Name:perf_event_ksymbol_match] map[Kind:function Name:perf_event_ksymbol_output] map[Kind:function Name:perf_event_max_sample_rate_handler] map[Kind:function Name:perf_event_mmap] map[Kind:function Name:perf_event_mmap_event] map[Kind:function Name:perf_event_mmap_match] map[Kind:function Name:perf_event_mmap_output] map[Kind:function Name:perf_event_modify_attr] map[Kind:function Name:perf_event_modify_breakpoint] map[Kind:function Name:perf_event_modify_copy_attr] map[Kind:function Name:perf_event_mux_interval_ms_show] map[Kind:function Name:perf_event_mux_interval_ms_store] map[Kind:function Name:perf_event_namespaces] map[Kind:function Name:perf_event_namespaces_match] map[Kind:function Name:perf_event_namespaces_output] map[Kind:function Name:perf_event_nop_int] map[Kind:function Name:perf_event_output] map[Kind:function Name:perf_event_output_backward] map[Kind:function Name:perf_event_output_forward] map[Kind:function Name:perf_event_overflow] map[Kind:function Name:perf_event_parse_addr_filter] map[Kind:function Name:perf_event_pause] map[Kind:function Name:perf_event_pause] map[Kind:function Name:perf_event_period] map[Kind:function Name:perf_event_period] map[Kind:function Name:perf_event_pid] map[Kind:function Name:perf_event_pid_type] map[Kind:function Name:perf_event_print_debug] map[Kind:function Name:perf_event_read] map[Kind:function Name:perf_event_read_event] map[Kind:function Name:perf_event_read_local] map[Kind:function Name:perf_event_read_value] map[Kind:function Name:perf_event_read_value] map[Kind:function Name:perf_event_refresh] map[Kind:function Name:perf_event_refresh] map[Kind:function Name:perf_event_release_kernel] map[Kind:function Name:perf_event_release_kernel] map[Kind:function Name:perf_event_remove_on_exec] map[Kind:function Name:perf_event_sched_in] map[Kind:function Name:perf_event_set_addr_filter] map[Kind:function Name:perf_event_set_bpf_handler] map[Kind:function Name:perf_event_set_bpf_prog] map[Kind:function Name:perf_event_set_clock] map[Kind:function Name:perf_event_set_filter] map[Kind:function Name:perf_event_set_filter] map[Kind:function Name:perf_event_set_output] map[Kind:function Name:perf_event_set_output] map[Kind:function Name:perf_event_set_state] map[Kind:function Name:perf_event_setup_cpumask] map[Kind:function Name:perf_event_stop] map[Kind:function Name:perf_event_switch] map[Kind:function Name:perf_event_switch] map[Kind:function Name:perf_event_switch_match] map[Kind:function Name:perf_event_switch_output] map[Kind:function Name:perf_event_sync_stat] map[Kind:function Name:perf_event_sysfs_init] map[Kind:function Name:perf_event_sysfs_show] map[Kind:function Name:perf_event_sysfs_show] map[Kind:function Name:perf_event_task] map[Kind:function Name:perf_event_task_disable] map[Kind:function Name:perf_event_task_enable] map[Kind:function Name:perf_event_task_match] map[Kind:function Name:perf_event_task_output] map[Kind:function Name:perf_event_task_tick] map[Kind:function Name:perf_event_text_poke] map[Kind:function Name:perf_event_text_poke_match] map[Kind:function Name:perf_event_text_poke_output] map[Kind:function Name:perf_event_throttle] map[Kind:function Name:perf_event_throttle_group] map[Kind:function Name:perf_event_tid] map[Kind:function Name:perf_event_time] map[Kind:function Name:perf_event_time] map[Kind:function Name:perf_event_time_now] map[Kind:function Name:perf_event_unthrottle] map[Kind:function Name:perf_event_unthrottle_group] map[Kind:function Name:perf_event_update_sibling_time] map[Kind:function Name:perf_event_update_time] map[Kind:function Name:perf_event_update_userpage] map[Kind:function Name:perf_event_update_userpage] map[Kind:function Name:perf_event_validate_size] map[Kind:function Name:perf_event_wakeup] map[Kind:function Name:perf_exclude_event] map[Kind:function Name:perf_fasync] map[Kind:function Name:perf_fill_ns_link_info] map[Kind:function Name:perf_free_addr_filters] map[Kind:function Name:perf_free_addr_filters] map[Kind:function Name:perf_free_ctx_data_rcu] map[Kind:function Name:perf_get_aux_event] map[Kind:function Name:perf_get_event] map[Kind:function Name:perf_get_page_size] map[Kind:function Name:perf_get_pgtable_size] map[Kind:function Name:perf_group_attach] map[Kind:function Name:perf_group_detach] map[Kind:function Name:perf_init_event] map[Kind:function Name:perf_install_in_context] map[Kind:function Name:perf_instruction_pointer] map[Kind:function Name:perf_ioctl] map[Kind:function Name:perf_iterate_ctx] map[Kind:function Name:perf_iterate_sb] map[Kind:function Name:perf_iterate_sb_cpu] map[Kind:function Name:perf_less_group_idx] map[Kind:function Name:perf_lock_task_context] map[Kind:function Name:perf_log_itrace_start] map[Kind:function Name:perf_log_itrace_start] map[Kind:function Name:perf_log_lost_samples] map[Kind:function Name:perf_log_throttle] map[Kind:function Name:perf_log_throttle] map[Kind:function Name:perf_misc_flags] map[Kind:function Name:perf_mmap] map[Kind:function Name:perf_mmap_account] map[Kind:function Name:perf_mmap_aux] map[Kind:function Name:perf_mmap_calc_limits] map[Kind:function Name:perf_mmap_close] map[Kind:function Name:perf_mmap_may_split] map[Kind:function Name:perf_mmap_open] map[Kind:function Name:perf_mmap_pfn_mkwrite] map[Kind:function Name:perf_mmap_rb] map[Kind:function Name:perf_mux_hrtimer_handler] map[Kind:function Name:perf_mux_hrtimer_restart] map[Kind:function Name:perf_mux_hrtimer_restart_ipi] map[Kind:function Name:perf_need_aux_event] map[Kind:function Name:perf_output_read] map[Kind:function Name:perf_output_read_group] map[Kind:function Name:perf_output_read_one] map[Kind:function Name:perf_output_sample] map[Kind:function Name:perf_output_sample_regs] map[Kind:function Name:perf_output_sample_ustack] map[Kind:function Name:perf_pending_disable] map[Kind:function Name:perf_pending_irq] map[Kind:function Name:perf_pending_task] map[Kind:function Name:perf_pin_task_context] map[Kind:function Name:perf_pmu_cancel_txn] map[Kind:function Name:perf_pmu_commit_txn] map[Kind:function Name:perf_pmu_disable] map[Kind:function Name:perf_pmu_enable] map[Kind:function Name:perf_pmu_free] map[Kind:function Name:perf_pmu_migrate_context] map[Kind:function Name:perf_pmu_migrate_context] map[Kind:function Name:perf_pmu_nop_int] map[Kind:function Name:perf_pmu_nop_txn] map[Kind:function Name:perf_pmu_nop_void] map[Kind:function Name:perf_pmu_output_stop] map[Kind:function Name:perf_pmu_output_stop] map[Kind:function Name:perf_pmu_read] map[Kind:function Name:perf_pmu_register] map[Kind:function Name:perf_pmu_register] map[Kind:function Name:perf_pmu_resched] map[Kind:function Name:perf_pmu_sched_task] map[Kind:function Name:perf_pmu_snapshot_aux] map[Kind:function Name:perf_pmu_start_txn] map[Kind:function Name:perf_pmu_unregister] map[Kind:function Name:perf_pmu_unregister] map[Kind:function Name:perf_poll] map[Kind:function Name:perf_prepare_header] map[Kind:function Name:perf_prepare_sample] map[Kind:function Name:perf_prepare_sample_aux] map[Kind:function Name:perf_put_aux_event] map[Kind:function Name:perf_read] map[Kind:function Name:perf_read_group] map[Kind:function Name:perf_read_one] map[Kind:function Name:perf_reboot] map[Kind:function Name:perf_release] map[Kind:function Name:perf_remove_from_context] map[Kind:function Name:perf_remove_from_owner] map[Kind:function Name:perf_remove_from_owner] map[Kind:function Name:perf_report_aux_output_id] map[Kind:function Name:perf_report_aux_output_id] map[Kind:function Name:perf_rotate_context] map[Kind:function Name:perf_rotate_context] map[Kind:function Name:perf_sample_event_took] map[Kind:function Name:perf_sample_regs_intr] map[Kind:function Name:perf_sample_regs_user] map[Kind:function Name:perf_sample_ustack_size] map[Kind:function Name:perf_sched_cb_dec] map[Kind:function Name:perf_sched_cb_inc] map[Kind:function Name:perf_sched_delayed] map[Kind:function Name:perf_sched_delayed] map[Kind:function Name:perf_scope_cpu_topology_cpumask] map[Kind:function Name:perf_scope_cpu_topology_cpumask] map[Kind:function Name:perf_scope_cpumask] map[Kind:function Name:perf_sigtrap] map[Kind:function Name:perf_swevent_add] map[Kind:function Name:perf_swevent_cancel_hrtimer] map[Kind:function Name:perf_swevent_del] map[Kind:function Name:perf_swevent_destroy_hrtimer] map[Kind:function Name:perf_swevent_event] map[Kind:function Name:perf_swevent_get_recursion_context] map[Kind:function Name:perf_swevent_get_recursion_context] map[Kind:function Name:perf_swevent_hrtimer] map[Kind:function Name:perf_swevent_init] map[Kind:function Name:perf_swevent_init_cpu] map[Kind:function Name:perf_swevent_init_hrtimer] map[Kind:function Name:perf_swevent_match] map[Kind:function Name:perf_swevent_overflow] map[Kind:function Name:perf_swevent_put_recursion_context] map[Kind:function Name:perf_swevent_read] map[Kind:function Name:perf_swevent_set_period] map[Kind:function Name:perf_swevent_start] map[Kind:function Name:perf_swevent_start_hrtimer] map[Kind:function Name:perf_swevent_stop] map[Kind:function Name:perf_tp_event] map[Kind:function Name:perf_tp_event] map[Kind:function Name:perf_tp_event_init] map[Kind:function Name:perf_tp_event_match] map[Kind:function Name:perf_tp_event_target_task] map[Kind:function Name:perf_tp_filter_match] map[Kind:function Name:perf_tp_register] map[Kind:function Name:perf_trace_run_bpf_submit] map[Kind:function Name:perf_trace_run_bpf_submit] map[Kind:function Name:perf_try_init_event] map[Kind:function Name:perf_unpin_context] map[Kind:function Name:perf_unwind_deferred_callback] map[Kind:function Name:perf_uprobe_event_init] map[Kind:function Name:perf_uprobe_event_init] map[Kind:function Name:perf_ustack_task_size] map[Kind:function Name:perf_virt_to_phys] map[Kind:function Name:pmu_detach_event] map[Kind:function Name:pmu_detach_events] map[Kind:function Name:pmu_dev_alloc] map[Kind:function Name:pmu_dev_is_visible] map[Kind:function Name:pmu_dev_release] map[Kind:function Name:pmu_empty] map[Kind:function Name:pmu_get_event] map[Kind:function Name:pmu_groups_sched_in] map[Kind:function Name:primary_event_id] map[Kind:function Name:put_ctx] map[Kind:function Name:put_event] map[Kind:function Name:put_event] map[Kind:function Name:put_pmu_ctx] map[Kind:function Name:ref_ctr_offset_show] map[Kind:function Name:remote_function] map[Kind:function Name:retprobe_show] map[Kind:function Name:ring_buffer_attach] map[Kind:function Name:ring_buffer_attach] map[Kind:function Name:ring_buffer_get] map[Kind:function Name:ring_buffer_put] map[Kind:function Name:ring_buffer_wakeup] map[Kind:function Name:rotate_ctx] map[Kind:function Name:sample_is_allowed] map[Kind:function Name:should_sample_guest] map[Kind:function Name:sw_perf_event_destroy] map[Kind:function Name:swevent_hash] map[Kind:function Name:swevent_hlist_deref] map[Kind:function Name:swevent_hlist_get] map[Kind:function Name:swevent_hlist_get_cpu] map[Kind:function Name:swevent_hlist_put] map[Kind:function Name:swevent_hlist_put_cpu] map[Kind:function Name:swevent_hlist_release] map[Kind:function Name:sync_child_event] map[Kind:function Name:task_clock_event_add] map[Kind:function Name:task_clock_event_del] map[Kind:function Name:task_clock_event_init] map[Kind:function Name:task_clock_event_read] map[Kind:function Name:task_clock_event_start] map[Kind:function Name:task_clock_event_stop] map[Kind:function Name:task_clock_event_update] map[Kind:function Name:task_ctx_sched_out] map[Kind:function Name:task_function_call] map[Kind:function Name:this_cpc] map[Kind:function Name:tp_perf_event_destroy] map[Kind:function Name:type_show] map[Kind:function Name:unaccount_event] map[Kind:function Name:unaccount_freq_event] map[Kind:function Name:unaccount_freq_event_nohz] map[Kind:function Name:unaccount_pmu_sb_event] map[Kind:function Name:unclone_ctx] map[Kind:function Name:update_cgrp_time_from_cpuctx] map[Kind:function Name:update_cgrp_time_from_event] map[Kind:function Name:update_context_time] map[Kind:function Name:update_context_time] map[Kind:function Name:update_perf_cpu_limits] map[Kind:function Name:visit_groups_merge]] Missing:false]

19/2 2026/01/14 13:09 llm expert
0m Model:
unknown

Thoughts:
Okay, here's the summary, assuming I'm an expert in the field and approaching this with a specific mindset:

**Analyzing the `ring_buffer_attach` Function**

Right, before I dive too deep into anything else, I need to make sure I understand the fundamentals. My first thought is to zero in on that `ring_buffer_attach` function. This is likely a critical piece of the puzzle, probably dealing with attaching a ring buffer, which is a common and often efficient data structure. I'll need to confirm what context this is in. Is it hardware, software, a specific library? I have to understand its role in memory management.

I'm thinking about the implications. Is this function responsible for allocation, initialization, linking, or all of the above? I need to analyze how it handles concurrency. What are the synchronization primitives involved? What are the potential pitfalls? Are there race conditions I need to consider? Knowing the details of the function will reveal the entire design of this section of code.



20/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:ring_buffer_attach SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:5169:	static void ring_buffer_attach(struct perf_event *event,
5170:				       struct perf_buffer *rb);
 SourceFile:kernel/events/core.c]

21/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Debugging a Prototype: Finding the "Real Deal"**

Okay, hold on a second. This code I'm looking at… it's still just a prototype, isn't it? Before I dig in any deeper, I need to nail down the actual definition. Let's see... I'll use `grep`, or maybe just scroll a bit further down in the file. No, wait... the `codesearch-file-index` output is helpful, saying `ring_buffer_attach` shows up twice in `kernel/events/core.c`. Hmm, maybe one is a declaration.

Aha! There it is, line 5169, I think I've found one instance of it. Now I see it. It looks like there might be another, so let's check it. I should pull a few more lines of context around that line 5169, just to be sure I've got the right `ring_buffer_attach`.



22/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:ring_buffer_attach SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:5169:	static void ring_buffer_attach(struct perf_event *event,
5170:				       struct perf_buffer *rb);
 SourceFile:kernel/events/core.c]

23/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Diving Deep into a Potential Race Condition**

Okay, I'm on it. Initially, I considered using a code search tool with some rudimentary queries, but I already have a suspicion of the specific file, `core.c`, so I'll just check that directly.

I'm focusing in on `perf_event_update_time`, and based on the context, I'll attempt to understand what's happening around this specific function. Let me see... I see the function definition, and it looks like this:

```c
 730:	static void perf_event_update_time(struct perf_event *event)
 731:	{
 732:		u64 now = perf_event_time(event);
 733:	
 734:		__perf_update_times(event, now, &event->total_time_enabled,
 735:						&event->total_time_running);
 736:		event->tstamp = now;
 737:	}
```

Now, this is called by `perf_mmap_rb` (line 7036) and `perf_event_set_state` (line 753). Aha! I think I see the issue now. There appears to be a race between these two callers.

The race specifically focuses on the following:
1. `event->tstamp = now;` in `perf_event_update_time` (called by `perf_mmap_rb`)
2. `u64 delta = now - event->tstamp;` in `__perf_update_times` (called by `perf_event_update_time` which is called by `perf_event_set_state`)

Both are calling `perf_event_update_time`, and if they happen concurrently, they both read and write `event->tstamp`, `event->total_time_enabled`, and `event->total_time_running`. But let's see, if `perf_mmap_rb` holds `event->mmap_mutex` and `perf_event_set_state` holds `ctx->lock` and they are different locks, then yes they *could* be concurrent. I will check.

Let me revisit `perf_mmap_rb`. It calls `ring_buffer_attach(event, rb);`. And `ring_buffer_attach` usually involves changing `event->rb`. The report is that the race is on `tstamp`, and the reported change, `0x000000000038c145 -> 0x00000000003929d3`, looks like values of `perf_event_time(event)`. If these updates happen concurrently, it can lead to incorrect timing information, such as `total_time_enabled` being updated with overlapping intervals, or updates being lost.

Specifically, in `__perf_update_times`:

```c
 718:		enum perf_event_state state = __perf_effective_state(event);
 719:		u64 delta = now - event->tstamp;
 720:	
 721:		*enabled = event->total_time_enabled;
 722:		if (state >= PERF_EVENT_STATE_INACTIVE)
 723:			*enabled += delta;
...
```

And in `perf_event_update_time`:

```c
 734:		__perf_update_times(event, now, &event->total_time_enabled,
 735:						&event->total_time_running);
 736:		event->tstamp = now;
```

This *is not* atomic. Suppose two threads are racing:
*   **T1:** `now1 = perf_event_time(event)`
*   **T2:** `now2 = perf_event_time(event)`
*   **T1:** `delta1 = now1 - event->tstamp`
*   **T1:** `event->total_time_enabled += delta1`
*   **T2:** `delta2 = now2 - event->tstamp` (if T1 hasn't updated tstamp yet, delta2 is too large!)
*   **T2:** `event->total_time_enabled += delta2` (we add the same interval twice!)
*   **T1:** `event->tstamp = now1`
*   **T2:** `event->t


24/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_mmap SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:7122:	static int perf_mmap(struct file *file, struct vm_area_struct *vma)
7123:	{
7124:		struct perf_event *event = file->private_data;
7125:		unsigned long vma_size, nr_pages;
7126:		mapped_f mapped;
7127:		int ret;
7128:	
7129:		/*
7130:		 * Don't allow mmap() of inherited per-task counters. This would
7131:		 * create a performance issue due to all children writing to the
7132:		 * same rb.
7133:		 */
7134:		if (event->cpu == -1 && event->attr.inherit)
7135:			return -EINVAL;
7136:	
7137:		if (!(vma->vm_flags & VM_SHARED))
7138:			return -EINVAL;
7139:	
7140:		ret = security_perf_event_read(event);
7141:		if (ret)
7142:			return ret;
7143:	
7144:		vma_size = vma->vm_end - vma->vm_start;
7145:		nr_pages = vma_size / PAGE_SIZE;
7146:	
7147:		if (nr_pages > INT_MAX)
7148:			return -ENOMEM;
7149:	
7150:		if (vma_size != PAGE_SIZE * nr_pages)
7151:			return -EINVAL;
7152:	
7153:		scoped_guard (mutex, &event->mmap_mutex) {
7154:			/*
7155:			 * This relies on __pmu_detach_event() taking mmap_mutex after marking
7156:			 * the event REVOKED. Either we observe the state, or __pmu_detach_event()
7157:			 * will detach the rb created here.
7158:			 */
7159:			if (event->state <= PERF_EVENT_STATE_REVOKED)
7160:				return -ENODEV;
7161:	
7162:			if (vma->vm_pgoff == 0)
7163:				ret = perf_mmap_rb(vma, event, nr_pages);
7164:			else
7165:				ret = perf_mmap_aux(vma, event, nr_pages);
7166:			if (ret)
7167:				return ret;
7168:		}
7169:	
7170:		/*
7171:		 * Since pinned accounting is per vm we cannot allow fork() to copy our
7172:		 * vma.
7173:		 */
7174:		vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP);
7175:		vma->vm_ops = &perf_mmap_vmops;
7176:	
7177:		mapped = get_mapped(event, event_mapped);
7178:		if (mapped)
7179:			mapped(event, vma->vm_mm);
7180:	
7181:		/*
7182:		 * Try to map it into the page table. On fail, invoke
7183:		 * perf_mmap_close() to undo the above, as the callsite expects
7184:		 * full cleanup in this case and therefore does not invoke
7185:		 * vmops::close().
7186:		 */
7187:		ret = map_range(event->rb, vma);
7188:		if (ret)
7189:			perf_mmap_close(vma);
7190:	
7191:		return ret;
7192:	}
 SourceFile:kernel/events/core.c]

25/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Thinking Through a Potential Race Condition in Perf**

Okay, I'm digging into this `perf_mmap` code, and something's bugging me. Specifically, I'm noticing that `ctx->lock` isn't held when `perf_mmap` is called. That makes me wonder about `perf_event_update_time`, which is called quite a bit throughout the code. Typically, updating those timing fields should be protected, usually by a lock that guards the event's time information.

So, the question is whether `perf_event_update_time` is intended to be protected by `ctx->lock`. I'm starting to trace where it's called. Hmm, let's look at `perf_event_set_state`. Okay, I see it there:

```c
 747:	static void
 748:	perf_event_set_state(struct perf_event *event, enum perf_event_state state)
 749:	{
 750:		if (event->state == state)
 751:			return;
 752:	
 753:		perf_event_update_time(event);
...
```

Right, but isn't `perf_event_set_state` always called with `ctx->lock` held? I recall seeing `lockdep_assert_held(&ctx->lock);` in `event_sched_out`.

Okay, now let's think about `perf_mmap_rb`. Ah, there it is! `perf_event_update_time(event)` is called at line 7036, and it's only holding `mmap_mutex`. If an event is *currently active* on one CPU, and then `perf_mmap` is triggered on another CPU, then they could race.

Hold on, I think I see a pattern. `perf_mmap_rb` is called when a ring buffer is first attached to an event. Let me check the code; yes, `ring_buffer_attach` is called right before `perf_event_update_time`.

But... can an event be active *without* a ring buffer? Yes, of course, it can just be counting!

So, the bottom line is, if the event *is* active, then `ctx->lock` *should* be held when the timing fields are updated. I need to dig further into `ring_buffer_attach` to confirm my suspicion and see the exact control flow.



26/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:ring_buffer_attach SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:5169:	static void ring_buffer_attach(struct perf_event *event,
5170:				       struct perf_buffer *rb);
 SourceFile:kernel/events/core.c]

27/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Finding the Definition of `ring_buffer_attach`**

Okay, so I'm still hitting a wall trying to pin down the definitive definition of `ring_buffer_attach`. I've been trying to find it using `grep` through the code search, specifically using `codesearch-definition-source` on a likely usage. Maybe I need a wider search range, or maybe I should just look within the file directly.

Wait, hold on, it's right there in the `codesearch-file-index` list!

```
{Kind: function, Name: ring_buffer_attach}
```

Okay, so the index knows about it. Hmm, why did I get a prototype before? Could there be multiple definitions, or maybe it's a static function and I'm just overlooking it in the source? Wait, Line 5169 is just the prototype. The actual implementation must be defined elsewhere.

Alright, let's try a different tack. I'll search for the signature string: `ring_buffer_attach(struct perf_event *event,`.

Ah, right, `codesearch-definition-source` should find it this time! I'll try that again. Maybe I missed it the first time around.



28/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:ring_buffer_attach SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:5169:	static void ring_buffer_attach(struct perf_event *event,
5170:				       struct perf_buffer *rb);
 SourceFile:kernel/events/core.c]

29/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Navigating the Codebase**

Alright, let's get down to brass tacks. I need to pinpoint the exact definition of this function or variable. My initial instinct is to leverage the `codesearch-definition-source` tool – a tried and true method. However, I immediately hit a snag. I need to be more precise: I need to rule out prototype definitions. The tool, unfortunately, doesn't offer that level of granularity in its search criteria. A minor setback, but nothing insurmountable.

Instead, I'll go old-school. I'll meticulously examine the code, focusing on `kernel/events/core.c`. I recall that file being a likely candidate. Given the size of the file, I'll avoid a full scan, starting my investigation around line 5900. Hopefully, the surrounding code will shed light on what I'm looking for. Time to dig in.



30/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:ring_buffer_put SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6684:	void ring_buffer_put(struct perf_buffer *rb)
6685:	{
6686:		if (!refcount_dec_and_test(&rb->refcount))
6687:			return;
6688:	
6689:		WARN_ON_ONCE(!list_empty(&rb->event_list));
6690:	
6691:		call_rcu(&rb->rcu_head, rb_free_rcu);
6692:	}
 SourceFile:kernel/events/core.c]

31/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Analysis of a Potential Race Condition in Perf Event Handling**

Okay, so I'm digging into a possible race condition related to `perf_event_update_time`. My initial thought was to find the `ring_buffer_attach` definition, but that's not the critical piece here; `core.c` has the necessary context. The more important bit is the interaction between `perf_event_update_time` and concurrent calls. I've been looking at how time accounting for performance events might be getting messed up.

Specifically, I'm concerned about whether `perf_event_update_time` is intentionally left unprotected in certain scenarios. It seems that during `perf_mmap_rb`, an event might be freshly created or in a state where locking isn't applied, but `perf_mmap` *can* be called on an already existing event, which raises a red flag.

My investigation is driven by a stack trace that points to `perf_event_set_state` being called from `event_sched_out` during a context switch. This involves a task `syz.4.2772` (PID 12005). The other thread (PID 12011) is calling `perf_mmap`. This simultaneous access to the `perf_event` structure is the crux of the issue.

Is this interaction benign? I'm not convinced. The `perf_event_update_time` function updates `tstamp`, `total_time_enabled`, and `total_time_running`. While these are 64-bit values and likely updated atomically on x86_64, the sequence of operations within that function isn't itself atomic, which makes this concerning. The logic is: get `now` timestamp, calculate `delta`, add `delta` to `total_time_enabled`, and update `tstamp`.

Consider a scenario with two threads operating concurrently. If both threads read the same `tstamp` and the same `total_time_enabled` then, after applying their independent updates, the final result will be incorrect. This is because they will calculate deltas based on stale information. Moreover, the `+=` operation introduces even greater risk of corruption.

Looking closer at the code, particularly the `__perf_update_times` function, my initial concern is confirmed. The code isn't designed to handle concurrent access safely. Even though `enabled` is a pointer to `event->total_time_enabled` within `perf_event_update_time`, this operation is not atomic: read `total_time_enabled`, add to it, and write it back. Both `event->total_time_enabled` and `event->tstamp` are susceptible to race conditions.

If `perf_mmap_rb` is racing with `event_sched_out`, one thread is modifying the ring buffer while another is scheduling the event out. Since calling `perf_mmap` on an active event is valid, the race condition is possible.

I need to confirm whether `perf_mmap_rb` should hold `ctx->lock`. Typically, other calls to `perf_event_update_time` (like within `perf_event_set_state`) do hold this lock, which protects the `perf_event` structure. It looks like `perf_mmap_rb` *doesn't* hold the lock, which is the problem. I'll check `perf_event_read` to see whether it too is missing the locking. I suspect the race condition is here.



32/2 2026/01/14 13:10 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_read SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:4816:	static int perf_event_read(struct perf_event *event, bool group)
4817:	{
4818:		enum perf_event_state state = READ_ONCE(event->state);
4819:		int event_cpu, ret = 0;
4820:	
4821:		/*
4822:		 * If event is enabled and currently active on a CPU, update the
4823:		 * value in the event structure:
4824:		 */
4825:	again:
4826:		if (state == PERF_EVENT_STATE_ACTIVE) {
4827:			struct perf_read_data data;
4828:	
4829:			/*
4830:			 * Orders the ->state and ->oncpu loads such that if we see
4831:			 * ACTIVE we must also see the right ->oncpu.
4832:			 *
4833:			 * Matches the smp_wmb() from event_sched_in().
4834:			 */
4835:			smp_rmb();
4836:	
4837:			event_cpu = READ_ONCE(event->oncpu);
4838:			if ((unsigned)event_cpu >= nr_cpu_ids)
4839:				return 0;
4840:	
4841:			data = (struct perf_read_data){
4842:				.event = event,
4843:				.group = group,
4844:				.ret = 0,
4845:			};
4846:	
4847:			preempt_disable();
4848:			event_cpu = __perf_event_read_cpu(event, event_cpu);
4849:	
4850:			/*
4851:			 * Purposely ignore the smp_call_function_single() return
4852:			 * value.
4853:			 *
4854:			 * If event_cpu isn't a valid CPU it means the event got
4855:			 * scheduled out and that will have updated the event count.
4856:			 *
4857:			 * Therefore, either way, we'll have an up-to-date event count
4858:			 * after this.
4859:			 */
4860:			(void)smp_call_function_single(event_cpu, __perf_event_read, &data, 1);
4861:			preempt_enable();
4862:			ret = data.ret;
4863:	
4864:		} else if (state == PERF_EVENT_STATE_INACTIVE) {
4865:			struct perf_event_context *ctx = event->ctx;
4866:			unsigned long flags;
4867:	
4868:			raw_spin_lock_irqsave(&ctx->lock, flags);
4869:			state = event->state;
4870:			if (state != PERF_EVENT_STATE_INACTIVE) {
4871:				raw_spin_unlock_irqrestore(&ctx->lock, flags);
4872:				goto again;
4873:			}
4874:	
4875:			/*
4876:			 * May read while context is not active (e.g., thread is
4877:			 * blocked), in that case we cannot update context time
4878:			 */
4879:			ctx_time_update_event(ctx, event);
4880:	
4881:			perf_event_update_time(event);
4882:			if (group)
4883:				perf_event_update_sibling_time(event);
4884:			raw_spin_unlock_irqrestore(&ctx->lock, flags);
4885:		}
4886:	
4887:		return ret;
4888:	}
 SourceFile:kernel/events/core.c]

33/2 2026/01/14 13:10 llm expert
0m Model:
unknown

Thoughts:
**Delving into the Timing Logic of `perf_event_update_time`**

Okay, so I'm digging into this `perf_event_read` function, and it's holding `ctx->lock` before calling `perf_event_update_time`. This strongly suggests that `perf_event_update_time` is *designed* to be called with that lock held, especially given that the events typically belong to a context. That seems straightforward enough, but my expert intuition is tingling…

Wait a minute, what about `perf_mmap_rb`? Is that a special case I need to consider? We're attaching a new ring buffer there, and if we *don't* hold `ctx->lock`, we could potentially have a race condition with the event being scheduled in or out, and I definitely don't want that.

I need to understand *why* `perf_mmap_rb` calls `perf_event_update_time`. Let me trace that. Ah, it looks like the goal is to make sure the timestamp (`tstamp`) is up-to-date when the userpage is initialized. Okay, I see the sequence: `perf_event_update_time(event)`, followed by `perf_event_init_userpage(event)`, and then `perf_event_update_userpage(event)`. That makes sense.



34/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_init_userpage SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6506:	static void perf_event_init_userpage(struct perf_event *event)
6507:	{
6508:		struct perf_event_mmap_page *userpg;
6509:		struct perf_buffer *rb;
6510:	
6511:		rcu_read_lock();
6512:		rb = rcu_dereference(event->rb);
6513:		if (!rb)
6514:			goto unlock;
6515:	
6516:		userpg = rb->user_page;
6517:	
6518:		/* Allow new userspace to detect that bit 0 is deprecated */
6519:		userpg->cap_bit0_is_deprecated = 1;
6520:		userpg->size = offsetof(struct perf_event_mmap_page, __reserved);
6521:		userpg->data_offset = PAGE_SIZE;
6522:		userpg->data_size = perf_data_size(rb);
6523:	
6524:	unlock:
6525:		rcu_read_unlock();
6526:	}
 SourceFile:kernel/events/core.c]

35/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
Okay, here's the summary, rendered as your internal thought process:

**Diving into `perf_event_update_userpage`**

Alright, let's break this down. We're looking at `perf_event_update_userpage`, a core function in the performance monitoring subsystem. My initial assumption, given its name, is that this is where we're syncing user-space data with the kernel's performance event structures. It’s the critical piece that ensures user-space can properly interpret the performance counter data. I expect it handles updates to the shared memory region between kernel and user space.

I'll need to recall the relevant data structures here. We've got the `perf_event_attr` for configuration, the `perf_event` struct itself, and the associated ring buffer layout. This function likely manages pointer updates, flags, and potentially ring buffer head/tail management, depending on the event's type and the hardware capabilities.

Is it handling all possible access patterns to the user page? We must consider cases of multiple readers/writers on different CPUs, lock contention and whether it's optimised for the common case. I need to keep in mind possible data races too. It must be efficient, non-blocking where possible, and robust against all sorts of race conditions. And of course, there's always the concern about speculative execution and how this function interacts with memory barriers. 

My next step is to examine the specific arguments passed to `perf_event_update_userpage` and understand how the various components interact. I'll be looking for any indications of locking mechanisms, atomic operations, or any use of memory barriers. The overall architecture is going to drive how this operates – and from there, I can build an understanding of the trade-offs in its design.



36/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_update_userpage SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6533:	/*
6534:	 * Callers need to ensure there can be no nesting of this function, otherwise
6535:	 * the seqlock logic goes bad. We can not serialize this because the arch
6536:	 * code calls this from NMI context.
6537:	 */
6538:	void perf_event_update_userpage(struct perf_event *event)
6539:	{
6540:		struct perf_event_mmap_page *userpg;
6541:		struct perf_buffer *rb;
6542:		u64 enabled, running, now;
6543:	
6544:		rcu_read_lock();
6545:		rb = rcu_dereference(event->rb);
6546:		if (!rb)
6547:			goto unlock;
6548:	
6549:		/*
6550:		 * compute total_time_enabled, total_time_running
6551:		 * based on snapshot values taken when the event
6552:		 * was last scheduled in.
6553:		 *
6554:		 * we cannot simply called update_context_time()
6555:		 * because of locking issue as we can be called in
6556:		 * NMI context
6557:		 */
6558:		calc_timer_values(event, &now, &enabled, &running);
6559:	
6560:		userpg = rb->user_page;
6561:		/*
6562:		 * Disable preemption to guarantee consistent time stamps are stored to
6563:		 * the user page.
6564:		 */
6565:		preempt_disable();
6566:		++userpg->lock;
6567:		barrier();
6568:		userpg->index = perf_event_index(event);
6569:		userpg->offset = perf_event_count(event, false);
6570:		if (userpg->index)
6571:			userpg->offset -= local64_read(&event->hw.prev_count);
6572:	
6573:		userpg->time_enabled = enabled +
6574:				atomic64_read(&event->child_total_time_enabled);
6575:	
6576:		userpg->time_running = running +
6577:				atomic64_read(&event->child_total_time_running);
6578:	
6579:		arch_perf_update_userpage(event, userpg, now);
6580:	
6581:		barrier();
6582:		++userpg->lock;
6583:		preempt_enable();
6584:	unlock:
6585:		rcu_read_unlock();
6586:	}
 SourceFile:kernel/events/core.c]

37/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
Here's a breakdown of my thought process:

**Linking the Timer Logic**

Okay, so I'm digging into this `perf_event` code and I see that `perf_event_update_userpage` is calling `calc_timer_values`. Interesting. `calc_timer_values` is central to timer calculations, and I immediately remember that it's also responsible for reading `tstamp`. This connection is important because `tstamp`, of course, is the crucial timestamp value used in timer calculations within the `perf_event` subsystem. Now, the implications are becoming clearer: updates to the user page are intertwined with the logic for calculating timer values and reading timestamps, all of which are critical to the overall timer functionality. I need to keep this relationship in mind as I delve further into the details.



38/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:calc_timer_values SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:4722:	static void calc_timer_values(struct perf_event *event,
4723:					u64 *now,
4724:					u64 *enabled,
4725:					u64 *running)
4726:	{
4727:		u64 ctx_time;
4728:	
4729:		*now = perf_clock();
4730:		ctx_time = perf_event_time_now(event, *now);
4731:		__perf_update_times(event, ctx_time, enabled, running);
4732:	}
 SourceFile:kernel/events/core.c]

39/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
**My Analysis of a Potential Data Race in Perf Event Timestamps**

Okay, so I'm digging into this reported data race concerning the `perf` subsystem, and it's starting to become clear what's happening. The core issue revolves around updating and reading timestamps (`event->tstamp`) and associated timing information (`total_time_enabled`, `total_time_running`) for performance events. It appears that `perf_mmap_rb` is calling `perf_event_update_time`, which is where things get tricky.

I initially questioned why `perf_mmap_rb` needed to call `perf_event_update_time` in the first place. My thinking was that if the goal was to ensure recent event timings, then the code should definitely be holding the `ctx->lock`. Without that lock, there's a race condition possible, where another CPU could schedule the event out at the same time. The reported race occurs between writes to `event->tstamp` in `perf_event_update_time` (called by `perf_mmap_rb`) and reads of `event->tstamp` in `__perf_update_times` (also part of the timing update). Importantly, `ctx->lock` is held in `event_sched_out` but *not* held in `perf_mmap_rb`.

The concern is this: if `perf_mmap_rb` updates the timestamp and total times without the lock while another thread *does* hold the lock and updates them, there's a conflict. The locked update (from `event_sched_out`) is legitimate, as the event is transitioning, but the unlocked update (from `perf_mmap_rb`) is just a snapshot, trying to read a fresh value.

What I've realized is that `perf_event_update_time` modifies *multiple* fields: `event->total_time_enabled`, `event->total_time_running`, and `event->tstamp`. All these updates *should* be protected by `ctx->lock` if the event is associated with a context.

My next step was to understand why `perf_mmap_rb` updates those values. The comment in `perf_event_update_userpage` suggests the code tries to calculate the total running time, but it cannot call `update_context_time()` due to locking issues because `perf_event_update_userpage` can be called from NMI context. Because of that, `calc_timer_values` is used.

I now see the data race because  `perf_event_update_time` writes these fields. It's unsafe to call `perf_event_update_time` without `ctx->lock`.

The data race is very harmful. If `total_time_enabled` gets a corrupted value, the user sees wrong timing for the performance event which in turn corrupts the scaling of the counter values.

The delta calculation is ruined, and there is a loss of timing information.

So, the next question is: Should `perf_mmap_rb` take `ctx->lock`? It seems like a reasonable solution, because `perf_event_update_time` is modifying shared state. `perf_mmap` calls `perf_mmap_rb` and `perf_mmap` uses the `mmap_mutex`. However, `mmap_mutex` is per-event and `ctx->lock` is per-context. `event_sched_out` doesn't take the `mmap_mutex`. The lock isn't a sleeping lock.

I see that `perf_event_update_time` is also called in `perf_event_read` which also takes `ctx->lock`. This reinforces my concern.

Based on my analysis of the code, and considering the potential data loss, this looks like a significant bug that needs to be addressed. It's likely that taking `ctx->lock` within `perf_mmap_rb` is the correct fix. It also appears the issue may have been discussed or seen before. I'll continue to dig in the archives.



40/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_update_time SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode: 730:	static void perf_event_update_time(struct perf_event *event)
 731:	{
 732:		u64 now = perf_event_time(event);
 733:	
 734:		__perf_update_times(event, now, &event->total_time_enabled,
 735:						&event->total_time_running);
 736:		event->tstamp = now;
 737:	}
 SourceFile:kernel/events/core.c]

41/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
**Digging Deeper into the Perf Event Code**

Alright, I'm going to revisit that locking issue in the perf event code. I've already scrutinized a few functions that seem related and hold `ctx->lock`: `perf_event_read` and `perf_event_set_state`. They're probably okay. I was also pleased to see that `perf_mmap_rb` doesn't hold `ctx->lock`, which simplifies things. But I'm still not entirely convinced. Time to see if the locks being held are a problem.

Now, my focus is shifting towards `perf_event_stop` and `perf_event_start`. These functions seem like natural candidates to investigate. Let's start with `perf_event_stop`. I need to figure out what's happening in there.



42/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_stop SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:3267:	static int perf_event_stop(struct perf_event *event, int restart)
3268:	{
3269:		struct stop_event_data sd = {
3270:			.event		= event,
3271:			.restart	= restart,
3272:		};
3273:		int ret = 0;
3274:	
3275:		do {
3276:			if (READ_ONCE(event->state) != PERF_EVENT_STATE_ACTIVE)
3277:				return 0;
3278:	
3279:			/* matches smp_wmb() in event_sched_in() */
3280:			smp_rmb();
3281:	
3282:			/*
3283:			 * We only want to restart ACTIVE events, so if the event goes
3284:			 * inactive here (event->oncpu==-1), there's nothing more to do;
3285:			 * fall through with ret==-ENXIO.
3286:			 */
3287:			ret = cpu_function_call(READ_ONCE(event->oncpu),
3288:						__perf_event_stop, &sd);
3289:		} while (ret == -EAGAIN);
3290:	
3291:		return ret;
3292:	}
 SourceFile:kernel/events/core.c]

43/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
Okay, here's the summary, rendered as a first-person account, assuming I'm an expert in systems performance:

**Halting the Performance Event Counter**

Alright, I'm diving into this `__perf_event_stop` function. My initial thought is, this is a critical part of the performance monitoring framework. This is where we tell the hardware performance counter to *stop* gathering data. This isn't just a simple operation; it’s about ensuring data integrity and minimizing any potential overhead. My experience tells me that correctly halting the counters involves dealing with race conditions, interrupt masking, and making sure all the necessary state is consistently updated. I'm imagining a complex interplay between the kernel and the hardware, and the importance of atomicity here is immediately apparent. Let's make sure this is done correctly!



44/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:__perf_event_stop SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:3231:	static int __perf_event_stop(void *info)
3232:	{
3233:		struct stop_event_data *sd = info;
3234:		struct perf_event *event = sd->event;
3235:	
3236:		/* if it's already INACTIVE, do nothing */
3237:		if (READ_ONCE(event->state) != PERF_EVENT_STATE_ACTIVE)
3238:			return 0;
3239:	
3240:		/* matches smp_wmb() in event_sched_in() */
3241:		smp_rmb();
3242:	
3243:		/*
3244:		 * There is a window with interrupts enabled before we get here,
3245:		 * so we need to check again lest we try to stop another CPU's event.
3246:		 */
3247:		if (READ_ONCE(event->oncpu) != smp_processor_id())
3248:			return -EAGAIN;
3249:	
3250:		event->pmu->stop(event, PERF_EF_UPDATE);
3251:	
3252:		/*
3253:		 * May race with the actual stop (through perf_pmu_output_stop()),
3254:		 * but it is only used for events with AUX ring buffer, and such
3255:		 * events will refuse to restart because of rb::aux_mmap_count==0,
3256:		 * see comments in perf_aux_output_begin().
3257:		 *
3258:		 * Since this is happening on an event-local CPU, no trace is lost
3259:		 * while restarting.
3260:		 */
3261:		if (sd->restart)
3262:			event->pmu->start(event, 0);
3263:	
3264:		return 0;
3265:	}
 SourceFile:kernel/events/core.c]

45/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
Okay, let's see...

**Investigating a Timing Issue in the Perf Event System**

Right, so I was looking into something related to performance events, and I realized something that seems a bit off. Specifically, `__perf_event_stop` doesn't appear to directly call `perf_event_update_time`. That's a little surprising, and I'm curious how time updates are handled during a stop operation. 

Okay, let's see if something else calls it, like `perf_event_modify_breakpoint`. It's possible time updates are handled in a different location, so I'll check the whole file for the `perf_event_update_time(` string to see where and how it's being used.



46/2 2026/01/14 13:11 tool codesearch-file-index
0m Model:
unknown

Args:
map[SourceFile:kernel/events/core.c]

Results:
map[Entities:[map[Kind:function Name:___perf_sw_event] map[Kind:function Name:__cond_set] map[Kind:function Name:__ctx_time_update] map[Kind:function Name:__detach_global_ctx_data] map[Kind:function Name:__detach_global_ctx_data] map[Kind:function Name:__do_sys_perf_event_open] map[Kind:function Name:__do_sys_perf_event_open] map[Kind:function Name:__event_disable] map[Kind:function Name:__event_disable] map[Kind:function Name:__find_swevent_head] map[Kind:function Name:__free___free_event] map[Kind:function Name:__free_event] map[Kind:function Name:__free_perf_ctx_data_rcu] map[Kind:function Name:__free_pmu_unregister] map[Kind:function Name:__group_cmp] map[Kind:function Name:__group_cmp_ignore_cgroup] map[Kind:function Name:__group_less] map[Kind:function Name:__heap_add] map[Kind:function Name:__ia32_sys_perf_event_open] map[Kind:function Name:__link_epc] map[Kind:function Name:__perf_addr_filters_adjust] map[Kind:function Name:__perf_cgroup_move] map[Kind:function Name:__perf_ctx_lock] map[Kind:function Name:__perf_ctx_unlock] map[Kind:function Name:__perf_effective_state] map[Kind:function Name:__perf_event__output_id_sample] map[Kind:function Name:__perf_event_account_interrupt] map[Kind:function Name:__perf_event_aux_pause] map[Kind:function Name:__perf_event_disable] map[Kind:function Name:__perf_event_enable] map[Kind:function Name:__perf_event_exit_context] map[Kind:function Name:__perf_event_header__init_id] map[Kind:function Name:__perf_event_header_size] map[Kind:function Name:__perf_event_init_context] map[Kind:function Name:__perf_event_output] map[Kind:function Name:__perf_event_output_stop] map[Kind:function Name:__perf_event_overflow] map[Kind:function Name:__perf_event_period] map[Kind:function Name:__perf_event_read] map[Kind:function Name:__perf_event_read_cpu] map[Kind:function Name:__perf_event_read_size] map[Kind:function Name:__perf_event_read_value] map[Kind:function Name:__perf_event_set_bpf_prog] map[Kind:function Name:__perf_event_set_bpf_prog] map[Kind:function Name:__perf_event_stop] map[Kind:function Name:__perf_event_sync_stat] map[Kind:function Name:__perf_event_task_sched_in] map[Kind:function Name:__perf_event_task_sched_out] map[Kind:function Name:__perf_init_event_pmu_context] map[Kind:function Name:__perf_install_in_context] map[Kind:function Name:__perf_mux_hrtimer_init] map[Kind:function Name:__perf_pending_disable] map[Kind:function Name:__perf_pmu_install] map[Kind:function Name:__perf_pmu_install_event] map[Kind:function Name:__perf_pmu_output_stop] map[Kind:function Name:__perf_pmu_remove] map[Kind:function Name:__perf_pmu_sched_task] map[Kind:function Name:__perf_read] map[Kind:function Name:__perf_read_group_add] map[Kind:function Name:__perf_remove_from_context] map[Kind:function Name:__perf_sw_event] map[Kind:function Name:__perf_tp_event_target_task] map[Kind:function Name:__perf_update_times] map[Kind:function Name:__pmu_ctx_sched_in] map[Kind:function Name:__pmu_ctx_sched_out] map[Kind:function Name:__pmu_detach_event] map[Kind:function Name:__se_sys_perf_event_open] map[Kind:function Name:__update_cgrp_time] map[Kind:function Name:__update_context_time] map[Kind:function Name:__x64_sys_perf_event_open] map[Kind:function Name:_free_event] map[Kind:function Name:_perf_event_disable] map[Kind:function Name:_perf_event_enable] map[Kind:function Name:_perf_event_period] map[Kind:function Name:_perf_event_refresh] map[Kind:function Name:_perf_event_reset] map[Kind:function Name:_perf_ioctl] map[Kind:function Name:account_event] map[Kind:function Name:account_freq_event] map[Kind:function Name:account_freq_event_nohz] map[Kind:function Name:account_pmu_sb_event] map[Kind:function Name:add_event_to_ctx] map[Kind:function Name:add_event_to_groups] map[Kind:function Name:alloc_perf_context] map[Kind:function Name:alloc_perf_ctx_data] map[Kind:function Name:arch_perf_update_userpage] map[Kind:function Name:attach_global_ctx_data] map[Kind:function Name:attach_perf_ctx_data] map[Kind:function Name:attach_sb_event] map[Kind:function Name:attach_task_ctx_data] map[Kind:function Name:bpf_overflow_handler] map[Kind:function Name:calc_timer_values] map[Kind:function Name:class_perf_ctx_lock_constructor] map[Kind:function Name:class_perf_ctx_lock_destructor] map[Kind:function Name:context_equiv] map[Kind:function Name:cpu_clock_event_add] map[Kind:function Name:cpu_clock_event_del] map[Kind:function Name:cpu_clock_event_init] map[Kind:function Name:cpu_clock_event_read] map[Kind:function Name:cpu_clock_event_start] map[Kind:function Name:cpu_clock_event_stop] map[Kind:function Name:cpu_clock_event_update] map[Kind:function Name:cpu_function_call] map[Kind:function Name:cpumask_show] map[Kind:function Name:ctx_event_to_rotate] map[Kind:function Name:ctx_resched] map[Kind:function Name:ctx_sched_in] map[Kind:function Name:ctx_sched_in] map[Kind:function Name:ctx_sched_out] map[Kind:function Name:ctx_sched_out] map[Kind:function Name:ctx_time_freeze] map[Kind:function Name:ctx_time_update] map[Kind:function Name:ctx_time_update_event] map[Kind:function Name:del_event_from_groups] map[Kind:function Name:detach_global_ctx_data] map[Kind:function Name:detach_perf_ctx_data] map[Kind:function Name:detach_sb_event] map[Kind:function Name:detach_task_ctx_data] map[Kind:function Name:do_perf_sw_event] map[Kind:function Name:event_cgroup] map[Kind:function Name:event_enable_on_exec] map[Kind:function Name:event_filter_match] map[Kind:function Name:event_function] map[Kind:function Name:event_function_call] map[Kind:function Name:event_function_local] map[Kind:function Name:event_sched_in] map[Kind:function Name:event_sched_out] map[Kind:function Name:event_update_userpage] map[Kind:function Name:exclusive_event_destroy] map[Kind:function Name:exclusive_event_init] map[Kind:function Name:exclusive_event_installable] map[Kind:function Name:exclusive_event_installable] map[Kind:function Name:exclusive_event_match] map[Kind:function Name:find_get_context] map[Kind:function Name:find_get_pmu_context] map[Kind:function Name:find_lively_task_by_vpid] map[Kind:function Name:find_swevent_head] map[Kind:function Name:find_swevent_head_rcu] map[Kind:function Name:free_cpc_rcu] map[Kind:function Name:free_ctx] map[Kind:function Name:free_epc_rcu] map[Kind:function Name:free_event] map[Kind:function Name:free_event_rcu] map[Kind:function Name:free_filters_list] map[Kind:function Name:free_perf_ctx_data] map[Kind:function Name:get_ctx] map[Kind:function Name:get_event_groups] map[Kind:function Name:get_event_list] map[Kind:function Name:get_event_type] map[Kind:function Name:get_pmu_ctx] map[Kind:function Name:group_can_go_on] map[Kind:function Name:group_sched_in] map[Kind:function Name:group_sched_out] map[Kind:function Name:group_update_userpage] map[Kind:function Name:has_extended_regs] map[Kind:function Name:has_inherit_and_sample_read] map[Kind:function Name:idr_cmpxchg] map[Kind:function Name:inherit_event] map[Kind:function Name:inherit_group] map[Kind:function Name:inherit_task_group] map[Kind:function Name:init_event_group] map[Kind:function Name:init_events_core_sysctls] map[Kind:function Name:is_cgroup_event] map[Kind:function Name:is_event_hup] map[Kind:function Name:is_event_in_freq_mode] map[Kind:function Name:is_kernel_event] map[Kind:function Name:is_orphaned_event] map[Kind:function Name:is_perf_file] map[Kind:function Name:is_sb_event] map[Kind:function Name:list_add_event] map[Kind:function Name:list_del_event] map[Kind:function Name:map_range] map[Kind:function Name:merge_sched_in] map[Kind:function Name:mutex_lock_double] map[Kind:function Name:nr_addr_filters_show] map[Kind:function Name:perf_addr_filter_apply] map[Kind:function Name:perf_addr_filter_match] map[Kind:function Name:perf_addr_filter_new] map[Kind:function Name:perf_addr_filter_vma_adjust] map[Kind:function Name:perf_addr_filters_adjust] map[Kind:function Name:perf_addr_filters_splice] map[Kind:function Name:perf_adjust_freq_unthr_context] map[Kind:function Name:perf_adjust_freq_unthr_events] map[Kind:function Name:perf_adjust_period] map[Kind:function Name:perf_allow_kernel] map[Kind:function Name:perf_allow_kernel] map[Kind:function Name:perf_assert_pmu_disabled] map[Kind:function Name:perf_aux_output_match] map[Kind:function Name:perf_aux_sample_output] map[Kind:function Name:perf_bp_event] map[Kind:function Name:perf_calculate_period] map[Kind:function Name:perf_callchain] map[Kind:function Name:perf_callchain_deferred_output] map[Kind:function Name:perf_cgroup_attach] map[Kind:function Name:perf_cgroup_connect] map[Kind:function Name:perf_cgroup_css_alloc] map[Kind:function Name:perf_cgroup_css_free] map[Kind:function Name:perf_cgroup_css_online] map[Kind:function Name:perf_cgroup_ensure_storage] map[Kind:function Name:perf_cgroup_event_disable] map[Kind:function Name:perf_cgroup_event_enable] map[Kind:function Name:perf_cgroup_event_time] map[Kind:function Name:perf_cgroup_event_time_now] map[Kind:function Name:perf_cgroup_match] map[Kind:function Name:perf_cgroup_set_timestamp] map[Kind:function Name:perf_cgroup_switch] map[Kind:function Name:perf_check_permission] map[Kind:function Name:perf_child_detach] map[Kind:function Name:perf_clock] map[Kind:function Name:perf_compat_ioctl] map[Kind:function Name:perf_copy_attr] map[Kind:function Name:perf_copy_attr] map[Kind:function Name:perf_cpu_task_ctx] map[Kind:function Name:perf_cpu_time_max_percent_handler] map[Kind:function Name:perf_ctx_disable] map[Kind:function Name:perf_ctx_enable] map[Kind:function Name:perf_ctx_lock] map[Kind:function Name:perf_ctx_sched_task_cb] map[Kind:function Name:perf_ctx_unlock] map[Kind:function Name:perf_detach_cgroup] map[Kind:function Name:perf_duration_warn] map[Kind:function Name:perf_event__header_size] map[Kind:function Name:perf_event__id_header_size] map[Kind:function Name:perf_event__output_id_sample] map[Kind:function Name:perf_event__state_init] map[Kind:function Name:perf_event_account_interrupt] map[Kind:function Name:perf_event_addr_filters_apply] map[Kind:function Name:perf_event_addr_filters_exec] map[Kind:function Name:perf_event_addr_filters_sync] map[Kind:function Name:perf_event_addr_filters_sync] map[Kind:function Name:perf_event_alloc] map[Kind:function Name:perf_event_alloc_task_data] map[Kind:function Name:perf_event_attrs] map[Kind:function Name:perf_event_aux_event] map[Kind:function Name:perf_event_aux_pause] map[Kind:function Name:perf_event_bpf_emit_ksymbols] map[Kind:function Name:perf_event_bpf_event] map[Kind:function Name:perf_event_bpf_match] map[Kind:function Name:perf_event_bpf_output] map[Kind:function Name:perf_event_cgroup] map[Kind:function Name:perf_event_cgroup_match] map[Kind:function Name:perf_event_cgroup_output] map[Kind:function Name:perf_event_check_period] map[Kind:function Name:perf_event_clear_cpumask] map[Kind:function Name:perf_event_clock] map[Kind:function Name:perf_event_comm] map[Kind:function Name:perf_event_comm_event] map[Kind:function Name:perf_event_comm_match] map[Kind:function Name:perf_event_comm_output] map[Kind:function Name:perf_event_context_sched_in] map[Kind:function Name:perf_event_context_sched_out] map[Kind:function Name:perf_event_count] map[Kind:function Name:perf_event_create_kernel_counter] map[Kind:function Name:perf_event_create_kernel_counter] map[Kind:function Name:perf_event_ctx_lock] map[Kind:function Name:perf_event_ctx_lock_nested] map[Kind:function Name:perf_event_ctx_unlock] map[Kind:function Name:perf_event_delayed_put] map[Kind:function Name:perf_event_disable] map[Kind:function Name:perf_event_disable] map[Kind:function Name:perf_event_disable_inatomic] map[Kind:function Name:perf_event_disable_local] map[Kind:function Name:perf_event_enable] map[Kind:function Name:perf_event_enable] map[Kind:function Name:perf_event_enable_on_exec] map[Kind:function Name:perf_event_exec] map[Kind:function Name:perf_event_exit_cpu] map[Kind:function Name:perf_event_exit_cpu_context] map[Kind:function Name:perf_event_exit_event] map[Kind:function Name:perf_event_exit_event] map[Kind:function Name:perf_event_exit_task] map[Kind:function Name:perf_event_exit_task_context] map[Kind:function Name:perf_event_for_each] map[Kind:function Name:perf_event_for_each_child] map[Kind:function Name:perf_event_fork] map[Kind:function Name:perf_event_free_bpf_handler] map[Kind:function Name:perf_event_free_bpf_prog] map[Kind:function Name:perf_event_free_filter] map[Kind:function Name:perf_event_free_filter] map[Kind:function Name:perf_event_free_task] map[Kind:function Name:perf_event_get] map[Kind:function Name:perf_event_groups_cmp] map[Kind:function Name:perf_event_groups_delete] map[Kind:function Name:perf_event_groups_first] map[Kind:function Name:perf_event_groups_init] map[Kind:function Name:perf_event_groups_insert] map[Kind:function Name:perf_event_groups_next] map[Kind:function Name:perf_event_header__init_id] map[Kind:function Name:perf_event_idx_default] map[Kind:function Name:perf_event_index] map[Kind:function Name:perf_event_init] map[Kind:function Name:perf_event_init_all_cpus] map[Kind:function Name:perf_event_init_context] map[Kind:function Name:perf_event_init_cpu] map[Kind:function Name:perf_event_init_task] map[Kind:function Name:perf_event_init_userpage] map[Kind:function Name:perf_event_is_tracing] map[Kind:function Name:perf_event_itrace_started] map[Kind:function Name:perf_event_ksymbol] map[Kind:function Name:perf_event_ksymbol_match] map[Kind:function Name:perf_event_ksymbol_output] map[Kind:function Name:perf_event_max_sample_rate_handler] map[Kind:function Name:perf_event_mmap] map[Kind:function Name:perf_event_mmap_event] map[Kind:function Name:perf_event_mmap_match] map[Kind:function Name:perf_event_mmap_output] map[Kind:function Name:perf_event_modify_attr] map[Kind:function Name:perf_event_modify_breakpoint] map[Kind:function Name:perf_event_modify_copy_attr] map[Kind:function Name:perf_event_mux_interval_ms_show] map[Kind:function Name:perf_event_mux_interval_ms_store] map[Kind:function Name:perf_event_namespaces] map[Kind:function Name:perf_event_namespaces_match] map[Kind:function Name:perf_event_namespaces_output] map[Kind:function Name:perf_event_nop_int] map[Kind:function Name:perf_event_output] map[Kind:function Name:perf_event_output_backward] map[Kind:function Name:perf_event_output_forward] map[Kind:function Name:perf_event_overflow] map[Kind:function Name:perf_event_parse_addr_filter] map[Kind:function Name:perf_event_pause] map[Kind:function Name:perf_event_pause] map[Kind:function Name:perf_event_period] map[Kind:function Name:perf_event_period] map[Kind:function Name:perf_event_pid] map[Kind:function Name:perf_event_pid_type] map[Kind:function Name:perf_event_print_debug] map[Kind:function Name:perf_event_read] map[Kind:function Name:perf_event_read_event] map[Kind:function Name:perf_event_read_local] map[Kind:function Name:perf_event_read_value] map[Kind:function Name:perf_event_read_value] map[Kind:function Name:perf_event_refresh] map[Kind:function Name:perf_event_refresh] map[Kind:function Name:perf_event_release_kernel] map[Kind:function Name:perf_event_release_kernel] map[Kind:function Name:perf_event_remove_on_exec] map[Kind:function Name:perf_event_sched_in] map[Kind:function Name:perf_event_set_addr_filter] map[Kind:function Name:perf_event_set_bpf_handler] map[Kind:function Name:perf_event_set_bpf_prog] map[Kind:function Name:perf_event_set_clock] map[Kind:function Name:perf_event_set_filter] map[Kind:function Name:perf_event_set_filter] map[Kind:function Name:perf_event_set_output] map[Kind:function Name:perf_event_set_output] map[Kind:function Name:perf_event_set_state] map[Kind:function Name:perf_event_setup_cpumask] map[Kind:function Name:perf_event_stop] map[Kind:function Name:perf_event_switch] map[Kind:function Name:perf_event_switch] map[Kind:function Name:perf_event_switch_match] map[Kind:function Name:perf_event_switch_output] map[Kind:function Name:perf_event_sync_stat] map[Kind:function Name:perf_event_sysfs_init] map[Kind:function Name:perf_event_sysfs_show] map[Kind:function Name:perf_event_sysfs_show] map[Kind:function Name:perf_event_task] map[Kind:function Name:perf_event_task_disable] map[Kind:function Name:perf_event_task_enable] map[Kind:function Name:perf_event_task_match] map[Kind:function Name:perf_event_task_output] map[Kind:function Name:perf_event_task_tick] map[Kind:function Name:perf_event_text_poke] map[Kind:function Name:perf_event_text_poke_match] map[Kind:function Name:perf_event_text_poke_output] map[Kind:function Name:perf_event_throttle] map[Kind:function Name:perf_event_throttle_group] map[Kind:function Name:perf_event_tid] map[Kind:function Name:perf_event_time] map[Kind:function Name:perf_event_time] map[Kind:function Name:perf_event_time_now] map[Kind:function Name:perf_event_unthrottle] map[Kind:function Name:perf_event_unthrottle_group] map[Kind:function Name:perf_event_update_sibling_time] map[Kind:function Name:perf_event_update_time] map[Kind:function Name:perf_event_update_userpage] map[Kind:function Name:perf_event_update_userpage] map[Kind:function Name:perf_event_validate_size] map[Kind:function Name:perf_event_wakeup] map[Kind:function Name:perf_exclude_event] map[Kind:function Name:perf_fasync] map[Kind:function Name:perf_fill_ns_link_info] map[Kind:function Name:perf_free_addr_filters] map[Kind:function Name:perf_free_addr_filters] map[Kind:function Name:perf_free_ctx_data_rcu] map[Kind:function Name:perf_get_aux_event] map[Kind:function Name:perf_get_event] map[Kind:function Name:perf_get_page_size] map[Kind:function Name:perf_get_pgtable_size] map[Kind:function Name:perf_group_attach] map[Kind:function Name:perf_group_detach] map[Kind:function Name:perf_init_event] map[Kind:function Name:perf_install_in_context] map[Kind:function Name:perf_instruction_pointer] map[Kind:function Name:perf_ioctl] map[Kind:function Name:perf_iterate_ctx] map[Kind:function Name:perf_iterate_sb] map[Kind:function Name:perf_iterate_sb_cpu] map[Kind:function Name:perf_less_group_idx] map[Kind:function Name:perf_lock_task_context] map[Kind:function Name:perf_log_itrace_start] map[Kind:function Name:perf_log_itrace_start] map[Kind:function Name:perf_log_lost_samples] map[Kind:function Name:perf_log_throttle] map[Kind:function Name:perf_log_throttle] map[Kind:function Name:perf_misc_flags] map[Kind:function Name:perf_mmap] map[Kind:function Name:perf_mmap_account] map[Kind:function Name:perf_mmap_aux] map[Kind:function Name:perf_mmap_calc_limits] map[Kind:function Name:perf_mmap_close] map[Kind:function Name:perf_mmap_may_split] map[Kind:function Name:perf_mmap_open] map[Kind:function Name:perf_mmap_pfn_mkwrite] map[Kind:function Name:perf_mmap_rb] map[Kind:function Name:perf_mux_hrtimer_handler] map[Kind:function Name:perf_mux_hrtimer_restart] map[Kind:function Name:perf_mux_hrtimer_restart_ipi] map[Kind:function Name:perf_need_aux_event] map[Kind:function Name:perf_output_read] map[Kind:function Name:perf_output_read_group] map[Kind:function Name:perf_output_read_one] map[Kind:function Name:perf_output_sample] map[Kind:function Name:perf_output_sample_regs] map[Kind:function Name:perf_output_sample_ustack] map[Kind:function Name:perf_pending_disable] map[Kind:function Name:perf_pending_irq] map[Kind:function Name:perf_pending_task] map[Kind:function Name:perf_pin_task_context] map[Kind:function Name:perf_pmu_cancel_txn] map[Kind:function Name:perf_pmu_commit_txn] map[Kind:function Name:perf_pmu_disable] map[Kind:function Name:perf_pmu_enable] map[Kind:function Name:perf_pmu_free] map[Kind:function Name:perf_pmu_migrate_context] map[Kind:function Name:perf_pmu_migrate_context] map[Kind:function Name:perf_pmu_nop_int] map[Kind:function Name:perf_pmu_nop_txn] map[Kind:function Name:perf_pmu_nop_void] map[Kind:function Name:perf_pmu_output_stop] map[Kind:function Name:perf_pmu_output_stop] map[Kind:function Name:perf_pmu_read] map[Kind:function Name:perf_pmu_register] map[Kind:function Name:perf_pmu_register] map[Kind:function Name:perf_pmu_resched] map[Kind:function Name:perf_pmu_sched_task] map[Kind:function Name:perf_pmu_snapshot_aux] map[Kind:function Name:perf_pmu_start_txn] map[Kind:function Name:perf_pmu_unregister] map[Kind:function Name:perf_pmu_unregister] map[Kind:function Name:perf_poll] map[Kind:function Name:perf_prepare_header] map[Kind:function Name:perf_prepare_sample] map[Kind:function Name:perf_prepare_sample_aux] map[Kind:function Name:perf_put_aux_event] map[Kind:function Name:perf_read] map[Kind:function Name:perf_read_group] map[Kind:function Name:perf_read_one] map[Kind:function Name:perf_reboot] map[Kind:function Name:perf_release] map[Kind:function Name:perf_remove_from_context] map[Kind:function Name:perf_remove_from_owner] map[Kind:function Name:perf_remove_from_owner] map[Kind:function Name:perf_report_aux_output_id] map[Kind:function Name:perf_report_aux_output_id] map[Kind:function Name:perf_rotate_context] map[Kind:function Name:perf_rotate_context] map[Kind:function Name:perf_sample_event_took] map[Kind:function Name:perf_sample_regs_intr] map[Kind:function Name:perf_sample_regs_user] map[Kind:function Name:perf_sample_ustack_size] map[Kind:function Name:perf_sched_cb_dec] map[Kind:function Name:perf_sched_cb_inc] map[Kind:function Name:perf_sched_delayed] map[Kind:function Name:perf_sched_delayed] map[Kind:function Name:perf_scope_cpu_topology_cpumask] map[Kind:function Name:perf_scope_cpu_topology_cpumask] map[Kind:function Name:perf_scope_cpumask] map[Kind:function Name:perf_sigtrap] map[Kind:function Name:perf_swevent_add] map[Kind:function Name:perf_swevent_cancel_hrtimer] map[Kind:function Name:perf_swevent_del] map[Kind:function Name:perf_swevent_destroy_hrtimer] map[Kind:function Name:perf_swevent_event] map[Kind:function Name:perf_swevent_get_recursion_context] map[Kind:function Name:perf_swevent_get_recursion_context] map[Kind:function Name:perf_swevent_hrtimer] map[Kind:function Name:perf_swevent_init] map[Kind:function Name:perf_swevent_init_cpu] map[Kind:function Name:perf_swevent_init_hrtimer] map[Kind:function Name:perf_swevent_match] map[Kind:function Name:perf_swevent_overflow] map[Kind:function Name:perf_swevent_put_recursion_context] map[Kind:function Name:perf_swevent_read] map[Kind:function Name:perf_swevent_set_period] map[Kind:function Name:perf_swevent_start] map[Kind:function Name:perf_swevent_start_hrtimer] map[Kind:function Name:perf_swevent_stop] map[Kind:function Name:perf_tp_event] map[Kind:function Name:perf_tp_event] map[Kind:function Name:perf_tp_event_init] map[Kind:function Name:perf_tp_event_match] map[Kind:function Name:perf_tp_event_target_task] map[Kind:function Name:perf_tp_filter_match] map[Kind:function Name:perf_tp_register] map[Kind:function Name:perf_trace_run_bpf_submit] map[Kind:function Name:perf_trace_run_bpf_submit] map[Kind:function Name:perf_try_init_event] map[Kind:function Name:perf_unpin_context] map[Kind:function Name:perf_unwind_deferred_callback] map[Kind:function Name:perf_uprobe_event_init] map[Kind:function Name:perf_uprobe_event_init] map[Kind:function Name:perf_ustack_task_size] map[Kind:function Name:perf_virt_to_phys] map[Kind:function Name:pmu_detach_event] map[Kind:function Name:pmu_detach_events] map[Kind:function Name:pmu_dev_alloc] map[Kind:function Name:pmu_dev_is_visible] map[Kind:function Name:pmu_dev_release] map[Kind:function Name:pmu_empty] map[Kind:function Name:pmu_get_event] map[Kind:function Name:pmu_groups_sched_in] map[Kind:function Name:primary_event_id] map[Kind:function Name:put_ctx] map[Kind:function Name:put_event] map[Kind:function Name:put_event] map[Kind:function Name:put_pmu_ctx] map[Kind:function Name:ref_ctr_offset_show] map[Kind:function Name:remote_function] map[Kind:function Name:retprobe_show] map[Kind:function Name:ring_buffer_attach] map[Kind:function Name:ring_buffer_attach] map[Kind:function Name:ring_buffer_get] map[Kind:function Name:ring_buffer_put] map[Kind:function Name:ring_buffer_wakeup] map[Kind:function Name:rotate_ctx] map[Kind:function Name:sample_is_allowed] map[Kind:function Name:should_sample_guest] map[Kind:function Name:sw_perf_event_destroy] map[Kind:function Name:swevent_hash] map[Kind:function Name:swevent_hlist_deref] map[Kind:function Name:swevent_hlist_get] map[Kind:function Name:swevent_hlist_get_cpu] map[Kind:function Name:swevent_hlist_put] map[Kind:function Name:swevent_hlist_put_cpu] map[Kind:function Name:swevent_hlist_release] map[Kind:function Name:sync_child_event] map[Kind:function Name:task_clock_event_add] map[Kind:function Name:task_clock_event_del] map[Kind:function Name:task_clock_event_init] map[Kind:function Name:task_clock_event_read] map[Kind:function Name:task_clock_event_start] map[Kind:function Name:task_clock_event_stop] map[Kind:function Name:task_clock_event_update] map[Kind:function Name:task_ctx_sched_out] map[Kind:function Name:task_function_call] map[Kind:function Name:this_cpc] map[Kind:function Name:tp_perf_event_destroy] map[Kind:function Name:type_show] map[Kind:function Name:unaccount_event] map[Kind:function Name:unaccount_freq_event] map[Kind:function Name:unaccount_freq_event_nohz] map[Kind:function Name:unaccount_pmu_sb_event] map[Kind:function Name:unclone_ctx] map[Kind:function Name:update_cgrp_time_from_cpuctx] map[Kind:function Name:update_cgrp_time_from_event] map[Kind:function Name:update_context_time] map[Kind:function Name:update_context_time] map[Kind:function Name:update_perf_cpu_limits] map[Kind:function Name:visit_groups_merge]] Missing:false]

47/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
Okay, here's the summary, expressed as your thoughts:

**Analyzing Performance Event Reset**

Right, let's dive in. My immediate focus is on the `_perf_event_reset` function. I need to understand its role within the broader performance monitoring context. It's almost certain this function is pivotal in initializing or restoring the state of performance counters or event groups. I'll need to confirm that it's handling the expected edge cases and potential race conditions. Is it thread-safe? How does it interact with other components? I'll probably start by cross-referencing this routine with the relevant kernel documentation and associated source code, ensuring I'm on solid ground with my interpretation of its function. My suspicion is that this is a critical function for ensuring accurate and reliable performance data collection, so I will need to understand it at the deepest levels. I also want to determine the impact of this function from the top, down. What will be the effects on dependent components?



48/2 2026/01/14 13:11 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:_perf_event_reset SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6157:	static void _perf_event_reset(struct perf_event *event)
6158:	{
6159:		(void)perf_event_read(event, false);
6160:		local64_set(&event->count, 0);
6161:		perf_event_update_userpage(event);
6162:	}
 SourceFile:kernel/events/core.c]

49/2 2026/01/14 13:11 llm expert
0m Model:
unknown

Thoughts:
Okay, here's the summary, assuming I'm an expert in this field, and speaking as myself:

**Investigating Performance Event Enablement**

Right, so I need to get to the bottom of this. The problem is probably tied to performance events, so my first step is to dive into the `_perf_event_enable` function. This is where the magic happens, or in this case, where the issue is likely rooted. I'm assuming that it is the most likely source of the problem. This function is critical for controlling and manipulating those low-level performance counters, and any misstep there could manifest in the weird behavior I'm seeing. So, let's start there.



50/2 2026/01/14 13:12 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:_perf_event_enable SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:3170:	/*
3171:	 * Enable an event.
3172:	 *
3173:	 * If event->ctx is a cloned context, callers must make sure that
3174:	 * every task struct that event->ctx->task could possibly point to
3175:	 * remains valid.  This condition is satisfied when called through
3176:	 * perf_event_for_each_child or perf_event_for_each as described
3177:	 * for perf_event_disable.
3178:	 */
3179:	static void _perf_event_enable(struct perf_event *event)
3180:	{
3181:		struct perf_event_context *ctx = event->ctx;
3182:	
3183:		raw_spin_lock_irq(&ctx->lock);
3184:		if (event->state >= PERF_EVENT_STATE_INACTIVE ||
3185:		    event->state <  PERF_EVENT_STATE_ERROR) {
3186:	out:
3187:			raw_spin_unlock_irq(&ctx->lock);
3188:			return;
3189:		}
3190:	
3191:		/*
3192:		 * If the event is in error state, clear that first.
3193:		 *
3194:		 * That way, if we see the event in error state below, we know that it
3195:		 * has gone back into error state, as distinct from the task having
3196:		 * been scheduled away before the cross-call arrived.
3197:		 */
3198:		if (event->state == PERF_EVENT_STATE_ERROR) {
3199:			/*
3200:			 * Detached SIBLING events cannot leave ERROR state.
3201:			 */
3202:			if (event->event_caps & PERF_EV_CAP_SIBLING &&
3203:			    event->group_leader == event)
3204:				goto out;
3205:	
3206:			event->state = PERF_EVENT_STATE_OFF;
3207:		}
3208:		raw_spin_unlock_irq(&ctx->lock);
3209:	
3210:		event_function_call(event, __perf_event_enable, NULL);
3211:	}
 SourceFile:kernel/events/core.c]

51/2 2026/01/14 13:12 llm expert
0m Model:
unknown

Thoughts:
Okay, here's my take on those thoughts, as an expert in my field, distilled into a first-person perspective:

**Diving into `__perf_event_enable`**

Alright, let's zero in on this `__perf_event_enable` function. My initial thought is to immediately consider its implications within the broader perf subsystem. It's the "enable" function, so it's critical. I'm already mentally running through the various contexts where this would be called – during event creation, perhaps, or when switching between contexts, or even during a CPU hotplug event. What are the synchronization primitives used? Spinlocks? Mutexes? And most importantly, what resources are being protected? Is it per-cpu data? Global structures?

I'm thinking about the potential for contention and the impact on overall performance if this is a hot path. The design here must be extremely careful to minimize any overhead. The implementation will likely involve modifying some hardware control registers, and I need to consider the associated memory barriers and cache coherency implications. Are they handled correctly? Are there any potential race conditions? I'll probably start by looking at the callers to see *how* and *when* it's being invoked. Then, I need to see if it's in an interrupt context or task context.

Ultimately, I need to understand its impact on the whole system. What side effects does enabling an event have? What happens if an error occurs during the enable process? Does it have any implications for other features in the perf subsystem like sampling or filtering? Let's get cracking.



52/2 2026/01/14 13:12 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:__perf_event_enable SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:3130:	/*
3131:	 * Cross CPU call to enable a performance event
3132:	 */
3133:	static void __perf_event_enable(struct perf_event *event,
3134:					struct perf_cpu_context *cpuctx,
3135:					struct perf_event_context *ctx,
3136:					void *info)
3137:	{
3138:		struct perf_event *leader = event->group_leader;
3139:		struct perf_event_context *task_ctx;
3140:	
3141:		if (event->state >= PERF_EVENT_STATE_INACTIVE ||
3142:		    event->state <= PERF_EVENT_STATE_ERROR)
3143:			return;
3144:	
3145:		ctx_time_freeze(cpuctx, ctx);
3146:	
3147:		perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);
3148:		perf_cgroup_event_enable(event, ctx);
3149:	
3150:		if (!ctx->is_active)
3151:			return;
3152:	
3153:		if (!event_filter_match(event))
3154:			return;
3155:	
3156:		/*
3157:		 * If the event is in a group and isn't the group leader,
3158:		 * then don't put it on unless the group is on.
3159:		 */
3160:		if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE)
3161:			return;
3162:	
3163:		task_ctx = cpuctx->task_ctx;
3164:		if (ctx->task)
3165:			WARN_ON_ONCE(task_ctx != ctx);
3166:	
3167:		ctx_resched(cpuctx, task_ctx, event->pmu_ctx->pmu, get_event_type(event));
3168:	}
 SourceFile:kernel/events/core.c]

53/2 2026/01/14 13:12 llm expert
0m Model:
unknown

Thoughts:
**Thinking Through the Perf Event Time Update**

Okay, so I'm focusing on how `perf_event_update_time` is called within the kernel. The typical path seems to be through `__perf_event_enable`, which, in turn, calls `perf_event_set_state`. Critically, `__perf_event_enable` is invoked via `event_function_call`, which runs on the CPU where the event or context is active. This means it already has the relevant locks in place.

So, the key point is where is `perf_event_update_time` being called WITHOUT the safety net of `ctx->lock`? It appears that `perf_mmap_rb` is the only such place.

Wait... I need to double-check that assumption. Can `perf_mmap_rb` *actually* acquire `ctx->lock`? Looking at it, can't it just call `perf_event_ctx_lock(event)`? That would solve this.

But, before I get too excited, I should make absolutely sure I haven't missed other places. Let me do a quick scan of `core.c` for any other instances of `perf_event_update_time`. I'll use `grep` with `codesearch-definition-source` but I think I'll try checking  `perf_event_set_output` first.



54/2 2026/01/14 13:12 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_event_set_output SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:13296:	static int
13297:	perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
13298:	{
13299:		struct perf_buffer *rb = NULL;
13300:		int ret = -EINVAL;
13301:	
13302:		if (!output_event) {
13303:			mutex_lock(&event->mmap_mutex);
13304:			goto set;
13305:		}
13306:	
13307:		/* don't allow circular references */
13308:		if (event == output_event)
13309:			goto out;
13310:	
13311:		/*
13312:		 * Don't allow cross-cpu buffers
13313:		 */
13314:		if (output_event->cpu != event->cpu)
13315:			goto out;
13316:	
13317:		/*
13318:		 * If its not a per-cpu rb, it must be the same task.
13319:		 */
13320:		if (output_event->cpu == -1 && output_event->hw.target != event->hw.target)
13321:			goto out;
13322:	
13323:		/*
13324:		 * Mixing clocks in the same buffer is trouble you don't need.
13325:		 */
13326:		if (output_event->clock != event->clock)
13327:			goto out;
13328:	
13329:		/*
13330:		 * Either writing ring buffer from beginning or from end.
13331:		 * Mixing is not allowed.
13332:		 */
13333:		if (is_write_backward(output_event) != is_write_backward(event))
13334:			goto out;
13335:	
13336:		/*
13337:		 * If both events generate aux data, they must be on the same PMU
13338:		 */
13339:		if (has_aux(event) && has_aux(output_event) &&
13340:		    event->pmu != output_event->pmu)
13341:			goto out;
13342:	
13343:		/*
13344:		 * Hold both mmap_mutex to serialize against perf_mmap_close().  Since
13345:		 * output_event is already on rb->event_list, and the list iteration
13346:		 * restarts after every removal, it is guaranteed this new event is
13347:		 * observed *OR* if output_event is already removed, it's guaranteed we
13348:		 * observe !rb->mmap_count.
13349:		 */
13350:		mutex_lock_double(&event->mmap_mutex, &output_event->mmap_mutex);
13351:	set:
13352:		/* Can't redirect output if we've got an active mmap() */
13353:		if (refcount_read(&event->mmap_count))
13354:			goto unlock;
13355:	
13356:		if (output_event) {
13357:			if (output_event->state <= PERF_EVENT_STATE_REVOKED)
13358:				goto unlock;
13359:	
13360:			/* get the rb we want to redirect to */
13361:			rb = ring_buffer_get(output_event);
13362:			if (!rb)
13363:				goto unlock;
13364:	
13365:			/* did we race against perf_mmap_close() */
13366:			if (!refcount_read(&rb->mmap_count)) {
13367:				ring_buffer_put(rb);
13368:				goto unlock;
13369:			}
13370:		}
13371:	
13372:		ring_buffer_attach(event, rb);
13373:	
13374:		ret = 0;
13375:	unlock:
13376:		mutex_unlock(&event->mmap_mutex);
13377:		if (output_event)
13378:			mutex_unlock(&output_event->mmap_mutex);
13379:	
13380:	out:
13381:		return ret;
13382:	}
 SourceFile:kernel/events/core.c]

55/2 2026/01/14 13:12 llm expert
0m Model:
unknown

Thoughts:
**A Deep Dive into a Potential Data Race in the Perf Subsystem**

Alright, let's break this down. It starts with a question: why `perf_event_set_output` doesn't call `perf_event_update_time` while `perf_mmap_rb` does. The initial thought is that it's related to updating the userpage when we `mmap`. Looking at `perf_mmap_rb` code:

```c
7034:		ring_buffer_attach(event, rb);
7035:	
7036:		perf_event_update_time(event);
7037:		perf_event_init_userpage(event);
7038:		perf_event_update_userpage(event);
```

The worry is that without `perf_event_update_time`, `perf_event_update_userpage` might be using outdated values for `total_time_enabled/running`. Digging deeper, `perf_event_update_userpage` calls `calc_timer_values`, which then calls `__perf_update_times`, which uses `event->tstamp`, `event->total_time_enabled`, and `event->total_time_running`. If `event->tstamp` is old, the `delta` will be large. However, if `event->total_time_enabled` is also old, the sum `event->total_time_enabled + delta` should still be correct as long as `event->tstamp` and `event->total_time_enabled` are consistent. `perf_event_update_time` is the one updating them together.

The alarm bells start ringing. If `perf_mmap_rb` calls `perf_event_update_time` but isn't holding `ctx->lock`, we have a potential data race. Is this a known issue? A quick search brings up a related commit, promising. But, let's see what is involved.

Okay, other `perf_event` fields might be raced on. The report mentioned `tstamp`. The analysis highlights a critical scenario:

*   **Write:** `event->tstamp = now;`
*   **Read:** `u64 delta = now - event->tstamp;`

The worry is if one thread writes `tstamp` while another reads it, we're going to get a wrong delta. The value change is `0x000000000038c145 -> 0x00000000003929d3`.

Thread 2, which might be `event_sched_out`, is trying to calculate how long the event was active since the last update, but Thread 1 just updated the current time to `tstamp`, then the delta will be ~0. But, `total_time_enabled` and `total_time_running` are also updated in Thread 1. So, if thread 2 reads the NEW `tstamp` but the OLD `total_time_enabled`, it will only add ~0 to the old value. This loses the timing information.

Therefore, this is a harmful data race.

Why does `perf_mmap_rb` call `perf_event_update_time` without the lock? The first guess is to use `event_function_call`, but `perf_mmap_rb` is already in a complex state. Then, the `perf_mmap` code is checked:

```c
7163:				ret = perf_mmap_rb(vma, event, nr_pages);
```

This is called while holding `mmap_mutex`, which is a good starting point. The fix is to take `ctx->lock` around `perf_event_update_time` and the other calls within `perf_mmap_rb`.

The comment in `perf_event_update_userpage` adds more context:

```c
6554:		 * we cannot simply called update_context_time()
6555:		 * because of locking issue as we can be called in
6556:		 * NMI context
```

But `perf_mmap_rb` is not called in an NMI context. It's called from the `mmap` syscall, so taking the lock should be possible. No deadlocks are expected as `event_sched_out` holds `ctx->lock` but doesn't take `mmap_mutex`.

Checking `event_sched_out`'s descendants reveals no calls to `perf_event_update_userpage`. The calls to `perf_event_update_


56/2 2026/01/14 13:12 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_mmap_close SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6723:	/*
6724:	 * A buffer can be mmap()ed multiple times; either directly through the same
6725:	 * event, or through other events by use of perf_event_set_output().
6726:	 *
6727:	 * In order to undo the VM accounting done by perf_mmap() we need to destroy
6728:	 * the buffer here, where we still have a VM context. This means we need
6729:	 * to detach all events redirecting to us.
6730:	 */
6731:	static void perf_mmap_close(struct vm_area_struct *vma)
6732:	{
6733:		struct perf_event *event = vma->vm_file->private_data;
6734:		mapped_f unmapped = get_mapped(event, event_unmapped);
6735:		struct perf_buffer *rb = ring_buffer_get(event);
6736:		struct user_struct *mmap_user = rb->mmap_user;
6737:		int mmap_locked = rb->mmap_locked;
6738:		unsigned long size = perf_data_size(rb);
6739:		bool detach_rest = false;
6740:	
6741:		/* FIXIES vs perf_pmu_unregister() */
6742:		if (unmapped)
6743:			unmapped(event, vma->vm_mm);
6744:	
6745:		/*
6746:		 * The AUX buffer is strictly a sub-buffer, serialize using aux_mutex
6747:		 * to avoid complications.
6748:		 */
6749:		if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff &&
6750:		    refcount_dec_and_mutex_lock(&rb->aux_mmap_count, &rb->aux_mutex)) {
6751:			/*
6752:			 * Stop all AUX events that are writing to this buffer,
6753:			 * so that we can free its AUX pages and corresponding PMU
6754:			 * data. Note that after rb::aux_mmap_count dropped to zero,
6755:			 * they won't start any more (see perf_aux_output_begin()).
6756:			 */
6757:			perf_pmu_output_stop(event);
6758:	
6759:			/* now it's safe to free the pages */
6760:			atomic_long_sub(rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->locked_vm);
6761:			atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
6762:	
6763:			/* this has to be the last one */
6764:			rb_free_aux(rb);
6765:			WARN_ON_ONCE(refcount_read(&rb->aux_refcount));
6766:	
6767:			mutex_unlock(&rb->aux_mutex);
6768:		}
6769:	
6770:		if (refcount_dec_and_test(&rb->mmap_count))
6771:			detach_rest = true;
6772:	
6773:		if (!refcount_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex))
6774:			goto out_put;
6775:	
6776:		ring_buffer_attach(event, NULL);
6777:		mutex_unlock(&event->mmap_mutex);
6778:	
6779:		/* If there's still other mmap()s of this buffer, we're done. */
6780:		if (!detach_rest)
6781:			goto out_put;
6782:	
6783:		/*
6784:		 * No other mmap()s, detach from all other events that might redirect
6785:		 * into the now unreachable buffer. Somewhat complicated by the
6786:		 * fact that rb::event_lock otherwise nests inside mmap_mutex.
6787:		 */
6788:	again:
6789:		rcu_read_lock();
6790:		list_for_each_entry_rcu(event, &rb->event_list, rb_entry) {
6791:			if (!atomic_long_inc_not_zero(&event->refcount)) {
6792:				/*
6793:				 * This event is en-route to free_event() which will
6794:				 * detach it and remove it from the list.
6795:				 */
6796:				continue;
6797:			}
6798:			rcu_read_unlock();
6799:	
6800:			mutex_lock(&event->mmap_mutex);
6801:			/*
6802:			 * Check we didn't race with perf_event_set_output() which can
6803:			 * swizzle the rb from under us while we were waiting to
6804:			 * acquire mmap_mutex.
6805:			 *
6806:			 * If we find a different rb; ignore this event, a next
6807:			 * iteration will no longer find it on the list. We have to
6808:			 * still restart the iteration to make sure we're not now
6809:			 * iterating the wrong list.
6810:			 */
6811:			if (event->rb == rb)
6812:				ring_buffer_attach(event, NULL);
6813:	
6814:			mutex_unlock(&event->mmap_mutex);
6815:			put_event(event);
6816:	
6817:			/*
6818:			 * Restart the iteration; either we're on the wrong list or
6819:			 * destroyed its integrity by doing a deletion.
6820:			 */
6821:			goto again;
6822:		}
6823:		rcu_read_unlock();
6824:	
6825:		/*
6826:		 * It could be there's still a few 0-ref events on the list; they'll
6827:		 * get cleaned up by free_event() -- they'll also still have their
6828:		 * ref on the rb and will free it whenever they are done with it.
6829:		 *
6830:		 * Aside from that, this buffer is 'fully' detached and unmapped,
6831:		 * undo the VM accounting.
6832:		 */
6833:	
6834:		atomic_long_sub((size >> PAGE_SHIFT) + 1 - mmap_locked,
6835:				&mmap_user->locked_vm);
6836:		atomic64_sub(mmap_locked, &vma->vm_mm->pinned_vm);
6837:		free_uid(mmap_user);
6838:	
6839:	out_put:
6840:		ring_buffer_put(rb); /* could be last */
6841:	}
 SourceFile:kernel/events/core.c]

57/2 2026/01/14 13:12 llm expert
0m Model:
unknown

Thoughts:
Okay, here's my thought process on this, distilled into a first-person expert summary:

**Hunting Down That `ring_buffer_attach` Definition**

Alright, I'm still coming up empty on finding the full definition of `ring_buffer_attach`. I know it's *got* to be around here somewhere. Let me try a more direct approach – I'll search for the full function signature using `void ring_buffer_attach(`, since `codesearch-definition-source` seems to be giving me grief.

Wait a second… if I use `grep` within `codesearch-definition-source`, providing a *little* bit of surrounding context might work better. But the tricky part is I don't recall the exact line number.

Okay, back to the basics. Let's try `codesearch-definition-source` again, but this time with a specific `SourceFile` in mind. Could it be in a different file than I initially thought? The `codesearch-file-index` is my friend here, and it previously pointed me to `kernel/events/core.c`.

Aha! Hang on... I see it in that list from `codesearch-file-index`: `{Kind: function, Name: ring_buffer_attach}`! If I run `codesearch-definition-source`, and it gives me *just* the prototype, it might then include a *second* entry for the actual definition, assuming its implementation is within that file. I can then use that.

Right, so to be sure, let's grab the entire file context. I'll ask for the full file `kernel/events/core.c`, specifically focusing on the area around line numbers 5900-6000. That should give me the complete picture and allow me to find the definition quickly.



58/2 2026/01/14 13:12 tool codesearch-definition-source
0m Model:
unknown

Args:
map[IncludeLines:true Name:perf_poll SourceFile:kernel/events/core.c]

Results:
map[Missing:false SourceCode:6124:	static __poll_t perf_poll(struct file *file, poll_table *wait)
6125:	{
6126:		struct perf_event *event = file->private_data;
6127:		struct perf_buffer *rb;
6128:		__poll_t events = EPOLLHUP;
6129:	
6130:		if (event->state <= PERF_EVENT_STATE_REVOKED)
6131:			return EPOLLERR;
6132:	
6133:		poll_wait(file, &event->waitq, wait);
6134:	
6135:		if (event->state <= PERF_EVENT_STATE_REVOKED)
6136:			return EPOLLERR;
6137:	
6138:		if (is_event_hup(event))
6139:			return events;
6140:	
6141:		if (unlikely(READ_ONCE(event->state) == PERF_EVENT_STATE_ERROR &&
6142:			     event->attr.pinned))
6143:			return EPOLLERR;
6144:	
6145:		/*
6146:		 * Pin the event->rb by taking event->mmap_mutex; otherwise
6147:		 * perf_event_set_output() can swizzle our rb and make us miss wakeups.
6148:		 */
6149:		mutex_lock(&event->mmap_mutex);
6150:		rb = event->rb;
6151:		if (rb)
6152:			events = atomic_xchg(&rb->poll, 0);
6153:		mutex_unlock(&event->mmap_mutex);
6154:		return events;
6155:	}
 SourceFile:kernel/events/core.c]

59/2 2026/01/14 13:12 llm expert
0m Model:
unknown

Thoughts:
**Finding the Definition of `ring_buffer_attach`**

Okay, let me retrace my steps on this. I need to nail down the definition of `ring_buffer_attach`. My initial thought was to jump into `kernel/events/core.c` around line 5900 and hunt for it directly. Then I remembered I could potentially find it again via `perf_event_set_output` since I know it's called in there, and that would give me context.

Wait a second, there's a better way. I can use `codesearch-definition-source`! I should be able to just search for the function name directly. No... let me try searching for the string "rb_entry" used in `perf_mmap_close` in relation to `ring_buffer_attach`. But that didn't work.

Aha! Got it. I remembered I had used `codesearch-definition-source` on `perf_mmap_rb` before, and I could just look at the lines around that. Wait, didn't I do that already?

Alright, let's try a different approach. I'll focus on the data structures. I'll search for the definition of `ring_buffer_attach` by searching for `rb->event_list` which it likely uses. That should get me there.



LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)