DF-5308 / diag.c
/* diag: how does read() on the ugen node behave, and does N blocked * readers saturate the fifo refcount (ioctl -> ENXIO)? */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/wait.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main(int argc, char **argv) { const char *node = argc > 1 ? argv[1] : "/dev/usb/0.2.1"; int n = argc > 2 ? atoi(argv[2]) : 254; int fd, i, x, err; pid_t pid, pids[512]; char buf[8]; setvbuf(stdout, NULL, _IONBF, 0); fd = open(node, O_RDONLY); if (fd < 0) { printf("open: %s\n", strerror(errno)); return (1); } /* single read behavior with alarm */ pid = fork(); if (pid == 0) { alarm(4); i = read(fd, buf, sizeof(buf)); if (i < 0) _exit(100 + (errno & 0x1f)); _exit(i); } waitpid(pid, &i, 0); if (WIFSIGNALED(i)) printf("single read: blocked (SIGALRM) -> ref held while asleep\n"); else if (WEXITSTATUS(i) >= 100) printf("single read: error errno=%d\n", WEXITSTATUS(i) - 100); else printf("single read: returned %d bytes\n", WEXITSTATUS(i)); /* saturation */ for (i = 0; i < n; i++) { pids[i] = fork(); if (pids[i] == 0) { for (;;) read(fd, buf, sizeof(buf)); _exit(0); } } for (i = 0; i < 20; i++) { usleep(250000); err = ioctl(fd, 0x12345678, &x); printf("t+%dms: ioctl=%d errno=%d\n", (i + 1) * 250, err, errno); if (err != 0) break; } for (i = 0; i < n; i++) kill(pids[i], 9); for (i = 0; i < n; i++) waitpid(pids[i], NULL, 0); err = ioctl(fd, 0x12345678, &x); printf("after drain: ioctl=%d errno=%d\n", err, errno); return (0); } |