DF-5550 / ptchurn.c
/* * ptchurn -- hammer /dev/ptN with open+read+close while the ptsim2 bus * churns targets, so pt periphs are xpt_schedule()d on their device drvq * exactly when AC_LOST_DEVICE frees them (DF-5550 live-path repro). * * usage: ptchurn <first> <last> <seconds> */ #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <errno.h> static volatile sig_atomic_t run_flag = 1; static int consfd = -1; static void on_alarm(int sig) { run_flag = 0; } int main(int argc, char **argv) { int first, last, secs, i; unsigned long *opens, *errs; int nproc; if (argc != 4) { fprintf(stderr, "usage: %s <first> <last> <seconds>\n", argv[0]); return (2); } first = atoi(argv[1]); last = atoi(argv[2]); secs = atoi(argv[3]); nproc = last - first + 1; if (nproc <= 0) return (2); opens = calloc(nproc, sizeof(*opens)); errs = calloc(nproc, sizeof(*errs)); consfd = open("/dev/console", O_WRONLY); signal(SIGALRM, on_alarm); for (i = first; i <= last; i++) { int pid = fork(); if (pid == 0) { char path[64]; unsigned long o = 0, e = 0; int idx = i - first, n = 0; alarm(secs); snprintf(path, sizeof(path), "/dev/pt%d", i); while (run_flag) { int fd = open(path, O_RDWR); if (fd >= 0) { char b[16]; read(fd, b, sizeof(b)); close(fd); o++; } else { e++; } if (++n % 64 == 0) opens[idx] = o, errs[idx] = e; } opens[idx] = o; errs[idx] = e; _exit(0); } } for (i = 0; i < nproc; i++) wait(NULL); { unsigned long o = 0, e = 0; for (i = 0; i < nproc; i++) o += opens[i], e += errs[i]; printf("CHURN-DONE opens=%lu errors=%lu\n", o, e); if (consfd >= 0) dprintf(consfd, "[CHURN] done opens=%lu errors=%lu\n", o, e); } return (0); } |