/* * lat_proc.c - process creation tests * * Usage: lat_proc [-P ] [-N ] procedure|fork|exec|shell * * TODO - linux clone, plan9 rfork, IRIX sproc(). * * Copyright (c) 1994 Larry McVoy. Distributed under the FSF GPL with * additional restriction that results may published only if * (1) the benchmark is unmodified, and * (2) the version in the sccsid below is included in the report. * Support for this development by Sun Microsystems is gratefully acknowledged. */ char *id = "$Id$\n"; #include "bench.h" #ifdef STATIC #define PROG "/tmp/hello-s" #define STATIC_PREFIX "Static " #else #define PROG "/tmp/hello" #define STATIC_PREFIX "" #endif void do_shell(iter_t iterations, void* cookie); void do_forkexec(iter_t iterations,void* cookie); void do_fork(iter_t iterations, void* cookie); void do_procedure(iter_t iterations, void* cookie); pid_t child_pid; void cleanup(iter_t iterations, void* cookie) { if (iterations) return; if (child_pid) { kill(child_pid, SIGKILL); waitpid(child_pid, NULL, 0); child_pid = 0; } } int main(int ac, char **av) { int parallel = 1; int warmup = 0; int repetitions = -1; int c; char* usage = "[-P ] [-W ] [-N ] procedure|fork|exec|shell\n"; while (( c = getopt(ac, av, "P:W: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; default: lmbench_usage(ac, av, usage); break; } } if (optind + 1 != ac) { /* should have one argument left */ lmbench_usage(ac, av, usage); } if (!strcmp("procedure", av[optind])) { benchmp(NULL, do_procedure, cleanup, 0, parallel, warmup, repetitions, &ac); micro("Procedure call", get_n()); } else if (!strcmp("fork", av[optind])) { benchmp(NULL, do_fork, cleanup, 0, parallel, warmup, repetitions, NULL); micro(STATIC_PREFIX "Process fork+exit", get_n()); } else if (!strcmp("exec", av[optind])) { benchmp(NULL, do_forkexec, cleanup, 0, parallel, warmup, repetitions, NULL); micro(STATIC_PREFIX "Process fork+execve", get_n()); } else if (!strcmp("shell", av[optind])) { benchmp(NULL, do_shell, cleanup, 0, parallel, warmup, repetitions, NULL); micro(STATIC_PREFIX "Process fork+/bin/sh -c", get_n()); } else { lmbench_usage(ac, av, usage); } return(0); } void do_shell(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); close(1); execlp("/bin/sh", "sh", "-c", PROG, 0); exit(1); default: waitpid(child_pid, NULL,0); } child_pid = 0; } } 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 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; } } void do_procedure(iter_t iterations, void* cookie) { int r = *(int *) cookie; handle_scheduler(benchmp_childid(), 0, 1); while (iterations-- > 0) { use_int(r); } }