--- /dev/null
+/*
+ * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+/*
+ * 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();
+}
+
+
--- /dev/null
+#!/bin/sh
+#
+# Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA 94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+help() {
+cat <<END
+Measure scaling of multiple cpus readin the same set of files.
+(NASA testcase).
+ Usage: $0 [-b <bytes>] [-f <files>] [-s] [-B] [-v] cpus ...
+ or
+ $0 -i [-b <bytes>] [-f <files>]
+
+ -b file size in bytes
+ -f number of files
+ -s keep processes synchronized when reading files
+ -B use bcfree to free buffer cache pages before each run
+END
+exit 1
+}
+
+err () {
+ echo "ERROR - $*"
+ exit 1
+}
+
+BYTES=8192
+FILES=10
+SYNC=""
+VERBOSE=""
+STRIDED=""
+BCFREE=0
+INIT=0
+OPTS="f:b:vsiSBH"
+while getopts "$OPTS" c ; do
+ case $c in
+ H) help;;
+ f) FILES=${OPTARG};;
+ b) BYTES=${OPTARG};;
+ i) INIT=1;;
+ B) BCFREE=1;;
+ S) STRIDED="-S";;
+ s) SYNC="-s";;
+ v) VERBOSE="-v";;
+ \?) help;;
+ esac
+
+done
+shift `expr $OPTIND - 1`
+
+if [ $INIT -gt 0 ] ; then
+ echo "Initializing $BYTES bytes, $FILES files"
+ ./scaleread $VERBOSE -i -b $BYTES -f $FILES
+ sync
+else
+ [ $# -gt 0 ] || help
+ echo "Testing $BYTES bytes, $FILES files"
+ for CPUS in $* ; do
+ [ $BCFREE -eq 0 ] || bcfree -a
+ /usr/bin/time -f "$CPUS: %e wall, %S sys, %U user" ./scaleread \
+ $SYNC $STRIDED $VERBOSE -b $BYTES -f $FILES -c $CPUS
+ done
+fi
+