Ejemplo n.º 1
0
static int
flowop_create_runtime_flowops(threadflow_t *threadflow, flowop_t **ops_list_ptr)
{
	flowop_t *flowop = *ops_list_ptr;
	char *name;

	while (flowop) {
		flowop_t *newflowop;

		if (flowop == *ops_list_ptr)
			*ops_list_ptr = NULL;

		newflowop = flowop_define_common(threadflow, flowop->fo_name,
		    flowop, ops_list_ptr, 1, 0);
		if (newflowop == NULL)
			return (FILEBENCH_ERROR);

		/* check for fo_filename attribute, and resolve if present */
		if (flowop->fo_filename) {
			name = avd_get_str(flowop->fo_filename);
			newflowop->fo_fileset = fileset_find(name);

			if (newflowop->fo_fileset == NULL) {
				filebench_log(LOG_ERROR,
				    "flowop %s: file %s not found",
				    newflowop->fo_name, name);
				filebench_shutdown(1);
			}
		}

		/* check for fo_possetname attribute, and resolve if present */
		if (flowop->fo_possetname) {
			name = avd_get_str(flowop->fo_possetname);
			newflowop->fo_posset = posset_find(name);

			if (newflowop->fo_posset == NULL) {
				filebench_log(LOG_ERROR,
				    "flowop %s: posset %s not found",
				    newflowop->fo_name, name);
				filebench_shutdown(1);
			}
		}

		if (flowop_initflow(newflowop) < 0) {
			filebench_log(LOG_ERROR, "Flowop init of %s failed",
			    newflowop->fo_name);
		}

		flowop = flowop->fo_exec_next;
	}
	return (FILEBENCH_OK);
}
Ejemplo n.º 2
0
/*
 * Initialize mutex attributes for the various flavors of mutexes
 */
static void
ipc_mutexattr_init(int mtx_type)
{
	pthread_mutexattr_t *mtx_attrp;

	mtx_attrp = &(filebench_shm->shm_mutexattr[mtx_type]);

	(void) pthread_mutexattr_init(mtx_attrp);

#ifdef USE_PROCESS_MODEL
#ifdef HAVE_PROCSCOPE_PTHREADS
	if (pthread_mutexattr_setpshared(mtx_attrp,
	    PTHREAD_PROCESS_SHARED) != 0) {
		filebench_log(LOG_ERROR, "cannot set mutex attr "
		    "PROCESS_SHARED on this platform");
		filebench_shutdown(1);
	}
#ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
	if (mtx_type & IPC_MUTEX_PRIORITY) {
		if (pthread_mutexattr_setprotocol(mtx_attrp,
		    PTHREAD_PRIO_INHERIT) != 0) {
			filebench_log(LOG_ERROR,
			    "cannot set mutex attr "
			    "PTHREAD_PRIO_INHERIT on this platform");
			filebench_shutdown(1);
		}
	}
#endif /* HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL */
#endif /* HAVE_PROCSCOPE_PTHREADS */
#ifdef HAVE_ROBUST_MUTEX
	if (mtx_type & IPC_MUTEX_ROBUST) {
		if (pthread_mutexattr_setrobust_np(mtx_attrp,
		    PTHREAD_MUTEX_ROBUST_NP) != 0) {
			filebench_log(LOG_ERROR,
			    "cannot set mutex attr "
			    "PTHREAD_MUTEX_ROBUST_NP on this platform");
			filebench_shutdown(1);
		}
		if (pthread_mutexattr_settype(mtx_attrp,
		    PTHREAD_MUTEX_ERRORCHECK) != 0) {
			filebench_log(LOG_ERROR,
			    "cannot set mutex attr "
			    "PTHREAD_MUTEX_ERRORCHECK "
			    "on this platform");
			filebench_shutdown(1);
		}
	}
#endif /* HAVE_ROBUST_MUTEX */
#endif /* USE_PROCESS_MODEL */
}
Ejemplo n.º 3
0
/*
 * Loops through the supplied list of flowops and creates and initializes
 * a flowop for each one by calling flowop_define. As a side effect of
 * calling flowop define, the created flowops are placed on the
 * master flowop list. All created flowops are set to instance "0".
 */
