tools/testing/selftests/pipe/pipe_bench.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/pipe/pipe_bench.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/pipe/pipe_bench.c
Extension
.c
Size
14780 bytes
Lines
617
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 wstats {
	uint64_t writes;
	uint64_t bytes;
	uint64_t lat_sum_ns;
	uint64_t lat_max_ns;
	uint64_t lat_hist[HIST_BUCKETS];
	char *buf;
};

struct rstats {
	char *buf;
};

struct hist_totals {
	uint64_t writes;
	uint64_t bytes;
	uint64_t lat_sum;
	uint64_t lat_max;
};

static inline uint64_t now_ns(void)
{
	struct timespec ts;

	clock_gettime(CLOCK_MONOTONIC, &ts);
	return (uint64_t)ts.tv_sec * 1000000000ull + (uint64_t)ts.tv_nsec;
}

static inline int log2_bucket(uint64_t v)
{
	int b = 0;

	if (!v)
		return 0;
	while (v >>= 1)
		b++;
	return b < HIST_BUCKETS ? b : HIST_BUCKETS - 1;
}

static void *writer(void *arg)
{
	struct wstats *s = arg;

	while (!atomic_load_explicit(&g_stop, memory_order_relaxed)) {
		uint64_t t0 = now_ns();
		ssize_t n = write(g_pipe[1], s->buf, g_msgsize);
		uint64_t dt = now_ns() - t0;

		if (n > 0) {
			s->writes++;
			s->bytes += (uint64_t)n;
			s->lat_sum_ns += dt;
			if (dt > s->lat_max_ns)
				s->lat_max_ns = dt;
			s->lat_hist[log2_bucket(dt)]++;
		} else if (n < 0 && (errno == EPIPE || errno == EBADF)) {
			break;
		}
	}
	return NULL;
}

static void *reader(void *arg)
{
	struct rstats *s = arg;

	/*
	 * Drain until EOF (write end closed by main). g_stop is not checked
	 * here on purpose: writers may be blocked in write() with the pipe
	 * full when g_stop is set, so the reader must keep draining until
	 * main closes the write end.
	 */
	for (;;) {
		ssize_t n = read(g_pipe[0], s->buf, g_msgsize);

		if (n <= 0)
			break;
	}
	return NULL;
}

/* Sum per-writer stats and per-bucket counts into the caller's aggregates. */
static void aggregate_wstats(struct wstats *all, int nw,
			     uint64_t agg[HIST_BUCKETS],
			     struct hist_totals *t)
{
	memset(t, 0, sizeof(*t));
	for (int i = 0; i < nw; i++) {
		t->writes += all[i].writes;
		t->bytes += all[i].bytes;

Annotation

Implementation Notes