DF-2712 / df2712_storm3.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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | /* * df2712_storm3.c -- sustained-kick unprivileged storm for DF-2712. * * Usage: df2712_storm3 <victim_cpu> <n_victim> <n_sender_per_cpu> <secs> * * Improvements over storm2 (whose kick traffic self-extinguishes once the * pure-yielding victims saturate estcpu and sort out of scan heads): * - victims pin to victim_cpu and interleave short sleeps with yield * bursts: the sleep decays estcpu (bsd4_recalculate_estcpu) keeping * their priorities competitive at runq heads, and every wake requeues * them with a fresh lwp_rebal_ticks window (usched_bsd4.c:679). * - senders pin to each non-victim cpu and tight-yield with tiny sleeps: * maximum chooseproc_cc scan rate -> maximum spin-held kick_helper * calls (up to queue_checks per scan, usched_bsd4.c:1483). * * All operations are unprivileged: lwp_setaffinity(0,-1,mask) self-pin * (kern_usched.c:423 allows self always), sched_yield, usleep. */ #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 int g_vcpu = 5; 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 unsigned long rstate = 1; static unsigned long xrand(void) { rstate = rstate * 6364136223846793005UL + 1442695040888963407UL; return (rstate >> 33); } static void victim_loop(long secs, double t0) { if (pin_to_cpu(g_vcpu) < 0) { } while (now() - t0 < secs) { int i; for (i = 0; i < 5; ++i) sched_yield(); usleep(700 + xrand() % 1400); } _exit(0); } static void sender_loop(int cpu, long secs, double t0) { if (pin_to_cpu(cpu) < 0) { } while (now() - t0 < secs) { int i; for (i = 0; i < 40; ++i) sched_yield(); usleep(200 + xrand() % 200); } _exit(0); } int main(int argc, char **argv) { int ncpu = 6; long nvic = 160, nspc = 16, secs = 120; long i, c, total = 0, ok = 0, bad = 0; pid_t pid; double t0; size_t sz = sizeof(ncpu); if (argc > 1) g_vcpu = atoi(argv[1]); if (argc > 2) nvic = atol(argv[2]); if (argc > 3) nspc = atol(argv[3]); if (argc > 4) secs = atol(argv[4]); sysctlbyname("hw.ncpu", &ncpu, &sz, NULL, 0); if (g_vcpu >= ncpu) g_vcpu = ncpu - 1; t0 = now(); for (i = 0; i < nvic; ++i) { pid = fork(); if (pid == 0) victim_loop(secs, t0); if (pid < 0) break; ++total; } for (c = 0; c < ncpu; ++c) { if ((int)c == g_vcpu) continue; for (i = 0; i < nspc; ++i) { pid = fork(); if (pid == 0) sender_loop((int)c, secs, t0); 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("STORM3-DONE vcpu=%d nvic=%ld nspc=%ld ok=%ld bad=%ld secs=%ld\n", g_vcpu, nvic, nspc, ok, bad, secs); return (bad != 0); } |