DF-2712 / df2712_storm5.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* * df2712_storm5.c -- PULSED unprivileged kick-burst storm for DF-2712. * * Usage: df2712_storm5 <victim_cpu> <n_victim> <n_sender_per_cpu> <cycle_secs> <cycles> * * Each cycle forks a fresh wave (n_victim pinned to victim_cpu + * n_sender_per_cpu pinned to every other cpu, all tight sched_yield) with * lifetime cycle_secs, waits for the wave to finish, sleeps 3 s so the * system goes quiet (bsd4_rdyprocmask bits re-arm via the helper threads), * then repeats. Every wave reproduces the fresh-boot burst conditions * that generate spin-held kick storms in bsd4_chooseproc_cc. * * Unprivileged: lwp_setaffinity self-pin + sched_yield only. */ #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #include <sched.h> #include <errno.h> #define SYS_lwp_setaffinity 544 static double now(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec + ts.tv_nsec / 1e9; } static int pin_to_cpu(int cpu) { unsigned long mask = 1UL << cpu; return syscall(SYS_lwp_setaffinity, 0, -1, &mask); } static void wave_worker(int cpu, double deadline) { volatile unsigned long n = 0; if (pin_to_cpu(cpu) < 0) { } while (now() < deadline) n += sched_yield(); _exit(0); } int main(int argc, char **argv) { int vcpu = 5, ncpu = 6, cy; long nvic = 180, nspc = 12, csec = 3, cycles = 15; long i, c, total, ok, bad; pid_t pid; double t0, dl; size_t sz = sizeof(ncpu); if (argc > 1) vcpu = atoi(argv[1]); if (argc > 2) nvic = atol(argv[2]); if (argc > 3) nspc = atol(argv[3]); if (argc > 4) csec = atol(argv[4]); if (argc > 5) cycles = atol(argv[5]); sysctlbyname("hw.ncpu", &ncpu, &sz, NULL, 0); if (vcpu >= ncpu) vcpu = ncpu - 1; for (cy = 0; cy < cycles; ++cy) { t0 = now(); dl = t0 + csec; total = ok = bad = 0; for (i = 0; i < nvic; ++i) { pid = fork(); if (pid == 0) wave_worker(vcpu, dl); if (pid < 0) break; ++total; } for (c = 0; c < ncpu; ++c) { if ((int)c == vcpu) continue; for (i = 0; i < nspc; ++i) { pid = fork(); if (pid == 0) wave_worker((int)c, dl); if (pid < 0) break; ++total; } } for (i = 0; i < total; ++i) { int st = 0; if (wait(&st) < 0) { if (errno == EINTR) { --i; continue; } break; } if (WIFEXITED(st) && WEXITSTATUS(st) == 0) ++ok; else ++bad; } printf("STORM5-CYCLE %d/%ld ok=%ld bad=%ld\n", cy + 1, cycles, ok, bad); fflush(stdout); sleep(3); /* let rdyprocmask re-arm */ } printf("STORM5-DONE cycles=%ld\n", cycles); return 0; } |