#include #include #include #include #include #include #include #include #include #include static char *progname; static int open_or_die(const char *name, int flag, mode_t mode) { int fd = open(name, flag, mode); if (fd < 0) { fprintf(stderr, "%s: open %s: %s\n", progname, name, strerror(errno)); exit(EXIT_FAILURE); } return fd; } int main(int argc, char *argv[]) { progname = argv[0]; if (argc < 2 || argc > 3) { fprintf(stderr, "%s: usage: %s FILE [-n]\n", argv[0], argv[0]); return EXIT_FAILURE; } // right now the limit for each trace is 256 uintptr_t buf[256]; int infd = open_or_die("/dev/prof", O_RDONLY | O_NONBLOCK, 0); int outfd = open_or_die(argv[1], O_WRONLY | O_CREAT, 0644); // enable raw mode if (isatty(outfd)) { struct termios termios; tcgetattr(outfd, &termios); cfmakeraw(&termios); termios.c_oflag &= ~ONLCR; tcsetattr(outfd, TCSANOW, &termios); } if (argc == 2 || (strcmp(argv[1], "-n") && strcmp(argv[2], "-n"))) { printf("%s: draining /dev/prof\n", argv[0]); // empty it if (ioctl(infd, 12345678, NULL) < 0) return EXIT_FAILURE; } struct pollfd pollfd[2]; pollfd[0].fd = 0; pollfd[0].events = POLLIN; pollfd[0].revents = 0; pollfd[1].fd = infd; pollfd[1].events = POLLIN; pollfd[1].revents = 0; printf("%s: working...\n", argv[0]); while (poll(pollfd, 2, -1)) { if (pollfd[0].revents) break; uint8_t count; read(infd, &count, 1); read(infd, buf, 8 * count); write(outfd, &count, 1); write(outfd, buf, 8 * count); } size_t hits[2]; ioctl(infd, 87654321, hits); size_t total = hits[0] + hits[1]; float u_ratio = (float)hits[0] / (float)total; float k_ratio = 1.f - u_ratio; printf("%s: %lu hits\n", argv[0], total); printf("%s: %lu userspace hits (%01.02f%%)\n", argv[0], hits[0], u_ratio * 100); printf("%s: %lu kernel hits (%01.02f%%)\n", argv[0], hits[1], k_ratio * 100); printf("%s: done\n", argv[0]); return EXIT_SUCCESS; }