⬢ DragonFlyBSD Kernel Audit
DF-2712 / df2712_bench.c
← back to finding ↓ download raw
/*
 * df2712_bench.c -- scheduler sanity microbench for DF-2712 fix validation.
 *
 * Measures, in order:
 *   1. single-thread sched_yield() rate over 2 s
 *   2. fork/exit x 64
 *   3. pipe round-trip latency x 20000 (2 procs)
 * Prints one line per metric.  Run identically on baseline and fixed
 * kernels; scheduling must keep functioning after the deferred-kick fix.
 */
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sched.h>

static double now(void)
{
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return ts.tv_sec + ts.tv_nsec / 1e9;
}

int main(void)
{
	volatile unsigned long n;
	double t0, t1;
	unsigned long it = 0;
	int i, pfd[2];
	char c = 'x';
	pid_t pid;

	/* 1. yield rate */

n = 0;
	t0 = now();
	while (now() - t0 < 2.0) {
		n += sched_yield();
		++it;
	}
	t1 = now();
	printf("YIELD-RATE %.0f /s\n", (double)it / (t1 - t0));

	/* 2. fork/exit */
	t0 = now();
	for (i = 0; i < 64; ++i) {
		pid = fork();
		if (pid == 0)
			_exit(0);
		waitpid(pid, NULL, 0);
	}
	t1 = now();
	printf("FORK64 %.3f s\n", t1 - t0);

	/* 3. pipe round-trip */
	if (pipe(pfd) < 0) { perror("pipe"); return 1; }
	pid = fork();
	if (pid == 0) {
		for (i = 0; i < 20000; ++i) {
			if (read(pfd[0], &c, 1) != 1) _exit(1);
			if (write(pfd[1], &c, 1) != 1) _exit(1);
		}
		_exit(0);
	}
	t0 = now();
	for (i = 0; i < 20000; ++i) {
		if (write(pfd[1], &c, 1) != 1) break;
		if (read(pfd[0], &c, 1) != 1) break;
	}
	t1 = now();
	waitpid(pid, NULL, 0);
	printf("PIPERT %.2f us/rt\n", (t1 - t0) * 1e6 / 20000.0);
	printf("BENCH-DONE\n");
	return 0;
}