void
flowop_flow_init(flowop_proto_t *list, int nops)
{
	int i;

	for (i = 0; i < nops; i++) {
		flowop_t *flowop;
		flowop_proto_t *fl;

		fl = &(list[i]);

		if ((flowop = flowop_define(NULL,
		    fl->fl_name, NULL, NULL, 0, fl->fl_type)) == 0) {
			filebench_log(LOG_ERROR,
			    "failed to create flowop %s\n",
			    fl->fl_name);
			filebench_shutdown(1);
		}

		flowop->fo_func = fl->fl_func;
		flowop->fo_init = fl->fl_init;
		flowop->fo_destruct = fl->fl_destruct;
		flowop->fo_attrs = fl->fl_attrs;
	}
}
Ejemplo n.º 4
0
double
get_cvar_value(cvar_t *cvar)
{
	int ret;
	double value = 0.0;
	fbint_t round = cvar->round;

	ipc_mutex_lock(&cvar->cvar_lock);
	cvar_library_t *cvar_lib = cvar_libraries[cvar->cvar_lib_info->index];
	ret = cvar_lib->cvar_op.cvar_next_value(cvar->cvar_handle, &value);
	ipc_mutex_unlock(&cvar->cvar_lock);

	if (ret) {
		filebench_log(LOG_ERROR, "Unable to get next_value from custom variable"
				" of type %s", cvar->cvar_lib_info->type);
		filebench_shutdown(1);
	}

	if (round) {
		fbint_t num, lower, upper;

		num = (fbint_t) value;
		lower = num - (num % round);
		upper = lower + round;

		value = (num - lower) > (upper - num) ? upper : lower;
	}

	if (value < cvar->min)
		value = cvar->min;
	else if (value > cvar->max)
		value = cvar->max;

	return value;
}
Ejemplo n.º 5
0
Archivo: ipc.c Proyecto: alhazred/onarm
/*
 * On first invocation, allocates a mutex attributes structure
 * and initializes it with appropriate attributes. In all cases,
 * returns a pointer to the structure.
 */
pthread_mutexattr_t *
ipc_mutexattr(void)
{
#ifdef USE_PROCESS_MODEL
	if (mutexattr == NULL) {
		if ((mutexattr =
		    malloc(sizeof (pthread_mutexattr_t))) == NULL) {
			filebench_log(LOG_ERROR, "cannot alloc mutex attr");
			filebench_shutdown(1);
		}
#ifdef HAVE_PROCSCOPE_PTHREADS
		(void) pthread_mutexattr_init(mutexattr);
		if (pthread_mutexattr_setpshared(mutexattr,
		    PTHREAD_PROCESS_SHARED) != 0) {
			filebench_log(LOG_ERROR, "cannot set mutex attr "
			    "PROCESS_SHARED on this platform");
			filebench_shutdown(1);
		}
#ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
		if (pthread_mutexattr_setprotocol(mutexattr,
		    PTHREAD_PRIO_INHERIT) != 0) {
			filebench_log(LOG_ERROR, "cannot set mutex attr "
			    "PTHREAD_PRIO_INHERIT on this platform");
			filebench_shutdown(1);
		}
#endif /* HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL */
#endif /* HAVE_PROCSCOPE_PTHREADS */
#ifdef HAVE_ROBUST_MUTEX
		if (pthread_mutexattr_setrobust_np(mutexattr,
		    PTHREAD_MUTEX_ROBUST_NP) != 0) {
			filebench_log(LOG_ERROR, "cannot set mutex attr "
			    "PTHREAD_MUTEX_ROBUST_NP on this platform");
			filebench_shutdown(1);
		}
		if (pthread_mutexattr_settype(mutexattr,
		    PTHREAD_MUTEX_ERRORCHECK) != 0) {
			filebench_log(LOG_ERROR, "cannot set mutex attr "
			    "PTHREAD_MUTEX_ERRORCHECK on this platform");
			filebench_shutdown(1);
		}
#endif /* HAVE_ROBUST_MUTEX */

	}
#endif /* USE_PROCESS_MODEL */
	return (mutexattr);
}
Ejemplo n.º 6
0
/*
 * Returns the number of preallocated objects in the filebench_shm region
 */
