[CC += linux-perf-users@] Hi Nick, > Date: 2026-11-08 21:08:44-0500 > From: Nick Krichevsky > > Hi, > > I was experimenting with perf_event_open(2) and caught this sentence in the > man page. > > Prior to Linux 3.0, setting wakeup_events to 0 resulted in no overflow > notifications; more recent kernels treat 0 the same as 1. > > I wrote a small test program (below) to test this behavior. On > kernel 7.1.13-200.fc44.x86_64, my experience seems to contradict the man page; > it seems that when wakeup_events is 0, it actually notifies the file descriptor > when the ring buffer is half filled (4096 byte size buffer here, (4096 bytes / > 2) / (8 bytes per event) = 256 events). Setting this to 1 sends a notification > after every event. > > My (rough) reading of the source code supports this understanding: > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/events/ring_buffer.c?id=7475ea8b58616b33c04afb976cf0fbaad9dd63fb#n322 > > Is this a stale entry in the man page, or is my understanding of this facility > incorrect? If it is indeed stale, perhaps this could read I don't know; it could be stale, or it could be a misunderstanding of the author of the text, or it could be that you're misunderstanding it. :) The commit that added that text was: 21977c9d2ac8 (2015-01-21; "perf_event_open.2: Clarify description of overflow events") by Vincent. I've added him to CC. Let's see if he or some maintainer can help clarify what happened. > Prior to Linux 3.0, setting wakeup_events to 0 resulted in no overflow > notifications; more recent kernels generate notifications based on a default > watermark of half the ring buffer size. If this is true, we should clarify the exact version in which the behavior changed. > Test run of program: > $ gcc main.c > $ ./a.out 0 > wakeup_events = 0 > wakeup 1: 257 samples of 8 bytes > wakeup 2: 256 samples of 8 bytes > wakeup 3: 256 samples of 8 bytes > wakeup 4: 256 samples of 8 bytes > $ ./a.out 1 > wakeup_events = 1 > wakeup 1: 1 samples of 8 bytes > wakeup 2: 1 samples of 8 bytes > wakeup 3: 1 samples of 8 bytes > wakeup 4: 1 samples of 8 bytes > > Program: > #define _GNU_SOURCE > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > > #define PAGE_SIZE 4096 > > static void *workload(void *unused) { > for (;;) { > } > > return unused; > } > > int main(int argc, char **argv) { > unsigned wakeup_events = argc > 1 ? atoi(argv[1]) : 0; > > pthread_t workload_thread; > pthread_create(&workload_thread, NULL, workload, NULL); > // Needs glibc >= 2.42 > pid_t workload_tid = pthread_gettid_np(workload_thread); > > struct perf_event_attr attrs = {.size = sizeof(attrs)}; > attrs.type = PERF_TYPE_SOFTWARE; > attrs.config = PERF_COUNT_SW_CPU_CLOCK; > attrs.freq = 1; > attrs.sample_freq = 49; > attrs.disabled = 1; > attrs.exclude_kernel = 1; > attrs.wakeup_events = wakeup_events; > > int fd = syscall(SYS_perf_event_open, &attrs, workload_tid, -1, -1, 0); > if (fd < 0) { > perror("perf_event_open"); > return 1; > } > > void *buffer = > mmap(NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); > if (buffer == MAP_FAILED) { > perror("mmap"); > return 1; > } > > struct perf_event_mmap_page *meta = buffer; > char *data = (char *)buffer + meta->data_offset; > > ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); > printf("wakeup_events = %u\n", wakeup_events); > > for (int i = 1; i <= 4; i++) { > struct pollfd poll_fd = {.fd = fd, .events = POLLIN}; > poll(&poll_fd, 1, -1); > > uint64_t head = __atomic_load_n(&meta->data_head, __ATOMIC_ACQUIRE); > uint64_t tail = meta->data_tail; > int sample_count = 0; > int sample_size = 0; > > while (tail < head) { > struct perf_event_header *header = > (struct perf_event_header *)(data + tail % meta->data_size); > > if (header->type == PERF_RECORD_SAMPLE) { > sample_count++; > sample_size = header->size; > } > > tail += header->size; > } > __atomic_store_n(&meta->data_tail, tail, __ATOMIC_RELEASE); > > printf( > "wakeup %d: %d samples of %d bytes\n", > i, sample_count, sample_size > ); > } > > return 0; > } Thanks a lot for the program! Have a lovely day! Alex > > > > > -Nick Krichevsky --