tools/perf/bench/breakpoint.c

Source file repositories/reference/linux-study-clean/tools/perf/bench/breakpoint.c

File Facts

System
Linux kernel
Corpus path
tools/perf/bench/breakpoint.c
Extension
.c
Size
7721 bytes
Lines
263
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct breakpoint {
	int fd;
	char watched;
};

static int breakpoint_setup(void *addr)
{
	struct perf_event_attr attr = { .size = 0, };
	int fd;

	attr.type = PERF_TYPE_BREAKPOINT;
	attr.size = sizeof(attr);
	attr.inherit = 1;
	attr.exclude_kernel = 1;
	attr.exclude_hv = 1;
	attr.bp_addr = (unsigned long)addr;
	attr.bp_type = HW_BREAKPOINT_RW;
	attr.bp_len = HW_BREAKPOINT_LEN_1;
	fd = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);

	if (fd < 0)
		fd = -errno;

	return fd;
}

static void *passive_thread(void *arg)
{
	unsigned int *done = (unsigned int *)arg;

	while (!__atomic_load_n(done, __ATOMIC_RELAXED))
		futex_wait(done, 0, NULL, 0);
	return NULL;
}

static void *active_thread(void *arg)
{
	unsigned int *done = (unsigned int *)arg;

	while (!__atomic_load_n(done, __ATOMIC_RELAXED));
	return NULL;
}

static void *breakpoint_thread(void *arg)
{
	unsigned int i, done;
	int *repeat = (int *)arg;
	pthread_t *threads;

	threads = calloc(thread_params.nthreads, sizeof(threads[0]));
	if (!threads)
		exit((perror("calloc"), EXIT_FAILURE));

	while (__atomic_fetch_sub(repeat, 1, __ATOMIC_RELAXED) > 0) {
		done = 0;
		for (i = 0; i < thread_params.nthreads; i++) {
			if (pthread_create(&threads[i], NULL, passive_thread, &done))
				exit((perror("pthread_create"), EXIT_FAILURE));
		}
		__atomic_store_n(&done, 1, __ATOMIC_RELAXED);
		futex_wake(&done, thread_params.nthreads, 0);
		for (i = 0; i < thread_params.nthreads; i++)
			pthread_join(threads[i], NULL);
	}
	free(threads);
	return NULL;
}

// The benchmark creates nbreakpoints inheritable breakpoints,
// then starts nparallel threads which create and join bench_repeat batches of nthreads threads.
int bench_breakpoint_thread(int argc, const char **argv)
{
	unsigned int i, result_usec;
	int repeat = bench_repeat;
	struct breakpoint *breakpoints;
	pthread_t *parallel;
	struct timeval start, stop, diff;

	if (parse_options(argc, argv, thread_options, thread_usage, 0)) {
		usage_with_options(thread_usage, thread_options);
		exit(EXIT_FAILURE);
	}
	breakpoints = calloc(thread_params.nbreakpoints, sizeof(breakpoints[0]));
	parallel = calloc(thread_params.nparallel, sizeof(parallel[0]));
	if (!breakpoints || !parallel)
		exit((perror("calloc"), EXIT_FAILURE));

	for (i = 0; i < thread_params.nbreakpoints; i++) {
		breakpoints[i].fd = breakpoint_setup(&breakpoints[i].watched);

Annotation

Implementation Notes