static int
preallocated_entries(int obj_type)
{
	int entries;

	switch(obj_type) {
	case FILEBENCH_FILESET:
		entries = sizeof(filebench_shm->shm_fileset)
						/ sizeof(fileset_t);
		break;
	case FILEBENCH_FILESETENTRY:
		entries = sizeof(filebench_shm->shm_filesetentry)
						/ sizeof(filesetentry_t);
		break;
	case FILEBENCH_PROCFLOW:
		entries = sizeof(filebench_shm->shm_procflow)
						/ sizeof(procflow_t);
		break;
	case FILEBENCH_THREADFLOW:
		entries = sizeof(filebench_shm->shm_threadflow)
						/ sizeof(threadflow_t);
		break;
	case FILEBENCH_FLOWOP:
		entries = sizeof(filebench_shm->shm_flowop)
						/ sizeof(flowop_t);
		break;
	case FILEBENCH_VARIABLE:
		entries = sizeof(filebench_shm->shm_var)
						/ sizeof(var_t);
		break;
	case FILEBENCH_AVD:
		entries = sizeof(filebench_shm->shm_avd_ptrs)
						/ sizeof(avd_t);
		break;
	case FILEBENCH_RANDDIST:
		entries = sizeof(filebench_shm->shm_randdist)
						/ sizeof(randdist_t);
		break;
	case FILEBENCH_CVAR:
		entries = sizeof(filebench_shm->shm_cvar)
						/ sizeof(cvar_t);
		break;
	case FILEBENCH_CVAR_LIB_INFO:
		entries = sizeof(filebench_shm->shm_cvar_lib_info)
						/ sizeof(cvar_library_info_t);
		break;
	default:
		entries = -1;
		filebench_log(LOG_ERROR, "preallocated_entries: "
						"unknown object type");
		filebench_shutdown(1);
		break;
	}

	return entries;
}
Ejemplo n.º 7
0
/*
 * Initialize the urandom random number source
 */
void
fb_random_init(void)
{
	/* open the "urandom" random number device file */
	if ((urandomfd = open("/dev/urandom", O_RDONLY)) < 0) {
		filebench_log(LOG_ERROR, "open /dev/urandom failed: %s",
		    strerror(errno));
		filebench_shutdown(1);
	}
}
Ejemplo n.º 8
0
Archivo: ipc.c Proyecto: alhazred/onarm
/*
 * On first invocation, allocates a condition variable attributes
 * structure and initializes it with appropriate attributes. In
 * all cases, returns a pointer to the structure.
 */
pthread_condattr_t *
ipc_condattr(void)
{
#ifdef USE_PROCESS_MODEL
	if (condattr == NULL) {
		if ((condattr = malloc(sizeof (pthread_condattr_t))) == NULL) {
			filebench_log(LOG_ERROR, "cannot alloc cond attr");
			filebench_shutdown(1);
		}
#ifdef HAVE_PROCSCOPE_PTHREADS
		(void) pthread_condattr_init(condattr);
		if (pthread_condattr_setpshared(condattr,
		    PTHREAD_PROCESS_SHARED) != 0) {
			filebench_log(LOG_ERROR,
			    "cannot set cond attr PROCESS_SHARED");
			filebench_shutdown(1);
		}
#endif /* HAVE_PROCSCOPE_PTHREADS */
	}
#endif /* USE_PROCESS_MODEL */
	return (condattr);
}
Ejemplo n.º 9
0
/*
 * Allocates a semid from the table of semids for pre intialized
 * semaphores. Searches for the first available semaphore, and
 * sets the entry in the table to "1" to indicate allocation.
 * Returns the allocated semid. Stops the run if all semaphores
 * are already in use.
 */
int
ipc_semidalloc(void)
{
	int semid;

	for (semid = 0; filebench_shm->shm_semids[semid] == 1; semid++)
		;
	if (semid == FILEBENCH_NSEMS) {
		filebench_log(LOG_ERROR,
		    "Out of semaphores, increase system tunable limit");
		filebench_shutdown(1);
	}
	filebench_shm->shm_semids[semid] = 1;
	return (semid);
}
Ejemplo n.º 10
0
void init_random_my()
{
	int urandomfd;
     int random_seed_my;
        urandomfd = open("/home/shubhamiit/random_seed", O_RDONLY);
        if (urandomfd < 0) {
                filebench_log(LOG_ERROR, "open /dev/urandom failed: %s",
                    strerror(errno));
                filebench_shutdown(1);
        }

        read (urandomfd,&random_seed_my,sizeof(random_seed_my));
        printf("random seed: %d\n", random_seed_my);
        srand(random_seed_my);

}
Ejemplo n.º 11
0
/* ARGSUSED */
static double
rand_src_urandom(unsigned short *xi)
{
	fbint_t randnum;

	if (read(urandomfd, &randnum,
	    sizeof (fbint_t)) != sizeof (fbint_t)) {
		filebench_log(LOG_ERROR,
		    "read /dev/urandom failed: %s", strerror(errno));
		filebench_shutdown(1);
		return (0.0);
	}

	/* convert to 0-1 probability */
	return ((double)randnum / (double)(FILEBENCH_RANDMAX64));
}
Ejemplo n.º 12
0
/*
 * Reads a 32 bit random number from the urandom "file".
 * Shuts down the run if the read fails. Otherwise returns
 * the random number after rounding it off by "round".
 * Returns 0 on success, -1 on failure.
 */
