tools/testing/selftests/powerpc/pmu/ebb/trace.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/powerpc/pmu/ebb/trace.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/powerpc/pmu/ebb/trace.c
Extension
.c
Size
5796 bytes
Lines
301
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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2014, Michael Ellerman, IBM Corp.
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

#include "trace.h"


struct trace_buffer *trace_buffer_allocate(u64 size)
{
	struct trace_buffer *tb;

	if (size < sizeof(*tb)) {
		fprintf(stderr, "Error: trace buffer too small\n");
		return NULL;
	}

	tb = mmap(NULL, size, PROT_READ | PROT_WRITE,
		  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
	if (tb == MAP_FAILED) {
		perror("mmap");
		return NULL;
	}

	tb->size = size;
	tb->tail = tb->data;
	tb->overflow = false;

	return tb;
}

static bool trace_check_bounds(struct trace_buffer *tb, void *p)
{
	return p < ((void *)tb + tb->size);
}

static bool trace_check_alloc(struct trace_buffer *tb, void *p)
{
	/*
	 * If we ever overflowed don't allow any more input. This prevents us
	 * from dropping a large item and then later logging a small one. The
	 * buffer should just stop when overflow happened, not be patchy. If
	 * you're overflowing, make your buffer bigger.
	 */
	if (tb->overflow)
		return false;

	if (!trace_check_bounds(tb, p)) {
		tb->overflow = true;
		return false;
	}

	return true;
}

static void *trace_alloc(struct trace_buffer *tb, int bytes)
{
	void *p, *newtail;

	p = tb->tail;
	newtail = tb->tail + bytes;
	if (!trace_check_alloc(tb, newtail))
		return NULL;

	tb->tail = newtail;

	return p;
}

static struct trace_entry *trace_alloc_entry(struct trace_buffer *tb, int payload_size)
{
	struct trace_entry *e;

	e = trace_alloc(tb, sizeof(*e) + payload_size);
	if (e)
		e->length = payload_size;

	return e;
}

int trace_log_reg(struct trace_buffer *tb, u64 reg, u64 value)
{
	struct trace_entry *e;
	u64 *p;

Annotation

Implementation Notes