Despite what https://man7.org/linux/man-pages/man2/PR_TASK_PERF_EVENTS_ENABLE.2const.html#DESCRIPTION says, PR_TASK_PERF_EVENTS_DISABLE disables / enables counters on the current thread, not process.
Counts after PR_TASK_PERF_EVENTS_DISABLE:
main: 0 (expected 0, events disabled)
worker: 537
Test Source (by AI)
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/perf_event.h>
static pthread_barrier_t go, done;
static volatile uint64_t sink;
static void burn(void) {
uint64_t x = 0;
for (uint64_t i = 0; i < 200000000ULL; i++)
x += i * 0x9e3779b97f4a7c15ULL;
sink = x;
}
static uint64_t read_counter(int fd) {
uint64_t v; read(fd, &v, sizeof(v)); return v;
}
static int open_sw_counter(void) {
struct perf_event_attr a = { .size = sizeof(a),
.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_CLOCK };
return syscall(__NR_perf_event_open, &a, 0, -1, -1, 0);
}
static void *worker(void *arg) {
int fd = open_sw_counter();
pthread_barrier_wait(&go);
uint64_t c0 = read_counter(fd);
burn();
printf(" worker: %lu\n", read_counter(fd) - c0);
pthread_barrier_wait(&done);
close(fd);
return NULL;
}
int main(void) {
pthread_barrier_init(&go, NULL, 2);
pthread_barrier_init(&done, NULL, 2);
int fd = open_sw_counter();
pthread_t tid;
pthread_create(&tid, NULL, worker, NULL);
prctl(PR_TASK_PERF_EVENTS_DISABLE);
sleep(1);
pthread_barrier_wait(&go);
uint64_t c0 = read_counter(fd);
burn();
printf(" main: %lu (expected 0, events disabled)\n",
read_counter(fd) - c0);
pthread_barrier_wait(&done);
pthread_join(tid, NULL);
close(fd);
}
Despite what https://man7.org/linux/man-pages/man2/PR_TASK_PERF_EVENTS_ENABLE.2const.html#DESCRIPTION says,
PR_TASK_PERF_EVENTS_DISABLEdisables / enables counters on the current thread, not process.Counts after
PR_TASK_PERF_EVENTS_DISABLE:Test Source (by AI)