Home | History | Annotate | Download | only in common
      1  5184  ek110237 /*
      2  5184  ek110237  * CDDL HEADER START
      3  5184  ek110237  *
      4  5184  ek110237  * The contents of this file are subject to the terms of the
      5  5184  ek110237  * Common Development and Distribution License (the "License").
      6  5184  ek110237  * You may not use this file except in compliance with the License.
      7  5184  ek110237  *
      8  5184  ek110237  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  5184  ek110237  * or http://www.opensolaris.org/os/licensing.
     10  5184  ek110237  * See the License for the specific language governing permissions
     11  5184  ek110237  * and limitations under the License.
     12  5184  ek110237  *
     13  5184  ek110237  * When distributing Covered Code, include this CDDL HEADER in each
     14  5184  ek110237  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  5184  ek110237  * If applicable, add the following below this CDDL HEADER, with the
     16  5184  ek110237  * fields enclosed by brackets "[]" replaced with your own identifying
     17  5184  ek110237  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  5184  ek110237  *
     19  5184  ek110237  * CDDL HEADER END
     20  5184  ek110237  */
     21  5184  ek110237 /*
     22  8615    Andrew  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  5184  ek110237  * Use is subject to license terms.
     24  6613  ek110237  *
     25  6613  ek110237  * Portions Copyright 2008 Denis Cheng
     26  5184  ek110237  */
     27  5184  ek110237 
     28  5184  ek110237 #include <signal.h>
     29  5184  ek110237 #include <fcntl.h>
     30  5184  ek110237 #include <sys/stat.h>
     31  5184  ek110237 #include <sys/wait.h>
     32  5184  ek110237 
     33  6613  ek110237 #include "filebench.h"
     34  5184  ek110237 #include "procflow.h"
     35  5184  ek110237 #include "flowop.h"
     36  5184  ek110237 #include "ipc.h"
     37  5184  ek110237 
     38  6084  aw148015 /* pid and procflow pointer for this process */
     39  6084  aw148015 pid_t my_pid;
     40  6084  aw148015 procflow_t *my_procflow = NULL;
     41  5184  ek110237 
     42  5184  ek110237 static procflow_t *procflow_define_common(procflow_t **list, char *name,
     43  5184  ek110237     procflow_t *inherit, int instance);
     44  8762    Andrew static void procflow_sleep(procflow_t *procflow, int wait_cnt);
     45  5184  ek110237 
     46  5184  ek110237 #ifdef USE_PROCESS_MODEL
     47  5184  ek110237 
     48  5184  ek110237 static enum create_n_wait {
     49  5184  ek110237 	CNW_DONE,
     50  5184  ek110237 	CNW_ERROR
     51  5184  ek110237 } cnw_wait;
     52  5184  ek110237 
     53  5184  ek110237 #endif	/* USE_PROCESS_MODEL */
     54  5184  ek110237 
     55  5184  ek110237 
     56  5184  ek110237 /*
     57  5184  ek110237  * Procflows are filebench entities which manage processes. Each
     58  5184  ek110237  * worker procflow spawns a separate filebench process, with attributes
     59  5184  ek110237  * inherited from a FLOW_MASTER procflow created during f model language
     60  5184  ek110237  * parsing. This section contains routines to define, create, control,
     61  5184  ek110237  * and delete procflows.
     62  5184  ek110237  *
     63  5184  ek110237  * Each process defined in the f model creates a FLOW_MASTER
     64  5184  ek110237  * procflow which encapsulates the defined attributes, and threads of
     65  5184  ek110237  * the f process, including the number of instances to create. At
     66  5184  ek110237  * runtime, a worker procflow instance with an associated filebench
     67  5184  ek110237  * process is created, which runs until told to quite by the original
     68  5184  ek110237  * filebench process or is specifically deleted.
     69  5184  ek110237  */
     70  5184  ek110237 
     71  5184  ek110237 
     72  5184  ek110237 /*
     73  5184  ek110237  * Prints a summary of the syntax for setting procflow parameters.
     74  5184  ek110237  */
     75  5184  ek110237 void
     76  5184  ek110237 procflow_usage(void)
     77  5184  ek110237 {
     78  5184  ek110237 	(void) fprintf(stderr,
     79  5184  ek110237 	    "define process name=<name>[,instances=<count>]\n");
     80  5184  ek110237 	(void) fprintf(stderr, "{\n");
     81  5184  ek110237 	(void) fprintf(stderr, "  thread ...\n");
     82  5184  ek110237 	(void) fprintf(stderr, "  thread ...\n");
     83  5184  ek110237 	(void) fprintf(stderr, "  thread ...\n");
     84  5184  ek110237 	(void) fprintf(stderr, "}\n");
     85  5184  ek110237 	(void) fprintf(stderr, "\n");
     86  5184  ek110237 	(void) fprintf(stderr, "\n");
     87  5184  ek110237 }
     88  5184  ek110237 
     89  5184  ek110237 /*
     90  5184  ek110237  * If filebench has been compiled to support multiple processes
     91  5184  ek110237  * (USE_PROCESS_MODEL defined), this routine forks a child
     92  5184  ek110237  * process and uses either system() or exec() to start up a new
     93  5184  ek110237  * instance of filebench, passing it the procflow name, instance
     94  5184  ek110237  * number and shared memory region address.
     95  5184  ek110237  * If USE_PROCESS_MODEL is NOT defined, then the routine
     96  5184  ek110237  * just creates a child thread which begins executing
     97  5184  ek110237  * threadflow_init() for the specified procflow.
     98  5184  ek110237  */
     99  5184  ek110237 static int
    100  5184  ek110237 procflow_createproc(procflow_t *procflow)
    101  5184  ek110237 {
    102  5184  ek110237 	char instance[128];
    103  5184  ek110237 	char shmaddr[128];
    104  5184  ek110237 	char procname[128];
    105  5184  ek110237 	pid_t pid;
    106  5184  ek110237 
    107  5184  ek110237 #ifdef USE_PROCESS_MODEL
    108  5184  ek110237 
    109  5184  ek110237 	(void) snprintf(instance, sizeof (instance), "%d",
    110  5184  ek110237 	    procflow->pf_instance);
    111  5184  ek110237 	(void) snprintf(procname, sizeof (procname), "%s", procflow->pf_name);
    112  5184  ek110237 #if defined(_LP64) || (__WORDSIZE == 64)
    113  5184  ek110237 	(void) snprintf(shmaddr, sizeof (shmaddr), "%llx", filebench_shm);
    114  5184  ek110237 #else
    115  5184  ek110237 	(void) snprintf(shmaddr, sizeof (shmaddr), "%x", filebench_shm);
    116  5184  ek110237 #endif
    117  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "creating process %s",
    118  5184  ek110237 	    procflow->pf_name);
    119  5184  ek110237 
    120  5184  ek110237 	procflow->pf_running = 0;
    121  5184  ek110237 
    122  5184  ek110237 #ifdef HAVE_FORK1
    123  5184  ek110237 	if ((pid = fork1()) < 0) {
    124  5184  ek110237 		filebench_log(LOG_ERROR,
    125  5184  ek110237 		    "procflow_createproc fork failed: %s",
    126  5184  ek110237 		    strerror(errno));
    127  5184  ek110237 		return (-1);
    128  5184  ek110237 	}
    129  5184  ek110237 #else
    130  5184  ek110237 	if ((pid = fork()) < 0) {
    131  5184  ek110237 		filebench_log(LOG_ERROR,
    132  5184  ek110237 		    "procflow_createproc fork failed: %s",
    133  5184  ek110237 		    strerror(errno));
    134  5184  ek110237 		return (-1);
    135  5184  ek110237 	}
    136  5184  ek110237 #endif /* HAVE_FORK1 */
    137  5184  ek110237 
    138  6084  aw148015 	/* if child, start up new copy of filebench */
    139  5184  ek110237 	if (pid == 0) {
    140  5184  ek110237 #ifdef USE_SYSTEM
    141  5184  ek110237 		char syscmd[1024];
    142  5184  ek110237 #endif
    143  5184  ek110237 
    144  5184  ek110237 		(void) sigignore(SIGINT);
    145  5184  ek110237 		filebench_log(LOG_DEBUG_SCRIPT,
    146  5184  ek110237 		    "Starting %s-%d", procflow->pf_name,
    147  5184  ek110237 		    procflow->pf_instance);
    148  5184  ek110237 		/* Child */
    149  5184  ek110237 
    150  5184  ek110237 #ifdef USE_SYSTEM
    151  5184  ek110237 		(void) snprintf(syscmd, sizeof (syscmd), "%s -a %s -i %s -s %s",
    152  5184  ek110237 		    execname,
    153  5184  ek110237 		    procname,
    154  5184  ek110237 		    instance,
    155  5184  ek110237 		    shmaddr);
    156  5184  ek110237 		if (system(syscmd) < 0) {
    157  5184  ek110237 			filebench_log(LOG_ERROR,
    158  5184  ek110237 			    "procflow exec proc failed: %s",
    159  5184  ek110237 			    strerror(errno));
    160  5184  ek110237 			filebench_shutdown(1);
    161  5184  ek110237 		}
    162  5184  ek110237 
    163  5184  ek110237 #else
    164  6613  ek110237 		if (execlp(execname, procname, "-a", procname, "-i",
    165  5184  ek110237 		    instance, "-s", shmaddr, "-m", shmpath, NULL) < 0) {
    166  5184  ek110237 			filebench_log(LOG_ERROR,
    167  5184  ek110237 			    "procflow exec proc failed: %s",
    168  5184  ek110237 			    strerror(errno));
    169  5184  ek110237 			filebench_shutdown(1);
    170  5184  ek110237 		}
    171  5184  ek110237 #endif
    172  5184  ek110237 		exit(1);
    173  5184  ek110237 	} else {
    174  6084  aw148015 		/* if parent, save pid and return */
    175  5184  ek110237 		procflow->pf_pid = pid;
    176  5184  ek110237 	}
    177  5184  ek110237 #else
    178  5184  ek110237 	procflow->pf_running = 1;
    179  5184  ek110237 	if (pthread_create(&procflow->pf_tid, NULL,
    180  5184  ek110237 	    (void *(*)(void*))threadflow_init, procflow) != 0) {
    181  5184  ek110237 		filebench_log(LOG_ERROR, "proc-thread create failed");
    182  5184  ek110237 		procflow->pf_running = 0;
    183  5184  ek110237 	}
    184  5184  ek110237 #endif
    185  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "procflow_createproc created pid %d",
    186  5184  ek110237 	    pid);
    187  5184  ek110237 
    188  5184  ek110237 	return (0);
    189  5184  ek110237 }
    190  5184  ek110237 
    191  5184  ek110237 /*
    192  5184  ek110237  * Find a procflow of name "name" and instance "instance" on the
    193  6391  aw148015  * master procflow list, filebench_shm->shm_proclist. Locks the list
    194  5184  ek110237  * and scans through it searching for a procflow with matching
    195  5184  ek110237  * name and instance number. If found returns a pointer to the
    196  5184  ek110237  * procflow, otherwise returns NULL.
    197  5184  ek110237  */
    198  5184  ek110237 static procflow_t *
    199  5184  ek110237 procflow_find(char *name, int instance)
    200  5184  ek110237 {
    201  6391  aw148015 	procflow_t *procflow = filebench_shm->shm_proclist;
    202  5184  ek110237 
    203  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "Find: (%s-%d) proclist = %zx",
    204  5184  ek110237 	    name, instance, procflow);
    205  5184  ek110237 
    206  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    207  5184  ek110237 
    208  5184  ek110237 	while (procflow) {
    209  5184  ek110237 		filebench_log(LOG_DEBUG_IMPL, "Find: (%s-%d) == (%s-%d)",
    210  5184  ek110237 		    name, instance,
    211  5184  ek110237 		    procflow->pf_name,
    212  5184  ek110237 		    procflow->pf_instance);
    213  5184  ek110237 		if ((strcmp(name, procflow->pf_name) == 0) &&
    214  5184  ek110237 		    (instance == procflow->pf_instance)) {
    215  5184  ek110237 
    216  6391  aw148015 			(void) ipc_mutex_unlock(
    217  6391  aw148015 			    &filebench_shm->shm_procflow_lock);
    218  5184  ek110237 
    219  5184  ek110237 			return (procflow);
    220  5184  ek110237 		}
    221  5184  ek110237 		procflow = procflow->pf_next;
    222  5184  ek110237 	}
    223  5184  ek110237 
    224  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    225  5184  ek110237 
    226  5184  ek110237 	return (NULL);
    227  5184  ek110237 }
    228  5184  ek110237 
    229  5184  ek110237 static int
    230  5184  ek110237 procflow_create_all_procs(void)
    231  5184  ek110237 {
    232  6391  aw148015 	procflow_t *procflow = filebench_shm->shm_proclist;
    233  5184  ek110237 	int	ret = 0;
    234  5184  ek110237 
    235  5184  ek110237 	while (procflow) {
    236  6212  aw148015 		int i, instances;
    237  5184  ek110237 
    238  6212  aw148015 		instances = (int)avd_get_int(procflow->pf_instances);
    239  6212  aw148015 		filebench_log(LOG_INFO, "Starting %d %s instances",
    240  6212  aw148015 		    instances, procflow->pf_name);
    241  5184  ek110237 
    242  5184  ek110237 		/* Create instances of procflow */
    243  6212  aw148015 		for (i = 0; (i < instances) && (ret == 0); i++) {
    244  5184  ek110237 			procflow_t *newproc;
    245  5184  ek110237 
    246  5184  ek110237 			/* Create processes */
    247  5184  ek110237 			newproc =
    248  6391  aw148015 			    procflow_define_common(&filebench_shm->shm_proclist,
    249  5184  ek110237 			    procflow->pf_name, procflow, i + 1);
    250  5184  ek110237 			if (newproc == NULL)
    251  5184  ek110237 				ret = -1;
    252  5184  ek110237 			else
    253  5184  ek110237 				ret = procflow_createproc(newproc);
    254  5184  ek110237 		}
    255  5184  ek110237 
    256  5184  ek110237 		if (ret != 0)
    257  5184  ek110237 			break;
    258  5184  ek110237 
    259  5184  ek110237 		procflow = procflow->pf_next;
    260  5184  ek110237 	}
    261  5184  ek110237 
    262  5184  ek110237 	return (ret);
    263  5184  ek110237 }
    264  5184  ek110237 
    265  5184  ek110237 #ifdef USE_PROCESS_MODEL
    266  5184  ek110237 /*
    267  5184  ek110237  * Used to start up threads on a child process, when filebench is
    268  5184  ek110237  * compiled to support multiple processes. Uses the name string
    269  5184  ek110237  * and instance number passed to the child to find the previously
    270  5184  ek110237  * created procflow entity. Then uses nice() to reduce the
    271  5184  ek110237  * process' priority by at least 10. A call is then made to
    272  5184  ek110237  * threadflow_init() which creates and runs the process' threads
    273  5184  ek110237  * and flowops to completion. When threadflow_init() returns,
    274  5184  ek110237  * a call to exit() terminates the child process.
    275  5184  ek110237  */
    276  5184  ek110237 int
    277  5184  ek110237 procflow_exec(char *name, int instance)
    278  5184  ek110237 {
    279  5184  ek110237 	procflow_t *procflow;
    280  5184  ek110237 	int proc_nice;
    281  5184  ek110237 #ifdef HAVE_SETRLIMIT
    282  5184  ek110237 	struct rlimit rlp;
    283  5184  ek110237 #endif
    284  6084  aw148015 	int ret;
    285  5184  ek110237 
    286  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL,
    287  5184  ek110237 	    "procflow_execproc %s-%d",
    288  5184  ek110237 	    name, instance);
    289  5184  ek110237 
    290  5184  ek110237 	if ((procflow = procflow_find(name, instance)) == NULL) {
    291  5184  ek110237 		filebench_log(LOG_ERROR,
    292  5184  ek110237 		    "procflow_exec could not find %s-%d",
    293  5184  ek110237 		    name, instance);
    294  5184  ek110237 		return (-1);
    295  5184  ek110237 	}
    296  6084  aw148015 
    297  6084  aw148015 	/* set the slave process' procflow pointer */
    298  6084  aw148015 	my_procflow = procflow;
    299  6084  aw148015 
    300  6084  aw148015 	/* set its pid from value stored by main() */
    301  6084  aw148015 	procflow->pf_pid = my_pid;
    302  5184  ek110237 
    303  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL,
    304  6084  aw148015 	    "Started up %s pid %d", procflow->pf_name, my_pid);
    305  5184  ek110237 
    306  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL,
    307  5184  ek110237 	    "nice = %llx", procflow->pf_nice);
    308  5184  ek110237 
    309  6212  aw148015 	proc_nice = avd_get_int(procflow->pf_nice);
    310  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "Setting pri of %s-%d to %d",
    311  5184  ek110237 	    name, instance, nice(proc_nice + 10));
    312  5184  ek110237 
    313  5184  ek110237 	procflow->pf_running = 1;
    314  5184  ek110237 
    315  5184  ek110237 #ifdef HAVE_SETRLIMIT
    316  5184  ek110237 	/* Get resource limits */
    317  5184  ek110237 	(void) getrlimit(RLIMIT_NOFILE, &rlp);
    318  5184  ek110237 	filebench_log(LOG_DEBUG_SCRIPT, "%d file descriptors", rlp.rlim_cur);
    319  5184  ek110237 #endif
    320  5184  ek110237 
    321  6084  aw148015 	if ((ret = threadflow_init(procflow)) != FILEBENCH_OK) {
    322  6084  aw148015 		if (ret < 0) {
    323  6084  aw148015 			filebench_log(LOG_ERROR,
    324  6084  aw148015 			    "Failed to start threads for %s pid %d",
    325  6084  aw148015 			    procflow->pf_name, my_pid);
    326  6084  aw148015 		}
    327  6084  aw148015 	} else {
    328  6084  aw148015 		filebench_log(LOG_DEBUG_IMPL,
    329  6084  aw148015 		    "procflow_createproc exiting...");
    330  5184  ek110237 	}
    331  6084  aw148015 
    332  6701  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock);
    333  6701  aw148015 	filebench_shm->shm_procs_running --;
    334  6701  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock);
    335  5184  ek110237 	procflow->pf_running = 0;
    336  5184  ek110237 
    337  6084  aw148015 	return (ret);
    338  5184  ek110237 }
    339  5184  ek110237 
    340  5184  ek110237 
    341  5184  ek110237 /*
    342  5184  ek110237  * A special thread from which worker (child) processes are created, and
    343  5184  ek110237  * which then waits for worker processes to die. If they die unexpectedly,
    344  5184  ek110237  * that is not a simple exit(0), then report an error and terminate the
    345  5184  ek110237  * run.
    346  5184  ek110237  */
    347  5184  ek110237 /* ARGSUSED */
    348  5184  ek110237 static void *
    349  5184  ek110237 procflow_createnwait(void *nothing)
    350  5184  ek110237 {
    351  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    352  5184  ek110237 
    353  5184  ek110237 	if (procflow_create_all_procs() == 0)
    354  5184  ek110237 		cnw_wait = CNW_DONE;
    355  5184  ek110237 	else
    356  5184  ek110237 		cnw_wait = CNW_ERROR;
    357  5184  ek110237 
    358  7556    Andrew 	if (pthread_cond_signal(&filebench_shm->shm_procflow_procs_cv) != 0)
    359  5184  ek110237 		exit(1);
    360  5184  ek110237 
    361  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    362  5184  ek110237 
    363  5184  ek110237 	/* CONSTCOND */
    364  5184  ek110237 	while (1) {
    365  5184  ek110237 		siginfo_t status;
    366  5184  ek110237 
    367  5184  ek110237 		/* wait for any child process to exit */
    368  5184  ek110237 		if (waitid(P_ALL, 0, &status, WEXITED) != 0)
    369  5184  ek110237 			pthread_exit(0);
    370  5184  ek110237 
    371  6701  aw148015 		(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    372  5184  ek110237 		/* if normal shutdown in progress, just quit */
    373  9326    Andrew 		if (filebench_shm->shm_f_abort) {
    374  6701  aw148015 			(void) ipc_mutex_unlock(
    375  6701  aw148015 			    &filebench_shm->shm_procflow_lock);
    376  5184  ek110237 			pthread_exit(0);
    377  9326    Andrew 		}
    378  6701  aw148015 
    379  6701  aw148015 		/* if nothing running, exit */
    380  6701  aw148015 		if (filebench_shm->shm_procs_running == 0) {
    381  6701  aw148015 			filebench_shm->shm_f_abort = FILEBENCH_ABORT_RSRC;
    382  6701  aw148015 			(void) ipc_mutex_unlock(
    383  6701  aw148015 			    &filebench_shm->shm_procflow_lock);
    384  6701  aw148015 			pthread_exit(0);
    385  6701  aw148015 		}
    386  6701  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    387  5184  ek110237 
    388  5184  ek110237 		if (status.si_code == CLD_EXITED) {
    389  5184  ek110237 			/* A process called exit(); check returned status */
    390  5184  ek110237 			if (status.si_status != 0) {
    391  5184  ek110237 				filebench_log(LOG_ERROR,
    392  5184  ek110237 				    "Unexpected Process termination; exiting",
    393  5184  ek110237 				    status.si_status);
    394  5184  ek110237 				filebench_shutdown(1);
    395  5184  ek110237 			}
    396  5184  ek110237 		} else {
    397  5184  ek110237 			/* A process quit because of some fatal error */
    398  5184  ek110237 			filebench_log(LOG_ERROR,
    399  5184  ek110237 			    "Unexpected Process termination Code %d, Errno %d",
    400  5184  ek110237 			    status.si_code, status.si_errno);
    401  5184  ek110237 			filebench_shutdown(1);
    402  5184  ek110237 		}
    403  5184  ek110237 
    404  5184  ek110237 	}
    405  5184  ek110237 	/* NOTREACHED */
    406  5184  ek110237 	return (NULL);
    407  5184  ek110237 }
    408  8762    Andrew 
    409  8762    Andrew /*
    410  8762    Andrew  * Cancel all threads within a processes, as well as the process itself.
    411  8762    Andrew  * Called by ^c or by sig_kill
    412  8762    Andrew  */
    413  8762    Andrew /* ARGSUSED */
    414  8762    Andrew static void
    415  8762    Andrew procflow_cancel(int arg1)
    416  8762    Andrew {
    417  8762    Andrew 	filebench_log(LOG_DEBUG_IMPL, "Process signal handler on pid %",
    418  8762    Andrew 	    my_procflow->pf_pid);
    419  8762    Andrew 
    420  8762    Andrew 	procflow_sleep(my_procflow, SHUTDOWN_WAIT_SECONDS);
    421  8762    Andrew 
    422  8762    Andrew 	threadflow_delete_all(&my_procflow->pf_threads);
    423  8762    Andrew 
    424  8762    Andrew 	/* quit the main procflow thread and hence the process */
    425  8762    Andrew 	exit(0);
    426  8762    Andrew }
    427  8762    Andrew 
    428  5184  ek110237 #endif	/* USE_PROCESS_MODEL */
    429  5184  ek110237 
    430  5184  ek110237 /*
    431  5184  ek110237  * Iterates through proclist, the master list of procflows,
    432  5184  ek110237  * creating the number of instances of each procflow specified
    433  5184  ek110237  * by its pf_instance attribute. Returns 0 on success, or -1
    434  5184  ek110237  * times the number of procflow instances that were not
    435  5184  ek110237  * successfully created.
    436  5184  ek110237  */
    437  5184  ek110237 int
    438  5184  ek110237 procflow_init(void)
    439  5184  ek110237 {
    440  6391  aw148015 	procflow_t *procflow = filebench_shm->shm_proclist;
    441  5184  ek110237 	pthread_t tid;
    442  5184  ek110237 	int ret = 0;
    443  5184  ek110237 
    444  9326    Andrew 	if (procflow == NULL) {
    445  9326    Andrew 		filebench_log(LOG_ERROR, "Workload has no processes");
    446  9326    Andrew 		return (FILEBENCH_ERROR);
    447  9326    Andrew 	}
    448  9326    Andrew 
    449  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL,
    450  6286  aw148015 	    "procflow_init %s, %llu",
    451  6286  aw148015 	    procflow->pf_name,
    452  6286  aw148015 	    (u_longlong_t)avd_get_int(procflow->pf_instances));
    453  5184  ek110237 
    454  5184  ek110237 #ifdef USE_PROCESS_MODEL
    455  5184  ek110237 	if ((pthread_create(&tid, NULL, procflow_createnwait, NULL)) != 0)
    456  5184  ek110237 		return (ret);
    457  5184  ek110237 
    458  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    459  8762    Andrew 
    460  8762    Andrew 	(void) signal(SIGUSR1, procflow_cancel);
    461  5184  ek110237 
    462  7556    Andrew 	if ((ret = pthread_cond_wait(&filebench_shm->shm_procflow_procs_cv,
    463  6391  aw148015 	    &filebench_shm->shm_procflow_lock)) != 0)
    464  5184  ek110237 		return (ret);
    465  5184  ek110237 
    466  5184  ek110237 	if (cnw_wait == CNW_ERROR)
    467  5184  ek110237 		ret = -1;
    468  5184  ek110237 
    469  5184  ek110237 #else /* USE_PROCESS_MODEL */
    470  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    471  5184  ek110237 
    472  5184  ek110237 	ret = procflow_create_all_procs();
    473  5184  ek110237 #endif /* USE_PROCESS_MODEL */
    474  5184  ek110237 
    475  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    476  5184  ek110237 
    477  5184  ek110237 	return (ret);
    478  5184  ek110237 }
    479  5184  ek110237 
    480  5184  ek110237 #ifdef USE_PROCESS_MODEL
    481  5184  ek110237 /*
    482  5184  ek110237  * Waits for child processes to finish and returns their exit
    483  5184  ek110237  * status. Used by procflow_delete() when the process model is
    484  5184  ek110237  * enabled to wait for a deleted process to exit.
    485  5184  ek110237  */
    486  5184  ek110237 static void
    487  5184  ek110237 procflow_wait(pid_t pid)
    488  5184  ek110237 {
    489  5184  ek110237 	pid_t wpid;
    490  5184  ek110237 	int stat;
    491  5184  ek110237 
    492  5184  ek110237 	(void) waitpid(pid, &stat, 0);
    493  5184  ek110237 	while ((wpid = waitpid(getpid() * -1, &stat, WNOHANG)) > 0)
    494  6286  aw148015 		filebench_log(LOG_DEBUG_IMPL, "Waited for pid %d", (int)wpid);
    495  5184  ek110237 }
    496  5184  ek110237 #endif
    497  5184  ek110237 
    498  5184  ek110237 /*
    499  8762    Andrew  * Common routine to sleep for wait_cnt seconds or for pf_running to
    500  8762    Andrew  * go false. Checks once a second to see if pf_running has gone false.
    501  8762    Andrew  */
    502  8762    Andrew static void
    503  8762    Andrew procflow_sleep(procflow_t *procflow, int wait_cnt)
    504  8762    Andrew {
    505  8762    Andrew 	while (procflow->pf_running & wait_cnt) {
    506  8769    Andrew 		(void) sleep(1);
    507  8762    Andrew 		wait_cnt--;
    508  8762    Andrew 	}
    509  8762    Andrew }
    510  8762    Andrew 
    511  8762    Andrew /*
    512  8762    Andrew  * Deletes the designated procflow. Finally it frees the
    513  6391  aw148015  * procflow entity. filebench_shm->shm_procflow_lock must be held on entry.
    514  5184  ek110237  *
    515  5184  ek110237  * If the designated procflow is not found on the list it returns -1 and
    516  5184  ek110237  * the procflow is not deleted. Otherwise it returns 0.
    517  5184  ek110237  */
    518  5184  ek110237 static int
    519  8762    Andrew procflow_cleanup(procflow_t *procflow)
    520  5184  ek110237 {
    521  5184  ek110237 	procflow_t *entry;
    522  5184  ek110237 
    523  5184  ek110237 	filebench_log(LOG_DEBUG_SCRIPT,
    524  5184  ek110237 	    "Deleted proc: (%s-%d) pid %d",
    525  5184  ek110237 	    procflow->pf_name,
    526  5184  ek110237 	    procflow->pf_instance,
    527  5184  ek110237 	    procflow->pf_pid);
    528  5184  ek110237 
    529  8762    Andrew 	procflow->pf_running = 0;
    530  5184  ek110237 
    531  5184  ek110237 	/* remove entry from proclist */
    532  6391  aw148015 	entry = filebench_shm->shm_proclist;
    533  5184  ek110237 
    534  5184  ek110237 	/* unlink procflow entity from proclist */
    535  5184  ek110237 	if (entry == procflow) {
    536  5184  ek110237 		/* at head of list */
    537  6391  aw148015 		filebench_shm->shm_proclist = procflow->pf_next;
    538  5184  ek110237 	} else {
    539  5184  ek110237 		/* search list for procflow */
    540  5184  ek110237 		while (entry && entry->pf_next != procflow)
    541  5184  ek110237 			entry = entry->pf_next;
    542  5184  ek110237 
    543  5184  ek110237 		/* if entity found, unlink it */
    544  5184  ek110237 		if (entry == NULL)
    545  5184  ek110237 			return (-1);
    546  5184  ek110237 		else
    547  5184  ek110237 			entry->pf_next = procflow->pf_next;
    548  5184  ek110237 	}
    549  5184  ek110237 
    550  5184  ek110237 	/* free up the procflow entity */
    551  5184  ek110237 	ipc_free(FILEBENCH_PROCFLOW, (char *)procflow);
    552  5184  ek110237 	return (0);
    553  5184  ek110237 }
    554  5184  ek110237 
    555  5184  ek110237 
    556  5184  ek110237 /*
    557  5184  ek110237  * Waits till all threadflows are started, or a timeout occurs.
    558  5184  ek110237  * Checks through the list of procflows, waiting up to 30
    559  5184  ek110237  * seconds for each one to set its pf_running flag to 1. If not
    560  5184  ek110237  * set after 30 seconds, continues on to the next procflow
    561  5184  ek110237  * anyway after logging the fact. Once pf_running is set
    562  5184  ek110237  * to 1 for a given procflow or the timeout is reached,
    563  5184  ek110237  * threadflow_allstarted() is called to start the threads.
    564  6391  aw148015  * Returns 0 (OK), unless filebench_shm->shm_f_abort is signaled,
    565  5184  ek110237  * in which case it returns -1.
    566  5184  ek110237  */
    567  5184  ek110237 int
    568  5184  ek110237 procflow_allstarted()
    569  5184  ek110237 {
    570  6391  aw148015 	procflow_t *procflow = filebench_shm->shm_proclist;
    571  6084  aw148015 	int running_procs = 0;
    572  5184  ek110237 	int ret = 0;
    573  5184  ek110237 
    574  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    575  5184  ek110237 
    576  5184  ek110237 	(void) sleep(1);
    577  5184  ek110237 
    578  5184  ek110237 	while (procflow) {
    579  5184  ek110237 		int waits;
    580  5184  ek110237 
    581  5184  ek110237 		if (procflow->pf_instance &&
    582  5184  ek110237 		    (procflow->pf_instance == FLOW_MASTER)) {
    583  5184  ek110237 			procflow = procflow->pf_next;
    584  5184  ek110237 			continue;
    585  5184  ek110237 		}
    586  5184  ek110237 
    587  5184  ek110237 		waits = 10;
    588  5184  ek110237 		while (waits && procflow->pf_running == 0) {
    589  6391  aw148015 			(void) ipc_mutex_unlock(
    590  6391  aw148015 			    &filebench_shm->shm_procflow_lock);
    591  6391  aw148015 			if (filebench_shm->shm_f_abort == 1)
    592  5184  ek110237 				return (-1);
    593  5184  ek110237 
    594  5184  ek110237 			if (waits < 3)
    595  5184  ek110237 				filebench_log(LOG_INFO,
    596  5184  ek110237 				    "Waiting for process %s-%d %d",
    597  5184  ek110237 				    procflow->pf_name,
    598  5184  ek110237 				    procflow->pf_instance,
    599  5184  ek110237 				    procflow->pf_pid);
    600  5184  ek110237 
    601  5184  ek110237 			(void) sleep(3);
    602  5184  ek110237 			waits--;
    603  6391  aw148015 			(void) ipc_mutex_lock(
    604  6391  aw148015 			    &filebench_shm->shm_procflow_lock);
    605  5184  ek110237 		}
    606  5184  ek110237 
    607  5184  ek110237 		if (waits == 0)
    608  6084  aw148015 			filebench_log(LOG_INFO,
    609  6084  aw148015 			    "Failed to start process %s-%d",
    610  5184  ek110237 			    procflow->pf_name,
    611  5184  ek110237 			    procflow->pf_instance);
    612  5184  ek110237 
    613  6084  aw148015 		running_procs++;
    614  5184  ek110237 		threadflow_allstarted(procflow->pf_pid, procflow->pf_threads);
    615  5184  ek110237 
    616  5184  ek110237 		procflow = procflow->pf_next;
    617  5184  ek110237 	}
    618  6701  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock);
    619  6701  aw148015 	filebench_shm->shm_procs_running = running_procs;
    620  6701  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock);
    621  5184  ek110237 
    622  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    623  5184  ek110237 
    624  5184  ek110237 
    625  5184  ek110237 	return (ret);
    626  5184  ek110237 }
    627  5184  ek110237 
    628  5184  ek110237 
    629  5184  ek110237 /*
    630  6084  aw148015  * Sets the f_abort flag and clears the running count to stop
    631  5184  ek110237  * all the flowop execution threads from running. Iterates
    632  5184  ek110237  * through the procflow list and deletes all procflows except
    633  5184  ek110237  * for the FLOW_MASTER procflow. Resets the f_abort flag when
    634  5184  ek110237  * finished.
    635  6701  aw148015  *
    636  5184  ek110237  */
    637  5184  ek110237 void
    638  5184  ek110237 procflow_shutdown(void)
    639  5184  ek110237 {
    640  8762    Andrew 	procflow_t *procflow, *next_procflow;
    641  8762    Andrew 	int wait_cnt = SHUTDOWN_WAIT_SECONDS;
    642  5184  ek110237 
    643  6701  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock);
    644  7556    Andrew 	if (filebench_shm->shm_procs_running <= 0) {
    645  6701  aw148015 		/* No processes running, so no need to do anything */
    646  6701  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock);
    647  6701  aw148015 		return;
    648  6701  aw148015 	}
    649  6701  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock);
    650  6701  aw148015 
    651  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    652  9326    Andrew 	if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_FINI) {
    653  9326    Andrew 		(void) ipc_mutex_unlock(
    654  9326    Andrew 		    &filebench_shm->shm_procflow_lock);
    655  9326    Andrew 		return;
    656  9326    Andrew 	}
    657  9326    Andrew 
    658  8615    Andrew 	procflow = filebench_shm->shm_proclist;
    659  9326    Andrew 	if (filebench_shm->shm_f_abort == FILEBENCH_OK)
    660  9326    Andrew 		filebench_shm->shm_f_abort = FILEBENCH_ABORT_DONE;
    661  5184  ek110237 
    662  5184  ek110237 	while (procflow) {
    663  5184  ek110237 		if (procflow->pf_instance &&
    664  5184  ek110237 		    (procflow->pf_instance == FLOW_MASTER)) {
    665  5184  ek110237 			procflow = procflow->pf_next;
    666  5184  ek110237 			continue;
    667  5184  ek110237 		}
    668  5184  ek110237 		filebench_log(LOG_DEBUG_IMPL, "Deleting process %s-%d %d",
    669  5184  ek110237 		    procflow->pf_name,
    670  5184  ek110237 		    procflow->pf_instance,
    671  5184  ek110237 		    procflow->pf_pid);
    672  8762    Andrew 
    673  8762    Andrew 		next_procflow = procflow->pf_next;
    674  8762    Andrew 
    675  8762    Andrew 		/*
    676  8762    Andrew 		 * Signalling the process with SIGUSR1 will result in it
    677  8762    Andrew 		 * gracefully shutting down and exiting
    678  8762    Andrew 		 */
    679  8762    Andrew 		procflow_sleep(procflow, wait_cnt);
    680  8762    Andrew 		if (procflow->pf_running) {
    681  8762    Andrew #ifdef USE_PROCESS_MODEL
    682  8762    Andrew 			pid_t pid;
    683  8762    Andrew 
    684  8762    Andrew 			pid = procflow->pf_pid;
    685  8762    Andrew #ifdef HAVE_SIGSEND
    686  8762    Andrew 			(void) sigsend(P_PID, pid, SIGUSR1);
    687  8762    Andrew #else
    688  8762    Andrew 			(void) kill(pid, SIGUSR1);
    689  8762    Andrew #endif
    690  8762    Andrew 			procflow_wait(pid);
    691  8762    Andrew 
    692  8762    Andrew #else /* USE_PROCESS_MODEL */
    693  8762    Andrew 			threadflow_delete_all(&procflow->pf_threads);
    694  8762    Andrew #endif /* USE_PROCESS_MODEL */
    695  8762    Andrew 		}
    696  8762    Andrew 		(void) procflow_cleanup(procflow);
    697  8762    Andrew 		procflow = next_procflow;
    698  8762    Andrew 		if (wait_cnt > 0)
    699  6084  aw148015 			wait_cnt--;
    700  5184  ek110237 	}
    701  5184  ek110237 
    702  9326    Andrew 	filebench_shm->shm_f_abort = FILEBENCH_ABORT_FINI;
    703  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    704  7556    Andrew 
    705  7556    Andrew 	/* indicate all processes are stopped, even if some are "stuck" */
    706  7556    Andrew 	(void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock);
    707  7556    Andrew 	filebench_shm->shm_procs_running = 0;
    708  7556    Andrew 	(void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock);
    709  5184  ek110237 }
    710  5184  ek110237 
    711  5184  ek110237 
    712  5184  ek110237 /*
    713  5184  ek110237  * Create an in-memory process object. Allocates a procflow
    714  5184  ek110237  * entity, initialized from the "inherit" procflow if supplied.
    715  5184  ek110237  * The name and instance number are set from the supplied name
    716  5184  ek110237  * and instance number and the procflow is added to the head of
    717  5184  ek110237  * the master procflow list. Returns pointer to the allocated
    718  5184  ek110237  * procflow, or NULL if a name isn't supplied or the procflow
    719  5184  ek110237  * entity cannot be allocated.
    720  5184  ek110237  *
    721  6391  aw148015  * The calling routine must hold the filebench_shm->shm_procflow_lock.
    722  5184  ek110237  */
    723  5184  ek110237 static procflow_t *
    724  5184  ek110237 procflow_define_common(procflow_t **list, char *name,
    725  5184  ek110237     procflow_t *inherit, int instance)
    726  5184  ek110237 {
    727  5184  ek110237 	procflow_t *procflow;
    728  5184  ek110237 
    729  5184  ek110237 	if (name == NULL)
    730  5184  ek110237 		return (NULL);
    731  5184  ek110237 
    732  5184  ek110237 	procflow = (procflow_t *)ipc_malloc(FILEBENCH_PROCFLOW);
    733  5184  ek110237 
    734  5184  ek110237 	if (procflow == NULL)
    735  5184  ek110237 		return (NULL);
    736  5184  ek110237 
    737  5184  ek110237 	if (inherit)
    738  5184  ek110237 		(void) memcpy(procflow, inherit, sizeof (procflow_t));
    739  5184  ek110237 	else
    740  5184  ek110237 		(void) memset(procflow, 0, sizeof (procflow_t));
    741  5184  ek110237 
    742  5184  ek110237 	procflow->pf_instance = instance;
    743  5184  ek110237 	(void) strcpy(procflow->pf_name, name);
    744  5184  ek110237 
    745  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "defining process %s-%d", name, instance);
    746  5184  ek110237 
    747  5184  ek110237 	/* Add procflow to list, lock is being held already */
    748  5184  ek110237 	if (*list == NULL) {
    749  5184  ek110237 		*list = procflow;
    750  5184  ek110237 		procflow->pf_next = NULL;
    751  5184  ek110237 	} else {
    752  5184  ek110237 		procflow->pf_next = *list;
    753  5184  ek110237 		*list = procflow;
    754  5184  ek110237 	}
    755  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "process %s-%d proclist %zx",
    756  6391  aw148015 	    name, instance, filebench_shm->shm_proclist);
    757  5184  ek110237 
    758  5184  ek110237 	return (procflow);
    759  5184  ek110237 }
    760  5184  ek110237 
    761  5184  ek110237 /*
    762  5184  ek110237  * Create an in-memory process object as described by the syntax.
    763  6391  aw148015  * Acquires the filebench_shm->shm_procflow_lock and calls
    764  5184  ek110237  * procflow_define_common() to create and initialize a
    765  5184  ek110237  * FLOW_MASTER procflow entity from the optional "inherit"
    766  5184  ek110237  * procflow with the given name and configured for "instances"
    767  5184  ek110237  * number of worker procflows. Currently only called from
    768  5184  ek110237  * parser_proc_define().
    769  5184  ek110237  */
    770  5184  ek110237 procflow_t *
    771  6212  aw148015 procflow_define(char *name, procflow_t *inherit, avd_t instances)
    772  5184  ek110237 {
    773  5184  ek110237 	procflow_t *procflow;
    774  5184  ek110237 
    775  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    776  5184  ek110237 
    777  6391  aw148015 	procflow = procflow_define_common(&filebench_shm->shm_proclist,
    778  5184  ek110237 	    name, inherit, FLOW_MASTER);
    779  5184  ek110237 	procflow->pf_instances = instances;
    780  5184  ek110237 
    781  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    782  5184  ek110237 
    783  5184  ek110237 	return (procflow);
    784  5184  ek110237 }
    785