int
filebench_randomno32(uint32_t *randp, uint32_t max,
    uint32_t round, avd_t avd)
{
	uint32_t random;

	/* check for round value too large */
	if (max <= round) {
		*randp = 0;

		/* if it just fits, its ok, otherwise error */
		if (max == round)
			return (0);
		else
			return (-1);
	}

	if (avd) {

		/* get it from the variable */
		random = (uint32_t)avd_get_int(avd);

	} else {

		/* get it from urandom */
		if (read(urandomfd, &random,
		    sizeof (uint32_t)) != sizeof (uint32_t)) {
			filebench_log(LOG_ERROR,
			    "read /dev/urandom failed: %s", strerror(errno));
			filebench_shutdown(1);
		}
	}

	/* clip with max and optionally round */
	max -= round;
	random = random / (FILEBENCH_RANDMAX32 / max);
	if (round) {
		random = random / round;
		random *= round;
	}
	if (random > max)
		random = max;

	*randp = random;
	return (0);
}
Ejemplo n.º 13
0
/*
 * Creates a thread for the supplied threadflow. If interprocess
 * shared memory is desired, then increments the amount of shared
 * memory needed by the amount specified in the threadflow's
 * tf_memsize parameter. The thread starts in routine
 * flowop_start() with a poineter to the threadflow supplied
 * as the argument.
 */
static int
threadflow_createthread(threadflow_t *threadflow)
{
	filebench_log(LOG_DEBUG_SCRIPT, "Creating thread %s, memory = %ld",
	    threadflow->tf_name,
	    *threadflow->tf_memsize);

	if (threadflow->tf_attrs & THREADFLOW_USEISM)
		filebench_shm->shm_required += (*threadflow->tf_memsize);

	if (pthread_create(&threadflow->tf_tid, NULL,
	    (void *(*)(void*))flowop_start, threadflow) != 0) {
		filebench_log(LOG_ERROR, "thread create failed");
		filebench_shutdown(1);
		return (FILEBENCH_ERROR);
	}

	return (FILEBENCH_OK);
}
Ejemplo n.º 14
0
/*
 * On first invocation, allocates a condition variable attributes
 * structure and initializes it with appropriate attributes. In
 * all cases, returns a pointer to the structure.
 */
pthread_condattr_t *
ipc_condattr(void)
{
	if (condattr == NULL) {
		if ((condattr = malloc(sizeof (pthread_condattr_t))) == NULL) {
			filebench_log(LOG_ERROR, "cannot alloc cond attr");
			filebench_shutdown(1);
		}
		(void) pthread_condattr_init(condattr);
#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
		if (pthread_condattr_setpshared(condattr,
		    PTHREAD_PROCESS_SHARED) != 0) {
			filebench_log(LOG_ERROR,
			    "cannot set cond attr PROCESS_SHARED");
//			filebench_shutdown(1);
		}
#endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */
	}
	return (condattr);
}
Ejemplo n.º 15
0
/*
 * Calls semget() to get a set of shared system V semaphores.
 */
void
ipc_seminit(void)
{
	key_t key = filebench_shm->shm_semkey;
	int sys_semid;

	/* Already done? */
	if (filebench_shm->shm_sys_semid >= 0)
		return;

	if ((sys_semid = semget(key, FILEBENCH_NSEMS, IPC_CREAT |
	    S_IRUSR | S_IWUSR)) == -1) {
		filebench_log(LOG_ERROR,
		    "could not create sysv semaphore set "
		    "(need to increase sems?): %s",
		    strerror(errno));
		filebench_shutdown(1);
	}

	filebench_shm->shm_sys_semid = sys_semid;
}
Ejemplo n.º 16
0
/*
 * On first invocation, allocates a readers/writers attributes
 * structure and initializes it with appropriate attributes.
 * In all cases, returns a pointer to the structure.
 */
static pthread_rwlockattr_t *
ipc_rwlockattr(void)
{
	if (rwlockattr == NULL) {
		if ((rwlockattr =
		    malloc(sizeof (pthread_rwlockattr_t))) == NULL) {
			filebench_log(LOG_ERROR, "cannot alloc rwlock attr");
			filebench_shutdown(1);
		}
		(void) pthread_rwlockattr_init(rwlockattr);
#ifdef HAVE_PROCSCOPE_PTHREADS
		if (pthread_rwlockattr_setpshared(rwlockattr,
		    PTHREAD_PROCESS_SHARED) != 0) {
			filebench_log(LOG_ERROR,
			    "cannot set rwlock attr PROCESS_SHARED");
//			filebench_shutdown(1);
		}
#endif /* HAVE_PROCSCOPE_PTHREADS */
	}
	return (rwlockattr);
}
Ejemplo n.º 17
0
/*
 * Searches for the named var, and if found returns a pointer
 * to the var's var_integer. If not found, attempts to allocate
 * a var named "name" and returns a  pointer to it's (zeroed)
 * var_integer. If the var cannot be found or allocated, an
 * error is logged and the run is terminated.
 */
