void initialize(iter_t iterations, void* cookie) { struct _state* pState = (struct _state*)cookie; if (iterations) return; if (socketpair(AF_UNIX, SOCK_STREAM, 0, pState->sv) == -1) { perror("socketpair"); } pState->buf = malloc(pState->msize); if (pState->buf == NULL) { fprintf(stderr, "buffer allocation\n"); exit(1); } handle_scheduler(benchmp_childid(), 0, 1); #ifdef CONFIG_NOMMU pState->pid = clone(unix_thread_function, thd_stack + STACK_SIZE - 4, CLONE_VM|SIGCHLD, pState); return; #else if (pState->pid = fork()) return; handle_scheduler(benchmp_childid(), 1, 1); /* Child sits and ping-pongs packets back to parent */ signal(SIGTERM, exit); while (read(pState->sv[0], pState->buf, pState->msize) == pState->msize) { write(pState->sv[0], pState->buf, pState->msize); } exit(0); #endif }
void initialize(iter_t iterations, void* cookie) { char c; state_t * state = (state_t *)cookie; if (iterations) return; state->semid = semget(IPC_PRIVATE, 2, IPC_CREAT | IPC_EXCL | 0600); semctl(state->semid, 0, SETVAL, 0); semctl(state->semid, 1, SETVAL, 0); handle_scheduler(benchmp_childid(), 0, 1); switch (state->pid = fork()) { case 0: signal(SIGTERM, exit); handle_scheduler(benchmp_childid(), 1, 1); writer(state->semid); return; case -1: perror("fork"); return; default: break; } }
void do_forkexec(iter_t iterations, void* cookie) { char *nav[2]; signal(SIGCHLD, SIG_DFL); handle_scheduler(benchmp_childid(), 0, 1); while (iterations-- > 0) { nav[0] = PROG; nav[1] = 0; switch (child_pid = fork()) { case -1: perror("fork"); exit(1); case 0: /* child */ handle_scheduler(benchmp_childid(), 1, 1); close(1); execve(PROG, nav, 0); exit(1); default: waitpid(child_pid, NULL,0); } child_pid = 0; } }
void initialize(iter_t iterations, void* cookie) { struct _state* state = (struct _state*)cookie; if (iterations) return; state->buf = valloc(XFERSIZE); touch(state->buf, XFERSIZE); state->initerr = 0; if (socketpair(AF_UNIX, SOCK_STREAM, 0, state->pipes) == -1) { perror("socketpair"); state->initerr = 1; return; } if (pipe(state->control) == -1) { perror("pipe"); state->initerr = 2; return; } handle_scheduler(benchmp_childid(), 0, 1); #ifdef CONFIG_NOMMU state->pid = clone(bw_unix_thread_function, thd_stack + STACK_SIZE - 4, CLONE_VM|SIGCHLD, state); #else switch (state->pid = fork()) { case 0: handle_scheduler(benchmp_childid(), 1, 1); close(state->control[1]); close(state->pipes[0]); writer(state->control[0], state->pipes[1], state->buf, state); return; /*NOTREACHED*/ case -1: perror("fork"); state->initerr = 3; return; /*NOTREACHED*/ default: break; } #endif close(state->control[0]); close(state->pipes[1]); }
void bench(register iter_t iterations, void *cookie) { int i; int status; state_t *state = (state_t *) cookie; state->pids = (pid_t*)malloc(state->jobs * sizeof(pid_t)); /* * This design has one buglet --- we cannot detect if the * worker process died prematurely. I.e., we don't have * a handshake step to collect "I finished correctly" * messages. */ while (iterations-- > 0) { for (i = 0; i < state->jobs; ++i) { #ifdef CONFIG_NOMMU if ((state->pids[i] = vfork()) == 0) { #else if ((state->pids[i] = fork()) == 0) { #endif handle_scheduler(benchmp_childid(), i+1, state->jobs); work(state->iterations, state); #ifdef CONFIG_NOMMU _exit(0); #else exit(0); #endif } } for (i = 0; i < state->jobs; ++i) { waitpid(state->pids[i], &status, 0); state->pids[i] = -1; /* child died badly */ if (!WIFEXITED(status)) { cleanup(0, cookie); exit(1); } } } } void cleanup(register iter_t iterations, void *cookie) { int i; state_t *state = (state_t *) cookie; for (i = 0; i < state->jobs; ++i) { if (state->pids[i] > 0) { kill(state->pids[i], SIGKILL); waitpid(state->pids[i], NULL, 0); state->pids[i] = -1; } } }
void initialize(iter_t iterations, void *cookie) { int pipes[2]; struct _state* state = (struct _state*)cookie; if (iterations) return; if (pipe(pipes) == -1) { perror("pipe"); exit(1); } handle_scheduler(benchmp_childid(), 0, 1); switch (state->pid = fork()) { case 0: close(pipes[0]); handle_scheduler(benchmp_childid(), 1, 1); state->buf = (char*)valloc(state->xfer); if (state->buf == NULL) { perror("child: no memory"); exit(2); } touch(state->buf, state->xfer); writer(pipes[1], state->buf, state->xfer); return; /*NOTREACHED*/ case -1: perror("fork"); exit(3); /*NOTREACHED*/ default: break; } close(pipes[1]); state->readfd = pipes[0]; state->buf = (char*)valloc(state->xfer + getpagesize()); if (state->buf == NULL) { perror("parent: no memory"); exit(4); } touch(state->buf, state->xfer + getpagesize()); state->buf += 128; /* destroy page alignment */ }
int main(int ac, char **av) { int i, prog; #ifdef sgi int ncpus = sysmp(MP_NPROCS); #endif for (i = 1; i < ac; ++i) { if (av[i][0] != '-') { break; } switch (av[i][1]) { case 'D': Dflg = 1; break; /* Allow directories */ case 'd': dflg = 1; break; /* debugging */ case 'f': fflg = atoi(&av[i][2]); break; /* # of threads */ case 'l': lflg = 1; break; /* logging */ case 'n': nflg = 1; break; /* fake file i/o */ case 'z': zflg = 1; break; /* all files are 0 size */ default: fprintf(stderr, "Barf.\n"); exit(1); } } if (getenv("DOCROOT")) { if (chdir(getenv("DOCROOT")) == -1) { perror(getenv("DOCROOT")); exit(1); } } if (atoi(av[ac - 1]) != 0) { prog = -atoi(av[ac - 1]); } else { prog = -80; } /* * Steve - why is this here? */ signal(SIGPIPE, SIG_IGN); data = tcp_server(prog, SOCKOPT_REUSE); bufs[0] = valloc(XFERSIZE); bufs[1] = valloc(XFERSIZE); bufs[2] = valloc(XFERSIZE); logfile = open(LOGFILE, O_CREAT|O_APPEND|O_WRONLY, 0666); signal(SIGINT, die); signal(SIGHUP, die); signal(SIGTERM, die); for (i = 1; i < fflg; ++i) { if (fork() <= 0) { break; } } handle_scheduler(i, 0, 0); worker(); return(0); }
void do_procedure(iter_t iterations, void* cookie) { int r = *(int *) cookie; handle_scheduler(benchmp_childid(), 0, 1); while (iterations-- > 0) { use_int(r); } }
void initialize(iter_t iterations, void* cookie) { char c; state_t * state = (state_t *)cookie; if (iterations) return; if (pipe(state->p1) == -1) { perror("pipe"); exit(1); } if (pipe(state->p2) == -1) { perror("pipe"); exit(1); } handle_scheduler(benchmp_childid(), 0, 1); switch (state->pid = fork()) { case 0: handle_scheduler(benchmp_childid(), 1, 1); signal(SIGTERM, exit); close(state->p1[1]); close(state->p2[0]); writer(state->p2[1], state->p1[0]); return; case -1: perror("fork"); return; default: close(state->p1[0]); close(state->p2[1]); break; } /* * One time around to make sure both processes are started. */ if (write(state->p1[1], &c, 1) != 1 || read(state->p2[0], &c, 1) != 1){ perror("(i) read/write on pipe"); exit(1); } }
int bw_unix_thread_function(void *t) { struct _state* state = (struct _state*)t; handle_scheduler(benchmp_childid(), 1, 1); close(state->control[1]); close(state->pipes[0]); writer(state->control[0], state->pipes[1], state->buf, state); return 0; }
int create_daemons(int **p, pid_t *pids, int procs, int process_size) { int i, j; int msg; /* * Use the pipes as a ring, and fork off a bunch of processes * to pass the byte through their part of the ring. * * Do the sum in each process and get that time before moving on. */ handle_scheduler(benchmp_childid(), 0, procs-1); for (i = 1; i < procs; ++i) { switch (pids[i] = fork()) { case -1: /* could not fork, out of processes? */ return i; case 0: /* child */ handle_scheduler(benchmp_childid(), i, procs-1); for (j = 0; j < procs; ++j) { if (j != i - 1) close(p[j][0]); if (j != i) close(p[j][1]); } doit(p[i-1][0], p[i][1], process_size); /* NOTREACHED */ default: /* parent */ ; } } /* * Go once around the loop to make sure that everyone is ready and * to get the token in the pipeline. */ if (write(p[0][1], &msg, sizeof(msg)) != sizeof(msg) || read(p[procs-1][0], &msg, sizeof(msg)) != sizeof(msg)) { /* perror("write/read/write on pipe"); */ exit(1); } return procs; }
void initialize(iter_t iterations, void* cookie) { struct _state* state = (struct _state*)cookie; if (iterations) return; state->buf = valloc(XFERSIZE); touch(state->buf, XFERSIZE); state->initerr = 0; if (socketpair(AF_UNIX, SOCK_STREAM, 0, state->pipes) == -1) { perror("socketpair"); state->initerr = 1; return; } if (pipe(state->control) == -1) { perror("pipe"); state->initerr = 2; return; } handle_scheduler(benchmp_childid(), 0, 1); switch (state->pid = fork()) { case 0: handle_scheduler(benchmp_childid(), 1, 1); close(state->control[1]); close(state->pipes[0]); writer(state->control[0], state->pipes[1], state->buf, state); return; /*NOTREACHED*/ case -1: perror("fork"); state->initerr = 3; return; /*NOTREACHED*/ default: break; } close(state->control[0]); close(state->pipes[1]); }
void do_fork(iter_t iterations, void* cookie) { signal(SIGCHLD, SIG_DFL); handle_scheduler(benchmp_childid(), 0, 1); while (iterations-- > 0) { switch (child_pid = fork()) { case -1: perror("fork"); exit(1); case 0: /* child */ handle_scheduler(benchmp_childid(), 1, 1); exit(1); default: waitpid(child_pid, NULL,0); } child_pid = 0; } }
int unix_thread_function(void *t) { struct _state* pState = (struct _state*)t; handle_scheduler(benchmp_childid(), 1, 1); /* Child sits and ping-pongs packets back to parent */ signal(SIGTERM, exit); while (read(pState->sv[0], pState->buf, pState->msize) == pState->msize) { write(pState->sv[0], pState->buf, pState->msize); } return 0; }
void setup(iter_t iterations, void* cookie) { state_t *state = (state_t *) cookie; if (iterations) return; state->x = (long*)malloc(sizeof(long*)); *(long**)state->x = state->x; state->p = (long**)state->x; handle_scheduler(benchmp_childid(), 0, state->jobs); }
int main(int ac, char **av) { state_t state; int rc, c, repetitions = -1, warmup = 0; char buf[256]; char *usage = "-s\n OR [-S] [-W <warmup>] [-N <repetitions>] server\n"; while (( c = getopt(ac, av, "sSP:W:N:")) != EOF) { switch(c) { case 's': /* Server */ if (fork() == 0) { server_main(); } exit(0); case 'S': /* shutdown serverhost */ { int sock = tcp_connect(av[optind], TCP_CONNECT, SOCKOPT_NONE); rc = write(sock, "0", 1); if (rc < 0) DIE_PERROR("write failed"); close(sock); exit(0); } case 'W': warmup = atoi(optarg); break; case 'N': repetitions = atoi(optarg); break; default: lmbench_usage(ac, av, usage); break; } } if (optind + 1 != ac) { lmbench_usage(ac, av, usage); } handle_scheduler(benchmp_childid(), 0, 0); state.server = av[optind]; benchmp(NULL, doclient, NULL, 0, 1, warmup, repetitions, &state); sprintf(buf, "TCP/IP connection cost to %s", state.server); micro(buf, get_n()); exit(0); }
void bench(register iter_t iterations, void *cookie) { int i; int status; state_t *state = (state_t *) cookie; state->pids = (pid_t*)malloc(state->jobs * sizeof(pid_t)); if (!state->pids) { perror("malloc"); exit(2); } /* * This design has one buglet --- we cannot detect if the * worker process died prematurely. I.e., we don't have * a handshake step to collect "I finished correctly" * messages. */ while (iterations-- > 0) { for (i = 0; i < state->jobs; ++i) { if ((state->pids[i] = fork()) == 0) { handle_scheduler(benchmp_childid(), i+1, state->jobs); work(state->iterations, state); exit(0); } } for (i = 0; i < state->jobs; ++i) { waitpid(state->pids[i], &status, 0); state->pids[i] = -1; /* child died badly */ if (!WIFEXITED(status)) { cleanup(0, cookie); exit(1); } } } }
int main(int ac, char **av) { state_t state; int parallel = 1; int warmup = 0; int repetitions = -1; int c; char* usage = "[-n <#descriptors>] [-P <parallelism>] [-W <warmup>] [-N <repetitions>] file|tcp\n"; char buf[256]; morefds(); /* bump fd_cur to fd_max */ state.num = 200; while (( c = getopt(ac, av, "P:W:N:n:")) != EOF) { switch(c) { case 'P': parallel = atoi(optarg); if (parallel <= 0) lmbench_usage(ac, av, usage); break; case 'W': warmup = atoi(optarg); break; case 'N': repetitions = atoi(optarg); break; case 'n': state.num = bytes(optarg); break; default: lmbench_usage(ac, av, usage); break; } } if (optind + 1 != ac) { lmbench_usage(ac, av, usage); } handle_scheduler(benchmp_childid(), 0, 0); if (streq("tcp", av[optind])) { state.fid_f = open_socket; server(&state); benchmp(initialize, doit, cleanup, 0, parallel, warmup, repetitions, &state); sprintf(buf, "Select on %d tcp fd's", state.num); kill(state.pid, SIGKILL); waitpid(state.pid, NULL, 0); micro(buf, get_n()); } else if (streq("file", av[optind])) { state.fid_f = open_file; server(&state); benchmp(initialize, doit, cleanup, 0, parallel, warmup, repetitions, &state); unlink(state.fname); sprintf(buf, "Select on %d fd's", state.num); micro(buf, get_n()); } else { lmbench_usage(ac, av, usage); } exit(0); }
void benchmp(benchmp_f initialize, benchmp_f benchmark, benchmp_f cleanup, int enough, int parallel, int warmup, int repetitions, void* cookie) { iter_t iterations = 1; long i; pid_t *pids = NULL; int response[2]; int start_signal[2]; int result_signal[2]; int exit_signal[2]; #ifdef _DEBUG fprintf(stderr, "benchmp(%p, %p, %p, %d, %d, %d, %d, %p): entering\n", initialize, benchmark, cleanup, enough, parallel, warmup, repetitions, cookie); #endif enough = get_enough(enough); #ifdef _DEBUG fprintf(stderr, "\tenough=%d\n", enough); #endif if (repetitions < 0) repetitions = (1 < parallel || 1000000 <= enough ? 1 : TRIES); /* initialize results */ settime(0); save_n(1); if (parallel > 1) { /* Compute the baseline performance */ benchmp(initialize, benchmark, cleanup, enough, 1, warmup, repetitions, cookie); /* if we can't even do a single job, then give up */ if (gettime() == 0) return; /* calculate iterations for 1sec runtime */ iterations = get_n(); if (enough < SHORT) { double tmp = (double)SHORT * (double)get_n(); tmp /= (double)gettime(); iterations = (iter_t)tmp + 1; } settime(0); save_n(1); } /* Create the necessary pipes for control */ if (pipe(response) < 0 || pipe(start_signal) < 0 || pipe(result_signal) < 0 || pipe(exit_signal) < 0) { #ifdef _DEBUG fprintf(stderr, "BENCHMP: Could not create control pipes\n"); #endif /* _DEBUG */ return; } /* fork the necessary children */ benchmp_sigchld_received = 0; benchmp_sigterm_received = 0; benchmp_sigterm_handler = signal(SIGTERM, benchmp_sigterm); benchmp_sigchld_handler = signal(SIGCHLD, benchmp_sigchld); pids = (pid_t*)malloc(parallel * sizeof(pid_t)); if (!pids) return; bzero((void*)pids, parallel * sizeof(pid_t)); for (i = 0; i < parallel; ++i) { if (benchmp_sigterm_received) goto error_exit; #ifdef _DEBUG fprintf(stderr, "benchmp(%p, %p, %p, %d, %d, %d, %d, %p): creating child %d\n", initialize, benchmark, cleanup, enough, parallel, warmup, repetitions, cookie, i); #endif switch(pids[i] = fork()) { case -1: /* could not open enough children! */ #ifdef _DEBUG fprintf(stderr, "BENCHMP: fork() failed!\n"); #endif /* _DEBUG */ goto error_exit; case 0: /* If child */ close(response[0]); close(start_signal[1]); close(result_signal[1]); close(exit_signal[1]); handle_scheduler(i, 0, 0); benchmp_child(initialize, benchmark, cleanup, i, response[1], start_signal[0], result_signal[0], exit_signal[0], enough, iterations, parallel, repetitions, cookie ); exit(0); default: break; } } close(response[1]); close(start_signal[0]); close(result_signal[0]); close(exit_signal[0]); benchmp_parent(response[0], start_signal[1], result_signal[1], exit_signal[1], pids, parallel, iterations, warmup, repetitions, enough ); goto cleanup_exit; error_exit: /* give the children a chance to clean up gracefully */ signal(SIGCHLD, SIG_DFL); while (--i >= 0) { kill(pids[i], SIGTERM); waitpid(pids[i], NULL, 0); } cleanup_exit: /* * Clean up and kill all children * * NOTE: the children themselves SHOULD exit, and * Killing them could prevent them from * cleanup up subprocesses, etc... So, we only * want to kill child processes when it appears * that they will not die of their own accord. * We wait twice the timing interval plus two seconds * for children to die. If they haven't died by * that time, then we start killing them. */ benchmp_sigalrm_timeout = (int)((2 * enough)/1000000) + 2; if (benchmp_sigalrm_timeout < 5) benchmp_sigalrm_timeout = 5; signal(SIGCHLD, SIG_DFL); while (i-- > 0) { /* wait timeout seconds for child to die, then kill it */ benchmp_sigalrm_pid = pids[i]; benchmp_sigalrm_handler = signal(SIGALRM, benchmp_sigalrm); alarm(benchmp_sigalrm_timeout); waitpid(pids[i], NULL, 0); alarm(0); signal(SIGALRM, benchmp_sigalrm_handler); } if (pids) free(pids); #ifdef _DEBUG fprintf(stderr, "benchmp(0x%x, 0x%x, 0x%x, %d, %d, 0x%x): exiting\n", (unsigned int)initialize, (unsigned int)benchmark, (unsigned int)cleanup, enough, parallel, (unsigned int)cookie); #endif }
int main(int ac, char **av) { int c; int warmup = 0; int repetitions = (1000000 <= get_enough(0) ? 1 : TRIES); double par; struct _state state; char *usage = "[-W <warmup>] [-N <repetitions>]\n"; state.N = 1; state.M = 1000; state.K = -1023; while (( c = getopt(ac, av, "W:N:")) != EOF) { switch(c) { case 'W': warmup = atoi(optarg); break; case 'N': repetitions = atoi(optarg); break; default: lmbench_usage(ac, av, usage); break; } } handle_scheduler(benchmp_childid(), 0, 0); par = max_parallelism(integer_bit_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "integer bit parallelism: %.2f\n", par); par = max_parallelism(integer_add_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "integer add parallelism: %.2f\n", par); par = max_parallelism(integer_mul_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "integer mul parallelism: %.2f\n", par); par = max_parallelism(integer_div_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "integer div parallelism: %.2f\n", par); par = max_parallelism(integer_mod_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "integer mod parallelism: %.2f\n", par); par = max_parallelism(int64_bit_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "int64 bit parallelism: %.2f\n", par); par = max_parallelism(int64_add_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "int64 add parallelism: %.2f\n", par); par = max_parallelism(int64_mul_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "int64 mul parallelism: %.2f\n", par); par = max_parallelism(int64_div_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "int64 div parallelism: %.2f\n", par); par = max_parallelism(int64_mod_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "int64 mod parallelism: %.2f\n", par); par = max_parallelism(float_add_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "float add parallelism: %.2f\n", par); par = max_parallelism(float_mul_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "float mul parallelism: %.2f\n", par); par = max_parallelism(float_div_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "float div parallelism: %.2f\n", par); par = max_parallelism(double_add_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "double add parallelism: %.2f\n", par); par = max_parallelism(double_mul_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "double mul parallelism: %.2f\n", par); par = max_parallelism(double_div_benchmarks, warmup, repetitions, &state); if (par > 0.) fprintf(stderr, "double div parallelism: %.2f\n", par); return(0); }
void initialize(iter_t iterations, void* cookie) { char c; state_t * state = (state_t *)cookie; struct mq_attr attr; if (iterations) return; memset(&attr, 0, sizeof(attr)); attr.mq_flags = 0; attr.mq_maxmsg = 1; attr.mq_msgsize = 1; attr.mq_curmsgs = 0; state->mq = mq_open("/testqueue", O_CREAT | O_RDWR, 0666, &attr); if (state->mq == -1) { perror("mq_open"); return; } fprintf(stderr, "mq fd: %d\n", state->mq); mq_getattr(state->mq, &attr); fprintf(stderr, "attrs\n"); fprintf(stderr, "flags: 0x%x\n", attr.mq_flags); fprintf(stderr, "maxmsg: %ld\n", attr.mq_maxmsg); fprintf(stderr, "msgsize: %ld\n", attr.mq_msgsize); fprintf(stderr, "curmsg: %ld\n", attr.mq_curmsgs); attr.mq_msgsize = 1; attr.mq_maxmsg = 1; if (mq_setattr(state->mq, &attr, NULL) == -1) { perror("mq_setattr"); return; } mq_getattr(state->mq, &attr); fprintf(stderr, "attrs\n"); fprintf(stderr, "flags: 0x%x\n", attr.mq_flags); fprintf(stderr, "maxmsg: %ld\n", attr.mq_maxmsg); fprintf(stderr, "msgsize: %ld\n", attr.mq_msgsize); fprintf(stderr, "curmsg: %ld\n", attr.mq_curmsgs); handle_scheduler(benchmp_childid(), 0, 1); switch (state->pid = fork()) { case 0: handle_scheduler(benchmp_childid(), 1, 1); signal(SIGTERM, exit); childloop(state->mq); return; case -1: perror("fork"); return; default: break; } /* * One time around to make sure both processes are started. */ #if 1 { int snd = 0; int rcv = 0; snd = mq_send(state->mq, &c, 1, 0); rcv = mq_receive(state->mq, buf, sizeof(buf), NULL); fprintf(stderr, "snd: %d rcv: %d\n", snd, rcv); /* if (mq_send(state->mq, &c, 1, 0) != -1 || mq_receive(state->mq, buf, sizeof(buf), NULL) != 1){ perror("(i) read/write on mq"); exit(1); } */ } #endif }