DF-2712 / df2712_storm.c
/* * df2712_storm.c -- unprivileged scheduler-pressure storm for DF-2712. * * Usage: df2712_storm <nprocs> <seconds> [pin_victim] * * nprocs processes, each single-threaded, hammering sched_yield(). * Every yield drives bsd4_release_curproc -> bsd4_setrunqueue (fresh * lwp_rebal_ticks) -> bsd4_acquire_curproc -> bsd4_select_curproc -> * bsd4_chooseproc_locked_cache_coherent under bsd4_spin, which calls * bsd4_kick_helper (up to queue_checks times per scan) -- the spin-held * lwkt_send_ipiq()/wakeup() path at usched_bsd4.c:1590-1615. * * No affinity syscalls are needed: chooseproc_cc kicks any candidate * homed on a non-sibling cpu that is batchy and inside its rebal * window (usched_bsd4.c:1483-1520). A uniform yield storm of N * processes spread over 6 cpus satisfies all three constantly. * * pin_victim (optional, requires privilege on this kernel: usched_set * USCHED_SET_CPU needs SYSCAP_NOSCHED_CPUSET = uid 0, kern_usched.c:235): * if given, 5/6 of the processes pin themselves to cpu `pin_victim` * (perpetual kick target) and 1/6 spread over the other cpus (kickers). * * Exits 0 printing "STORM-DONE ..." on survival. */ #include <sys/types.h> #include <sys/wait.h> #include <sys/usched.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <errno.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(int argc, char **argv) { long nprocs = 200, secs = 60; int pin_victim = -1; long i, ok = 0, bad = 0; int ncpu = 1; size_t sz = sizeof(ncpu); double t0; if (argc > 1) nprocs = atol(argv[1]); if (argc > 2) secs = atol(argv[2]); if (argc > 3) pin_victim = atoi(argv[3]); sysctlbyname("hw.ncpu", &ncpu, &sz, NULL, 0); t0 = now(); for (i = 0; i < nprocs; ++i) { pid_t pid = fork(); if (pid == 0) { double deadline = secs; volatile unsigned long n = 0; /* optional privilege-assisted concentration pinning */ if (pin_victim >= 0) { int c = ((i % 6) == 5) ? (i % (ncpu - 1)) : pin_victim % ncpu; if (usched_set(0, USCHED_SET_CPU, &c, sizeof(c)) < 0) ; /* unpriv: stay unpinned */ } while (now() - t0 < deadline) n += sched_yield(); _exit(0); } if (pid < 0) { perror("fork"); break; } } for (i = 0; i < nprocs; ++i) { int st = 0; if (wait(&st) < 0) { if (errno == EINTR) { --i; continue; } break; } if (WIFEXITED(st) && WEXITSTATUS(st) == 0) ++ok; else ++bad; } printf("STORM-DONE n=%ld ok=%ld bad=%ld secs=%ld pin=%d\n", nprocs, ok, bad, secs, pin_victim); return (bad != 0); } |