vinteger_t *
var_ref_integer(char *name)
{
	var_t *var;

	name += 1;

	if ((var = var_find(name)) == NULL)
		var = var_find_dynamic(name);

	if (var == NULL)
		var = var_alloc(name);

	if (var == NULL) {
		filebench_log(LOG_ERROR, "Invalid variable $%s",
		    name);
		filebench_shutdown(1);
	}

	return (&var->var_integer);

}
Ejemplo n.º 18
0
/*
 * Initializes a random distribution entity, converting avd_t
 * parameters to doubles, and converting the list of probability density
 * function table entries, if supplied, into a probablilty function table
 */
static void
randdist_init_one(randdist_t *rndp)
{
	probtabent_t	*rdte_hdp, *ptep;
	double		tablemean, tablemin;
	int		pteidx;

	/* convert parameters to doubles */
	rndp->rnd_dbl_gamma = (double)avd_get_int(rndp->rnd_gamma) / 1000.0;
	if (rndp->rnd_mean != NULL)
		rndp->rnd_dbl_mean  = (double)avd_get_int(rndp->rnd_mean);
	else
		rndp->rnd_dbl_mean = rndp->rnd_dbl_gamma;

	/* de-reference min and round amounts for later use */
	rndp->rnd_vint_min  = avd_get_int(rndp->rnd_min);
	rndp->rnd_vint_round  = avd_get_int(rndp->rnd_round);

	filebench_log(LOG_DEBUG_IMPL,
	    "init random var %s: Mean = %6.0llf, Gamma = %6.3llf, Min = %llu",
	    rndp->rnd_var->var_name, rndp->rnd_dbl_mean, rndp->rnd_dbl_gamma,
	    (u_longlong_t)rndp->rnd_vint_min);

	/* initialize distribution to apply */
	switch (rndp->rnd_type & RAND_TYPE_MASK) {
	case RAND_TYPE_UNIFORM:
		rndp->rnd_get = rand_uniform_get;
		break;

	case RAND_TYPE_GAMMA:
		rndp->rnd_get = rand_gamma_get;
		break;

	case RAND_TYPE_TABLE:
		rndp->rnd_get = rand_table_get;
		break;

	default:
		filebench_log(LOG_DEBUG_IMPL, "Random Type not Specified");
		filebench_shutdown(1);
		return;
	}

	/* initialize source of random numbers */
	if (rndp->rnd_type & RAND_SRC_GENERATOR) {
		rndp->rnd_src = rand_src_rand48;
		rand_seed_set(rndp);
	} else {
		rndp->rnd_src = rand_src_urandom;
	}

	/* any random distribution table to convert? */
	if ((rdte_hdp = rndp->rnd_probtabs) == NULL)
		return;

	/* determine random distribution max and mins and initialize table */
	pteidx = 0;
	tablemean = 0.0;
	for (ptep = rdte_hdp; ptep; ptep = ptep->pte_next) {
		double	dmin, dmax;
		int	entcnt;

		dmax = (double)avd_get_int(ptep->pte_segmax);
		dmin = (double)avd_get_int(ptep->pte_segmin);

		/* initialize table minimum on first pass */
		if (pteidx == 0)
			tablemin = dmin;

		/* update table minimum */
		if (tablemin > dmin)
			tablemin = dmin;

		entcnt = (int)avd_get_int(ptep->pte_percent);
		tablemean += (((dmin + dmax)/2.0) * (double)entcnt);

		/* populate the lookup table */

		for (; entcnt > 0; entcnt--) {
			rndp->rnd_rft[pteidx].rf_base = dmin;
			rndp->rnd_rft[pteidx].rf_range = dmax - dmin;
			pteidx++;
		}
	}

	/* check to see if probability equals 100% */
	if (pteidx != PF_TAB_SIZE)
		filebench_log(LOG_ERROR,
		    "Prob table only totals %d%%", pteidx);

	/* If table is not supplied with a mean value, set it to table mean */
	if (rndp->rnd_dbl_mean == 0.0)
		rndp->rnd_dbl_mean = (double)tablemean / (double)PF_TAB_SIZE;

	/* now normalize the entries for a min value of 0, mean of 1 */
	tablemean = (tablemean / 100.0) - tablemin;

	/* special case if really a constant value */
	if (tablemean == 0.0) {
		for (pteidx = 0; pteidx < PF_TAB_SIZE; pteidx++) {
			rndp->rnd_rft[pteidx].rf_base = 0.0;
			rndp->rnd_rft[pteidx].rf_range = 0.0;
		}
		return;
	}

	for (pteidx = 0; pteidx < PF_TAB_SIZE; pteidx++) {

		rndp->rnd_rft[pteidx].rf_base =
		    ((rndp->rnd_rft[pteidx].rf_base - tablemin) / tablemean);
		rndp->rnd_rft[pteidx].rf_range =
		    (rndp->rnd_rft[pteidx].rf_range / tablemean);
	}
}
Ejemplo n.º 19
0
/*
 * The final initialization and main execution loop for the
 * worker threads. Sets threadflow and flowop start times,
 * waits for all process to start, then creates the runtime
 * flowops from those defined by the F language workload
 * script. It does some more initialization, then enters a
 * loop to repeatedly execute the flowops on the flowop list
 * until an abort condition is detected, at which time it exits.
 * This is the starting routine for the new worker thread
 * created by threadflow_createthread(), and is not currently
 * called from anywhere else.
 */
