Exemplo 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);
}
Exemplo n.º 2
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 = 0;

	pid = getpid();

#ifdef HAVE_PROCFS
	if (noproc == 0) {
		char procname[128];
		long ctl[2] = {PCSET, PR_MSACCT};
		int pfd;

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

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

	flowop = threadflow->tf_ops;
	threadflow->tf_stats.fs_stime = gethrtime();
	flowop->fo_stats.fs_stime = gethrtime();

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

	/*
	 * 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->run_lock);
	(void) pthread_rwlock_unlock(&filebench_shm->run_lock);

	/* Create the runtime flowops from those defined by the script */
	(void) ipc_mutex_lock(&filebench_shm->flowop_lock);
	while (flowop) {
		flowop_t *newflowop;

		if (flowop == threadflow->tf_ops)
			threadflow->tf_ops = NULL;
		newflowop = flowop_define_common(threadflow, flowop->fo_name,
		    flowop, 1, 0);
		if (newflowop == NULL)
			return;
		if (flowop_initflow(newflowop) < 0) {
			filebench_log(LOG_ERROR, "Flowop init of %s failed",
			    newflowop->fo_name);
		}
		flowop = flowop->fo_threadnext;
	}
	(void) ipc_mutex_unlock(&filebench_shm->flowop_lock);

	filebench_log(LOG_DEBUG_SCRIPT, "Thread started");

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

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

	threadflow->tf_abort = 0;
	threadflow->tf_running = 1;


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

	if (threadflow->tf_mem == NULL) {
		filebench_log(LOG_ERROR,
			"Thread failed to allocate %zd bytes", 
			threadflow->tf_memsize);
		return;
	}

	memsize = *threadflow->tf_memsize;
	filebench_log(LOG_DEBUG_SCRIPT, "Thread allocated %lld bytes at %llx",
		memsize, threadflow->tf_mem);

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

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

	/* Main filebench worker loop */
	/* CONSTCOND */
	while (1) {
		int i;

		/* Abort if asked */
		if (threadflow->tf_abort || filebench_shm->f_abort) {
			(void) ipc_mutex_lock(&threadflow->tf_lock);
			threadflow->tf_running = 0;
			(void) ipc_mutex_unlock(&threadflow->tf_lock);
			filebench_log(LOG_DEBUG_SCRIPT, 
				"%s: aborting thread %s on request of a flowop",
			    	threadflow->tf_name);
			break;
		}

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

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

		if (flowop->fo_stats.fs_stime == 0)
			flowop->fo_stats.fs_stime = gethrtime();

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

		if (threadflow->tf_memsize == 0) {
			filebench_log(LOG_ERROR,
			    "Zero memory size for thread %s",
			    threadflow->tf_name);
			return;
		}

		/* Execute the flowop for fo_iters times */
		for (i = 0; i < *flowop->fo_iters; 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);
			filebench_log(LOG_DEBUG_SCRIPT, "%s: finished flowop "
			    "%s-%d", threadflow->tf_name, flowop->fo_name,
			    flowop->fo_instance);

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

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

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

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

	pthread_exit(&ret);
}