1 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <sys/file.h> 5 #include <sys/errno.h> 6 #include <sys/wait.h> 7 #include <string.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <unistd.h> 11 #include <machine/atomic.h> 12 #include "blib.h" 13 14 int 15 main(int ac, char **av) 16 { 17 char *buf; 18 size_t bytes = 512; 19 off_t limit; 20 int fd; 21 int i; 22 int nprocs = 32; 23 double range = 90.0; 24 volatile int *counterp; 25 int clast; 26 int cnext; 27 int cdelta; 28 29 if (ac < 2 || ac > 5) { 30 fprintf(stderr, "%s <device> [bufsize:512 [range%:90 [nprocs:32]]]\n", 31 av[0]); 32 exit (1); 33 } 34 35 if (ac >= 3) { 36 bytes = (size_t)strtoul(av[2], NULL, 0); 37 if (bytes < 512 || (bytes ^ (bytes - 1)) != ((bytes << 1) - 1)) { 38 fprintf(stderr, "bytes must be a power of 2 >= 512\n"); 39 exit (1); 40 } 41 } 42 buf = malloc(bytes); 43 44 if (ac >= 4) { 45 range = strtod(av[3], NULL); 46 } 47 48 if (ac >= 5) { 49 nprocs = strtol(av[4], NULL, 0); 50 if (nprocs < 0 || nprocs > 512) { 51 fprintf(stderr, "absurd nprocs (%d)\n", nprocs); 52 exit(1); 53 } 54 } 55 56 fd = open(av[1], O_RDONLY); 57 if (fd < 0) { 58 fprintf(stderr, "open %s: %s\n", av[1], strerror(errno)); 59 exit (1); 60 } 61 62 lseek(fd, 0L, 2); 63 limit = lseek(fd, 0L, 1); 64 limit = (off_t)((double)limit * range / 100.0); 65 limit &= ~(off_t)(bytes - 1); 66 printf("device %s bufsize %zd limit %4.3fGB nprocs %d\n", 67 av[1], bytes, (double)limit / (1024.0*1024.0*1024.0), nprocs); 68 69 counterp = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, 70 MAP_SHARED|MAP_ANON, -1, 0); 71 72 for (i = 0; i < nprocs; ++i) { 73 if (fork() == 0) { 74 close(fd); 75 fd = open(av[1], O_RDONLY); 76 srandomdev(); 77 for (;;) { 78 long pos; 79 80 pos = random() ^ ((long)random() << 31); 81 pos &= 0x7FFFFFFFFFFFFFFFLLU; 82 pos = (pos % limit) & ~(off_t)(bytes - 1); 83 lseek(fd, pos, 0); 84 read(fd, buf, bytes); 85 atomic_add_int(counterp, 1); 86 } 87 } 88 } 89 start_timing(); 90 sleep(1); 91 start_timing(); 92 clast = *counterp; 93 94 for (;;) { 95 sleep(1); 96 cnext = *counterp; 97 cdelta = cnext - clast; 98 clast = cnext; 99 stop_timing(cdelta, "randread"); 100 } 101 return 0; 102 } 103