/*------------------------------------------------------------------------------------*/ char *helpstr[] = { "This test program is a generic template.", 0 }; #include #include #include #include #include #include #include #include #include #include #include #include //#include "setup.h" #define MAXCPUS 4096 #define perrorx(s) do { perror(s); exit(1);} while(0) #define mb() asm volatile("mfence":::"memory") #define barrier() asm volatile("": : :"memory") #define cpu_relax() asm volatile ("rep;nop":::"memory"); extern int optind, opterr; extern char *optarg; static int verbose = 0; static int header = 0; static char *file = "/proc/stat"; static int numtasks = 1; static int repeat = 1; static int bufsize = 1024; struct control_s { int ready; int done; int go; int exit; } *cntl; static cpu_set_t *defmask; static int cpu_set_size; static void runon_init(void) { if (!defmask) { cpu_set_size = CPU_ALLOC_SIZE(MAXCPUS); defmask = CPU_ALLOC(MAXCPUS); if (sched_getaffinity(0, cpu_set_size, defmask) < 0) perrorx("unexpected failure in runon_init"); } } static double timeInSeconds(long time_in_microseconds) { double temp; temp = time_in_microseconds; temp /= 1000000; return temp; } static int runon(int cpu) { cpu_set_t *mask; runon_init(); mask = CPU_ALLOC(MAXCPUS); if (cpu < 0 || cpu >= MAXCPUS) return -1; CPU_ZERO_S(cpu_set_size, mask); CPU_SET_S(cpu, cpu_set_size, mask); if (sched_setaffinity(0, cpu_set_size, mask) < 0) return -1; CPU_FREE(mask); return 0; } static long getCurrentTime() { struct timeval tp; long usec; mb(); gettimeofday(&tp, 0); usec = tp.tv_sec * 1000000 + tp.tv_usec; mb(); return usec; } static void do_help(void) { char **p; for (p = helpstr; *p; p++) printf("%s\n", *p); exit(0); } static void slave(int id) { FILE *f; int i; char *buf; runon(id); buf = malloc(bufsize); memset(buf, 0, bufsize); if ((f = fopen(file, "r")) < 0) perrorx("open failed"); while (fgets(buf, bufsize, f) != NULL) { } fclose(f); (void)__sync_fetch_and_add(&cntl->ready, 1); while (!cntl->go) cpu_relax(); for (i = 0; i < repeat; i++) { if ((f = fopen(file, "r")) < 0) perrorx("open failed"); while (fgets(buf, bufsize, f) != NULL) { } fclose(f); barrier(); } (void)__sync_fetch_and_add(&cntl->done, 1); while (!cntl->exit) cpu_relax(); exit(0); } int main(int argc, char **argv) { int i, c, stat, er = 0; static char optstr[] = "b:f:hn:r:v"; unsigned long t, tfork, tready, tread, texit; opterr = 1; while ((c = getopt(argc, argv, optstr)) != EOF) switch (c) { case 'b': bufsize = atoi(optarg); break; case 'f': file = optarg; break; case 'h': header++; break; case 'n': numtasks = atoi(optarg); break; case 'r': repeat = atoi(optarg); break; case 'v': verbose++; break; case '?': er = 1; break; } if (er) do_help(); runon(0); cntl = mmap(NULL, getpagesize(), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); tfork = getCurrentTime(); for (i = 0; i < numtasks; i++) if (fork() == 0) slave(i + 1); t = getCurrentTime(); tfork = t - tfork; tready = t; while (cntl->ready != numtasks) usleep(1000); t = getCurrentTime(); tready = t - tready; tread = t; cntl->go = 1; while (cntl->done != numtasks) cpu_relax(); t = getCurrentTime(); tread = t - tread; texit = t; cntl->exit = 1; while (wait(&stat) > 0) usleep(1000); texit = getCurrentTime() - texit; if (header) { printf("File: %s\n", file); printf("Bufsize: %d\n", bufsize); printf("Repeats: %d\n", repeat); printf("%6s%18s%18s%18s%18s%18s\n", "tasks", "fork-sec", "ready-sec", "read-sec", "read/repeat sec", "texit"); } printf("%6d%18.6f%18.6f%18.6f%18.6f%18.6f\n", numtasks, timeInSeconds(tfork), timeInSeconds(tready), timeInSeconds(tread), timeInSeconds(tread) / repeat, timeInSeconds(texit)); return 0; }