void
flowop_start(threadflow_t *threadflow)
{
	flowop_t *flowop;
	size_t memsize;
	int ret = FILEBENCH_OK;

	set_thread_ioprio(threadflow);

#ifdef HAVE_PROC_PID_LWP
	char procname[128];
	long ctl[2] = {PCSET, PR_MSACCT};
	int pfd;

	(void) snprintf(procname, sizeof (procname),
	    "/proc/%d/lwp/%d/lwpctl", (int)my_pid, _lwp_self());
	pfd = open(procname, O_WRONLY);
	(void) pwrite(pfd, &ctl, sizeof (ctl), 0);
	(void) close(pfd);
#endif

	(void) ipc_mutex_lock(&controlstats_lock);
	if (!controlstats_zeroed) {
		(void) memset(&controlstats, 0, sizeof (controlstats));
		controlstats_zeroed = 1;
	}
	(void) ipc_mutex_unlock(&controlstats_lock);

	flowop = threadflow->tf_thrd_fops;

	/* Hold the flowop find lock as reader to prevent lookups */
	(void) pthread_rwlock_rdlock(&filebench_shm->shm_flowop_find_lock);

	/* Create the runtime flowops from those defined by the script */
	(void) ipc_mutex_lock(&filebench_shm->shm_flowop_lock);
	if (flowop_create_runtime_flowops(threadflow, &threadflow->tf_thrd_fops)
	    != FILEBENCH_OK) {
		(void) ipc_mutex_unlock(&filebench_shm->shm_flowop_lock);
		filebench_shutdown(1);
		return;
	}
	(void) ipc_mutex_unlock(&filebench_shm->shm_flowop_lock);

	/* Release the find lock as reader to allow lookups */
	(void) pthread_rwlock_unlock(&filebench_shm->shm_flowop_find_lock);

	/* Set to the start of the new flowop list */
	flowop = threadflow->tf_thrd_fops;

	memsize = (size_t)threadflow->tf_constmemsize;

	/* If we are going to use ISM, allocate later */
	if (threadflow->tf_attrs & THREADFLOW_USEISM) {
		threadflow->tf_mem =
		    ipc_ismmalloc(memsize);
	} else {
		threadflow->tf_mem =
		    malloc(memsize);
	}

	(void) memset(threadflow->tf_mem, 0, memsize);
	filebench_log(LOG_DEBUG_SCRIPT, "Thread allocated %d bytes", memsize);

#ifdef HAVE_LWPS
	filebench_log(LOG_DEBUG_SCRIPT, "Thread %zx (%d) started",
	    threadflow,
	    _lwp_self());
#endif

	/* 
	 * Now we set tf_running flag to indicate to the main process
	 * that the worker thread is running. However, the thread is
	 * still not executing the workload, as it is blocked by the
	 * shm_run_lock. Main thread will release this lock when all
	 * threads set their tf_running flag to 1.
	 */ 
	threadflow->tf_abort = 0;
	threadflow->tf_running = 1;

	/*
	 * Block until all processes have started, acting like
	 * a barrier. The original filebench process initially
	 * holds the run_lock as a reader, preventing any of the
	 * threads from obtaining the writer lock, and hence
	 * passing this point. Once all processes and threads
	 * have been created, the original process unlocks
	 * run_lock, allowing each waiting thread to lock
	 * and then immediately unlock it, then begin running.
	 */
	(void) pthread_rwlock_wrlock(&filebench_shm->shm_run_lock);
	(void) pthread_rwlock_unlock(&filebench_shm->shm_run_lock);

	/* Main filebench worker loop */
	while (ret == FILEBENCH_OK) {
		int i, count;

		/* Abort if asked */
		if (threadflow->tf_abort || filebench_shm->shm_f_abort)
			break;

		/* Be quiet while stats are gathered */
		if (filebench_shm->shm_bequiet) {
			(void) sleep(1);
			continue;
		}

		/* Take it easy until everyone is ready to go */
		if (!filebench_shm->shm_procs_running) {
			(void) sleep(1);
			continue;
		}

		if (flowop == NULL) {
			filebench_log(LOG_ERROR, "flowop_read null flowop");
			return;
		}

		/* Execute the flowop for fo_iters times */
		count = (int)avd_get_int(flowop->fo_iters);
		for (i = 0; i < count; i++) {

			filebench_log(LOG_DEBUG_SCRIPT, "%s: executing flowop "
			    "%s-%d", threadflow->tf_name, flowop->fo_name,
			    flowop->fo_instance);

			ret = (*flowop->fo_func)(threadflow, flowop);

			/*
			 * Return value FILEBENCH_ERROR means "flowop
			 * failed, stop the filebench run"
			 */
			if (ret == FILEBENCH_ERROR) {
				filebench_log(LOG_ERROR,
				    "%s-%d: flowop %s-%d failed",
				    threadflow->tf_name,
				    threadflow->tf_instance,
				    flowop->fo_name,
				    flowop->fo_instance);
				(void) ipc_mutex_lock(&threadflow->tf_lock);
				threadflow->tf_abort = 1;
				filebench_shm->shm_f_abort =
				    FILEBENCH_ABORT_ERROR;
				(void) ipc_mutex_unlock(&threadflow->tf_lock);
				break;
			}

			/*
			 * Return value of FILEBENCH_NORSC means "stop
			 * the filebench run" if in "end on no work mode",
			 * otherwise it indicates an error
			 */
			if (ret == FILEBENCH_NORSC) {
				(void) ipc_mutex_lock(&threadflow->tf_lock);
				threadflow->tf_abort = FILEBENCH_DONE;
				if (filebench_shm->shm_rmode ==
				    FILEBENCH_MODE_Q1STDONE) {
					filebench_shm->shm_f_abort =
					    FILEBENCH_ABORT_RSRC;
				} else if (filebench_shm->shm_rmode !=
				    FILEBENCH_MODE_QALLDONE) {
					filebench_log(LOG_ERROR1,
					    "WARNING! Run stopped early:\n   "
					    "             flowop %s-%d could "
					    "not obtain a file. Please\n      "
					    "          reduce runtime, "
					    "increase fileset entries "
					    "($nfiles), or switch modes.",
					    flowop->fo_name,
					    flowop->fo_instance);
					filebench_shm->shm_f_abort =
					    FILEBENCH_ABORT_ERROR;
				}
				(void) ipc_mutex_unlock(&threadflow->tf_lock);
				break;
			}

			/*
			 * Return value of FILEBENCH_DONE means "stop
			 * the filebench run without error"
			 */
			if (ret == FILEBENCH_DONE) {
				(void) ipc_mutex_lock(&threadflow->tf_lock);
				threadflow->tf_abort = FILEBENCH_DONE;
				filebench_shm->shm_f_abort =
				    FILEBENCH_ABORT_DONE;
				(void) ipc_mutex_unlock(&threadflow->tf_lock);
				break;
			}

			/*
			 * If we get here and the return is something other
			 * than FILEBENCH_OK, it means a spurious code
			 * was returned, so treat as major error. This
			 * probably indicates a bug in the flowop.
			 */
			if (ret != FILEBENCH_OK) {
				filebench_log(LOG_ERROR,
				    "Flowop %s unexpected return value = %d\n",
				    flowop->fo_name, ret);
				filebench_shm->shm_f_abort =
				    FILEBENCH_ABORT_ERROR;
				break;
			}
		}

		/* advance to next flowop */
		flowop = flowop->fo_exec_next;

		/* but if at end of list, start over from the beginning */
		if (flowop == NULL) {
			flowop = threadflow->tf_thrd_fops;
			threadflow->tf_stats.fs_count++;
		}
	}

#ifdef HAVE_LWPS
	filebench_log(LOG_DEBUG_SCRIPT, "Thread %d exiting",
	    _lwp_self());
#endif

	/* Tell flowops to destroy locally acquired state */
	flowop_destruct_all_flows(threadflow);

	pthread_exit(&threadflow->tf_abort);
}
Ejemplo n.º 20
0
/*
 * Given a fileset "fileset", create the associated files as
 * specified in the attributes of the fileset. The fileset is
 * rooted in a directory whose pathname is in fs_path. If the
 * directory exists, meaning that there is already a fileset,
 * and the fs_reuse attribute is false, then remove it and all
 * its contained files and subdirectories. Next, the routine
 * creates a root directory for the fileset. All the file type
 * filesetentries are cycled through creating as needed
 * their containing subdirectory trees in the filesystem and
 * creating actual files for fs_preallocpercent of them. The
 * created files are filled with fse_size bytes of unitialized
 * data. The routine returns -1 on errors, 0 on success.
 */
