#define _GNU_SOURCE #include #include #include #include #include #include #include #include struct time_exit { volatile int ready __attribute__((aligned(64))); volatile int quit __attribute__((aligned(64))); }; #define cpu_relax() asm volatile ("rep;nop":::"memory"); #define MAXCPUS 4096 static int cpu_set_size; static cpu_set_t *task_affinity; static int delay; static void pin(int cpu) { cpu_set_t *affinity; if (cpu < 0 || cpu >= MAXCPUS) return; affinity = CPU_ALLOC(MAXCPUS); CPU_ZERO_S(cpu_set_size, affinity); CPU_SET_S(cpu, cpu_set_size, affinity); (void)sched_setaffinity(0, cpu_set_size, affinity); CPU_FREE(affinity); return; } static void child(struct time_exit *sharep, int cpu) { pin(cpu); __sync_fetch_and_add(&sharep->ready, 1); while (sharep->quit == 0) cpu_relax(); exit(0); } int main(int argc, char **argv) { int children, i; struct time_exit *sharep; struct timeval tv0, tv1; long secs, usecs; char opt; while ((opt = getopt(argc, argv, "p:")) != -1) { switch (opt) { case 'p': delay = atoi(optarg); break; default: fprintf(stderr, "Usage:\n"); } } argv += optind - 1; argc -= optind - 1; if (argc != 2) { printf("Wrong\n"); exit(-1); } children = atoi(argv[1]); cpu_set_size = CPU_ALLOC_SIZE(MAXCPUS); task_affinity = CPU_ALLOC(MAXCPUS); if (sched_getaffinity(0, cpu_set_size, task_affinity) < 0) { perror("Failed in sched_getaffinitt"); exit(-2); } sharep = mmap(0, sizeof(struct time_exit), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); for (i = 0; i < children; i++) if (fork() == 0) child(sharep, i); while (sharep->ready != children) cpu_relax(); if (delay) sleep(delay); gettimeofday(&tv0, NULL); sharep->quit = 1; while (wait(&i) > 0) cpu_relax(); gettimeofday(&tv1, NULL); usecs = tv1.tv_usec - tv0.tv_usec; secs = tv1.tv_sec - tv0.tv_sec; if (usecs < 0) { secs--; usecs += 1000000; } printf("%7ld.%06ld\n", secs, usecs); return 0; }