| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2003-2004 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| /* |
| * Test scaling of multiple processes opening/reading |
| * a number of small files simultaneously. |
| * - create <f> files |
| * - fork <n> processes |
| * - wait for all processes ready |
| * - start all proceses at the same time |
| * - each processes opens , read, closes each file |
| * - option to resync each process at each file |
| * |
| * test [-c cpus] [-b bytes] [-f files] [-v] [-s] [-S] |
| * OR |
| * test -i [-b bytes] [-f files] |
| */ |
| #include <unistd.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/wait.h> |
| #include <fcntl.h> |
| #include <stdlib.h> |
| #include <sys/ipc.h> |
| #include <sys/shm.h> |
| |
| void do_initfiles(void); |
| void slave(int); |
| |
| #define VPRINT(x...) do { if(verbose) fprintf(x);} while(0) |
| #define perrorx(s) do {perror(s); exit(1);} while (0) |
| |
| long bytes=8192; |
| int cpus=1; |
| int init=0; |
| int strided=0; |
| int files=1; |
| int blksize=512; |
| int syncstep=0; |
| int verbose=0; |
| |
| typedef struct { |
| volatile long go; |
| long fill[15]; |
| volatile long rdy[512]; |
| } share_t; |
| |
| share_t *sharep; |
| |
| |
| int |
| runon(int cpu) |
| { |
| #ifdef sys_sched_setaffinity |
| unsigned long mask[8]; |
| |
| if (cpu < 0 || cpu >= 512) |
| return -1; |
| memset(mask, 0, sizeof(mask)); |
| mask[cpu/64] |= 1UL<<(cpu&63); |
| |
| if (syscall(sys_sched_setaffinity, 0, sizeof(mask), mask)) |
| return -1; |
| #endif |
| return 0; |
| } |
| |
| long |
| scaled_atol(char *p) |
| { |
| long val; |
| char *pe; |
| |
| val = strtol(p, &pe, 0); |
| if (*pe == 'K' || *pe == 'k') |
| val *= 1024L; |
| else if (*pe == 'M' || *pe == 'm') |
| val *= 1024L*1024L; |
| else if (*pe == 'G' || *pe == 'g') |
| val *= 1024L*1024L*1024L; |
| else if (*pe == 'p' || *pe == 'P') |
| val *= getpagesize(); |
| return val; |
| } |
| |
| |
| int |
| main(int argc, char** argv) { |
| int shmid; |
| static char optstr[] = "c:b:f:sSivH"; |
| int notdone, stat, i, j, c, er=0; |
| |
| opterr=1; |
| while ((c = getopt(argc, argv, optstr)) != EOF) |
| switch (c) { |
| case 'c': |
| cpus = atoi(optarg); |
| break; |
| case 'b': |
| bytes = scaled_atol(optarg); |
| break; |
| case 'f': |
| files = atoi(optarg); |
| break; |
| case 'i': |
| init++; |
| break; |
| case 's': |
| syncstep++; |
| break; |
| case 'S': |
| strided++; |
| break; |
| case 'v': |
| verbose++; |
| break; |
| case '?': |
| er = 1; |
| break; |
| } |
| if (er) { |
| printf("usage: %s %s\n", argv[0], optstr); |
| exit(1); |
| } |
| |
| |
| if ((shmid = shmget(IPC_PRIVATE, sizeof (share_t), IPC_CREAT|SHM_R|SHM_W)) == -1) |
| perrorx("shmget failed"); |
| sharep = (share_t*)shmat(shmid, (void*)0, SHM_R|SHM_W); |
| memset(sharep, -1, sizeof (share_t)); |
| |
| if (init) { |
| do_initfiles(); |
| exit(0); |
| } |
| for (i=0; i<cpus; i++) { |
| if (fork() == 0) |
| slave(i); |
| } |
| |
| for (i=0; i<files; i++) { |
| VPRINT(stderr, "%d:", i); |
| notdone = cpus; |
| do { |
| for (j=0; j<cpus; j++) { |
| if (sharep->rdy[j] == i) { |
| sharep->rdy[j] = -1; |
| VPRINT(stderr, " %d", j); |
| notdone--; |
| } |
| } |
| } while (notdone); |
| VPRINT(stderr, "\n"); |
| sharep->go = i; |
| if (!syncstep) |
| break; |
| } |
| VPRINT(stderr, "\n"); |
| |
| while (wait(&stat)> 0) |
| VPRINT(stderr, "."); |
| VPRINT(stderr, "\n"); |
| |
| exit(0); |
| } |
| |
| void |
| slave(int id) |
| { |
| int i, fd, byte; |
| char *buf, filename[32]; |
| |
| runon (id+1); |
| buf = malloc(blksize); |
| bzero(buf, blksize); |
| for (i=0; i<files; i++) { |
| if (!i || syncstep) { |
| sharep->rdy[id] = i; |
| while(sharep->go != i); |
| } |
| sprintf(filename, "/tmp/tst.%d", (strided ? ((i + id) % files) : i)); |
| if ((fd = open (filename, O_RDONLY)) < 0) { |
| perrorx(filename); |
| } |
| |
| for (byte=0; byte<bytes; byte+=blksize) { |
| if (read (fd, buf, blksize) != blksize) |
| perrorx("read of file failed"); |
| } |
| close(fd); |
| } |
| exit(0); |
| } |
| |
| void |
| do_initfiles(void) |
| { |
| int i, fd, byte; |
| char *buf, filename[32]; |
| |
| buf = malloc(blksize); |
| bzero(buf, blksize); |
| |
| for (i=0; i<files; i++) { |
| sprintf(filename, "/tmp/tst.%d", i); |
| unlink(filename); |
| if ((fd = open (filename, O_RDWR|O_CREAT, 0644)) < 0) |
| perrorx(filename); |
| |
| for (byte=0; byte<bytes; byte+=blksize) { |
| if (write (fd, buf, blksize) != blksize) |
| perrorx("write of file failed"); |
| } |
| close(fd); |
| } |
| sync(); |
| } |
| |
| |