static int
fileset_create(fileset_t *fileset)
{
	filesetentry_t *entry;
	char path[MAXPATHLEN];
	struct stat64 sb;
	int pickflags = FILESET_PICKUNIQUE | FILESET_PICKRESET;
	hrtime_t start = gethrtime();
	int preallocated = 0;
	int reusing = 0;

	if (*fileset->fs_path == NULL) {
		filebench_log(LOG_ERROR, "%s path not set",
		    fileset_entity_name(fileset));
		return (-1);
	}

#ifdef HAVE_RAW_SUPPORT
	/* treat raw device as special case */
	if (fileset->fs_attrs & FILESET_IS_RAW_DEV)
		return (0);
#endif /* HAVE_RAW_SUPPORT */

	/* XXX Add check to see if there is enough space */

	/* Remove existing */
	(void) strcpy(path, *fileset->fs_path);
	(void) strcat(path, "/");
	(void) strcat(path, fileset->fs_name);
	if ((stat64(path, &sb) == 0) && (strlen(path) > 3) &&
	    (strlen(*fileset->fs_path) > 2)) {
		if (!integer_isset(fileset->fs_reuse)) {
			char cmd[MAXPATHLEN];

			(void) snprintf(cmd, sizeof (cmd), "rm -rf %s", path);
			(void) system(cmd);
			filebench_log(LOG_VERBOSE,
			    "Removed any existing %s %s in %lld seconds",
			    fileset_entity_name(fileset), fileset->fs_name,
			    ((gethrtime() - start) / 1000000000) + 1);
		} else {
			/* we are re-using */
			reusing = 1;
			filebench_log(LOG_VERBOSE,
			    "Re-using %s %s on %s file system.",
			    fileset_entity_name(fileset),
			    fileset->fs_name, sb.st_fstype);
		}
	}
	(void) mkdir(path, 0755);

	/* make the filesets directory tree */
	if (fileset_create_subdirs(fileset, path) == -1)
		return (-1);

	start = gethrtime();

	filebench_log(LOG_VERBOSE, "Creating %s %s...",
	    fileset_entity_name(fileset), fileset->fs_name);

	if (!integer_isset(fileset->fs_prealloc))
		goto exit;

	while (entry = fileset_pick(fileset, pickflags, 0)) {
		int randno;
		pthread_t tid;

		pickflags = FILESET_PICKUNIQUE;

		entry->fse_flags &= ~FSE_EXISTS;

		randno = ((RAND_MAX * (100 - *(fileset->fs_preallocpercent)))
		    / 100);

		/* entry doesn't need to be locked during initialization */
		(void) ipc_mutex_unlock(&entry->fse_lock);

		if (rand() < randno)
			continue;

		preallocated++;

		if (reusing)
			entry->fse_flags |= FSE_REUSING;
		else
			entry->fse_flags &= (~FSE_REUSING);

		if (integer_isset(fileset->fs_paralloc)) {

			/* fire off a separate allocation thread */
			(void) pthread_mutex_lock(&paralloc_lock);
			while (paralloc_count >= MAX_PARALLOC_THREADS) {
				(void) pthread_cond_wait(
				    &paralloc_cv, &paralloc_lock);
			}

			if (paralloc_count < 0) {
				(void) pthread_mutex_unlock(&paralloc_lock);
				return (-1);
			}

			paralloc_count++;
			(void) pthread_mutex_unlock(&paralloc_lock);

			if (pthread_create(&tid, NULL,
			    (void *(*)(void*))fileset_alloc_thread,
			    entry) != 0) {
				filebench_log(LOG_ERROR,
				    "File prealloc thread create failed");
				filebench_shutdown(1);
			}

		} else {
			if (fileset_alloc_file(entry) == -1)
				return (-1);
		}
	}

exit:
	filebench_log(LOG_VERBOSE,
	    "Preallocated %d of %lld of %s %s in %lld seconds",
	    preallocated,
	    *(fileset->fs_entries),
	    fileset_entity_name(fileset),
	    fileset->fs_name,
	    ((gethrtime() - start) / 1000000000) + 1);

	return (0);
}