示例#1
0
/*
 * Allocates filebench objects from pre allocated region of
 * shareable memory. The memory region is partitioned into sets
 * of objects during initialization. This routine scans for
 * the first unallocated object of type "type" in the set of
 * available objects, and makes it as allocated. The routine
 * returns a pointer to the object, or NULL if all objects have
 * been allocated.
 */
void *
ipc_malloc(int obj_type)
{
	int start_idx;
	int max_idx;
	int i;

	(void) ipc_mutex_lock(&filebench_shm->shm_malloc_lock);

	start_idx = filebench_shm->shm_lastbitmapindex[obj_type];
	max_idx = preallocated_entries(obj_type) - 1;

	i = start_idx;
	do {
		i++;
		if (i > max_idx)
			i = 0;

		if (filebench_shm->shm_bitmap[obj_type][i] == 0)
			break;
	} while (i != start_idx);

	if (i == start_idx) {
		filebench_log(LOG_ERROR, "Out of shared memory (%d)!", obj_type);
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return (NULL);
	}

	filebench_shm->shm_bitmap[obj_type][i] = 1;
	filebench_shm->shm_lastbitmapindex[obj_type] = i;

	switch (obj_type) {
	case FILEBENCH_FILESET:
		(void) memset((char *)&filebench_shm->shm_fileset[i], 0,
		    sizeof (fileset_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_fileset[i]);

	case FILEBENCH_POSSET:
		(void) memset((char *)&filebench_shm->shm_posset[i], 0,
		    sizeof (struct posset));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_posset[i]);

	case FILEBENCH_FILESETENTRY:
		(void) memset((char *)&filebench_shm->shm_filesetentry[i], 0,
		    sizeof (filesetentry_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_filesetentry[i]);

	case FILEBENCH_PROCFLOW:
		(void) memset((char *)&filebench_shm->shm_procflow[i], 0,
		    sizeof (procflow_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_procflow[i]);

	case FILEBENCH_THREADFLOW:
		(void) memset((char *)&filebench_shm->shm_threadflow[i], 0,
		    sizeof (threadflow_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_threadflow[i]);

	case FILEBENCH_FLOWOP:
		(void) memset((char *)&filebench_shm->shm_flowop[i], 0,
		    sizeof (flowop_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_flowop[i]);

	case FILEBENCH_VARIABLE:
		(void) memset((char *)&filebench_shm->shm_var[i], 0,
		    sizeof (var_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_var[i]);

	case FILEBENCH_AVD:
		filebench_shm->shm_avd_ptrs[i].avd_type = AVD_INVALID;
		filebench_shm->shm_avd_ptrs[i].avd_val.varptr = NULL;
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_avd_ptrs[i]);

	case FILEBENCH_RANDDIST:
		(void) memset((char *)&filebench_shm->shm_randdist[i], 0,
		    sizeof (randdist_t));
		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
		return ((char *)&filebench_shm->shm_randdist[i]);

	}

	filebench_log(LOG_ERROR, "Attempt to ipc_malloc unknown object type (%d)!",
	    obj_type);
	(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
	return (NULL);
}
示例#2
0
/*
 * Frees a filebench object of type "type" at the location
 * pointed to by "addr". It uses the type and address to
 * calculate which object is being freed, and clears its
 * allocation map entry.
 */
void
ipc_free(int type, char *addr)
{
	int item;
	caddr_t base = 0;
	size_t offset;
	size_t size = 0;

	if (addr == NULL) {
		filebench_log(LOG_ERROR, "Freeing type %d %zx", type, addr);
		return;
	}

	switch (type) {

	case FILEBENCH_FILESET:
		base = (caddr_t)&filebench_shm->shm_fileset[0];
		size = sizeof (fileset_t);
		break;

	case FILEBENCH_FILESETENTRY:
		base = (caddr_t)&filebench_shm->shm_filesetentry[0];
		size = sizeof (filesetentry_t);
		break;

	case FILEBENCH_POSSET:
		base = (caddr_t)&filebench_shm->shm_posset[0];
		size = sizeof (struct posset);
		break;

	case FILEBENCH_PROCFLOW:
		base = (caddr_t)&filebench_shm->shm_procflow[0];
		size = sizeof (procflow_t);
		break;

	case FILEBENCH_THREADFLOW:
		base = (caddr_t)&filebench_shm->shm_threadflow[0];
		size = sizeof (threadflow_t);
		break;

	case FILEBENCH_FLOWOP:
		base = (caddr_t)&filebench_shm->shm_flowop[0];
		size = sizeof (flowop_t);
		break;

	case FILEBENCH_VARIABLE:
		base = (caddr_t)&filebench_shm->shm_var[0];
		size = sizeof (var_t);
		break;

	case FILEBENCH_AVD:
		base = (caddr_t)&filebench_shm->shm_avd_ptrs[0];
		size = sizeof (avd_t);
		break;

	case FILEBENCH_RANDDIST:
		base = (caddr_t)&filebench_shm->shm_randdist[0];
		size = sizeof (randdist_t);
		break;

	}

	offset = ((size_t)addr - (size_t)base);
	item = offset / size;

	(void) ipc_mutex_lock(&filebench_shm->shm_malloc_lock);
	filebench_shm->shm_bitmap[type][item] = 0;
	(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
}
示例#3
0
文件: ipc.c 项目: alhazred/onarm
/*
 * Frees a filebench object of type "type" at the location
 * pointed to by "addr". It uses the type and address to
 * calculate which object is being freed, and clears its
 * allocation map entry.
 */
void
ipc_free(int type, char *addr)
{
	int item;
	caddr_t base;
	size_t offset;
	size_t size;

	if (addr == NULL) {
		filebench_log(LOG_ERROR, "Freeing type %d %zx", type, addr);
		return;
	}

	switch (type) {

	case FILEBENCH_FILESET:
		base = (caddr_t)&filebench_shm->fileset[0];
		size = sizeof (fileset_t);
		break;

	case FILEBENCH_FILESETENTRY:
		base = (caddr_t)&filebench_shm->filesetentry[0];
		size = sizeof (filesetentry_t);
		break;

	case FILEBENCH_PROCFLOW:
		base = (caddr_t)&filebench_shm->procflow[0];
		size = sizeof (procflow_t);
		break;

	case FILEBENCH_THREADFLOW:
		base = (caddr_t)&filebench_shm->threadflow[0];
		size = sizeof (threadflow_t);
		break;

	case FILEBENCH_FLOWOP:
		base = (caddr_t)&filebench_shm->flowop[0];
		size = sizeof (flowop_t);
		break;

	case FILEBENCH_INTEGER:
		base = (caddr_t)&filebench_shm->integer_ptrs[0];
		size = sizeof (caddr_t);
		break;

	case FILEBENCH_STRING:
		base = (caddr_t)&filebench_shm->string_ptrs[0];
		size = sizeof (caddr_t);
		break;

	case FILEBENCH_VARIABLE:
		base = (caddr_t)&filebench_shm->var[0];
		size = sizeof (var_t);
		break;
	}

	offset = ((size_t)addr - (size_t)base);
	item = offset / size;

	(void) ipc_mutex_lock(&filebench_shm->malloc_lock);
	filebench_shm->bitmap[type][item] = 0;
	(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
}
示例#4
0
/*
 * Initialize the Interprocess Communication system and its associated shared
 * memory structure. It first creates a temporary file using the mkstemp()
 * function. It than sets the file large enough to hold the filebench_shm and an
 * additional megabyte.  (Additional megabyte is required to make sure that all
 * sizeof(filebench_shm) bytes plus page alignment bytes will fit in the file.)
 * The file is then memory mapped. Once the shared memory region is created,
 * ipc_init initializes various locks, pointers, and variables in the shared
 * memory. It also uses ftok() to get a shared memory semaphore key for later
 * use in allocating shared semaphores.
 */
void ipc_init(void)
{
	int shmfd;
	char tmpbuf[MB];
	key_t key;
#ifdef HAVE_SEM_RMID
	int sys_semid;
#endif

	shmfd = mkstemp(shmpath);
	if (shmfd  < 0) {
		filebench_log(LOG_FATAL, "Could not create shared memory "
			      "file %s: %s", shmpath, strerror(errno));
		exit(1);
	}

	(void)lseek(shmfd, sizeof(filebench_shm_t), SEEK_SET);
	if (write(shmfd, tmpbuf, MB) != MB) {
		filebench_log(LOG_FATAL,
		    "Could not write to the shared memory "
		    "file: %s", strerror(errno));
		exit(1);
	}

	if ((filebench_shm = (filebench_shm_t *)mmap(NULL,
	    sizeof(filebench_shm_t), PROT_READ | PROT_WRITE,
	    MAP_SHARED, shmfd, 0)) == MAP_FAILED) {
		filebench_log(LOG_FATAL, "Could not mmap the shared "
		"memory file: %s", strerror(errno));
		exit(1);
	}

	(void) memset(filebench_shm, 0,
		 (char *)&filebench_shm->shm_marker - (char *)filebench_shm);

	/*
	 * First, initialize all the structures needed for the filebench_log()
	 * function to work correctly with the log levels other than LOG_FATAL
	 */
	filebench_shm->shm_epoch = gethrtime();
	filebench_shm->shm_debug_level = LOG_VERBOSE;

	/* Setup mutexes for object lists */
	ipc_mutexattr_init(IPC_MUTEX_NORMAL);
	ipc_mutexattr_init(IPC_MUTEX_PRIORITY);
	ipc_mutexattr_init(IPC_MUTEX_ROBUST);
	ipc_mutexattr_init(IPC_MUTEX_PRI_ROB);

	(void) pthread_mutex_init(&filebench_shm->shm_msg_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));

	filebench_log(LOG_INFO, "Allocated %lldMB of shared memory",
			(sizeof(filebench_shm_t) + MB) / MB);

	filebench_shm->shm_rmode = FILEBENCH_MODE_TIMEOUT;
	filebench_shm->shm_string_ptr = &filebench_shm->shm_strings[0];
	filebench_shm->shm_ptr = (char *)filebench_shm->shm_addr;
	filebench_shm->shm_path_ptr = &filebench_shm->shm_filesetpaths[0];

	(void) pthread_mutex_init(&filebench_shm->shm_fileset_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_posset_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_procflow_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_procs_running_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_threadflow_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_flowop_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_eventgen_lock,
	    ipc_mutexattr(IPC_MUTEX_PRI_ROB));
	(void) pthread_mutex_init(&filebench_shm->shm_malloc_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) pthread_mutex_init(&filebench_shm->shm_ism_lock,
	    ipc_mutexattr(IPC_MUTEX_NORMAL));
	(void) ipc_mutex_lock(&filebench_shm->shm_ism_lock);
	(void) pthread_cond_init(&filebench_shm->shm_eventgen_cv,
	    ipc_condattr());
	(void) pthread_rwlock_init(&filebench_shm->shm_flowop_find_lock,
	    ipc_rwlockattr());
	(void) pthread_rwlock_init(&filebench_shm->shm_run_lock,
	    ipc_rwlockattr());

	/* Create semaphore */
	if ((key = ftok(shmpath, 1)) < 0) {
		filebench_log(LOG_ERROR, "cannot create sem: %s",
		    strerror(errno));
		exit(1);
	}

#ifdef HAVE_SEM_RMID
	if ((sys_semid = semget(key, 0, 0)) != -1)
		(void) semctl(sys_semid, 0, IPC_RMID);
#endif

	filebench_shm->shm_semkey = key;
	filebench_shm->shm_sys_semid = -1;
	filebench_shm->shm_log_fd = -1;
	filebench_shm->shm_dump_fd = -1;
	filebench_shm->shm_eventgen_hz = 0;
	filebench_shm->shm_id = -1;
}
示例#5
0
文件: ipc.c 项目: alhazred/onarm
/*
 * Allocates filebench objects from pre allocated region of
 * shareable memory. The memory region is partitioned into sets
 * of objects during initialization. This routine scans for
 * the first unallocated object of type "type" in the set of
 * available objects, and makes it as allocated. The routine
 * returns a pointer to the object, or NULL if all objects have
 * been allocated.
 */
void *
ipc_malloc(int type)
{
	int i;
	int max = filebench_sizes[type];

	(void) ipc_mutex_lock(&filebench_shm->malloc_lock);

	for (i = 0; i < max; i++) {
		if (filebench_shm->bitmap[type][i] == 0)
			break;
	}

	if (i >= max) {
		filebench_log(LOG_ERROR, "Out of shared memory (%d)!", type);
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return (NULL);
	}

	filebench_shm->bitmap[type][i] = 1;

	switch (type) {
	case FILEBENCH_FILESET:
		(void) memset((char *)&filebench_shm->fileset[i], 0,
		    sizeof (fileset_t));
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->fileset[i]);

	case FILEBENCH_FILESETENTRY:
		(void) memset((char *)&filebench_shm->filesetentry[i], 0,
		    sizeof (filesetentry_t));
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->filesetentry[i]);

	case FILEBENCH_PROCFLOW:
		(void) memset((char *)&filebench_shm->procflow[i], 0,
		    sizeof (procflow_t));
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->procflow[i]);

	case FILEBENCH_THREADFLOW:
		(void) memset((char *)&filebench_shm->threadflow[i], 0,
		    sizeof (threadflow_t));
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->threadflow[i]);

	case FILEBENCH_FLOWOP:
		(void) memset((char *)&filebench_shm->flowop[i], 0,
		    sizeof (flowop_t));
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->flowop[i]);

	case FILEBENCH_INTEGER:
		filebench_shm->integer_ptrs[i] = NULL;
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->integer_ptrs[i]);

	case FILEBENCH_STRING:
		filebench_shm->string_ptrs[i] = NULL;
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->string_ptrs[i]);

	case FILEBENCH_VARIABLE:
		(void) memset((char *)&filebench_shm->var[i], 0,
		    sizeof (var_t));
		(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
		return ((char *)&filebench_shm->var[i]);
	}

	filebench_log(LOG_ERROR, "Attempt to ipc_malloc unknown type (%d)!",
	    type);
	return (NULL);
}
示例#6
0
文件: ipc.c 项目: alhazred/onarm
/*
 * Initialize the Interprocess Communication system and its
 * associated shared memory structure. It first creates a
 * temporary file using either the mkstemp() function or the
 * tempnam() and open() functions. If the process model is in
 * use,it than sets the file large enough to hold the
 * filebench_shm and an additional Megabyte. The file is then
 * memory mapped. If the process model is not in use, it simply
 * mallocs a region of sizeof (filebench_shm_t).
 *
 * Once the shared memory region / file is created, ipc_init
 * initializes various locks pointers, and variables in the
 * shared memory. It also uses ftok() to get a shared memory
 * semaphore key for later use in allocating shared semaphores.
 */
void
ipc_init(void)
{
	filebench_shm_t *buf = malloc(MB);
	key_t key;
	caddr_t c1;
	caddr_t c2;
#ifdef HAVE_SEM_RMID
	int semid;
#endif

#ifdef HAVE_MKSTEMP
	shmpath = (char *)malloc(128);
	(void) strcpy(shmpath, "/var/tmp/fbenchXXXXXX");
	shmfd = mkstemp(shmpath);
#else
	shmfd   = open(shmpath, O_CREAT | O_RDWR | O_TRUNC, 0666);
	shmpath = tempnam("/var/tmp", "fbench");
#endif	/* HAVE_MKSTEMP */

#ifdef USE_PROCESS_MODEL

	if (shmfd  < 0) {
		filebench_log(LOG_FATAL, "Cannot open shm %s: %s",
		    shmpath,
		    strerror(errno));
		exit(1);
	}

	(void) lseek(shmfd, sizeof (filebench_shm_t), SEEK_SET);
	if (write(shmfd, buf, MB) != MB) {
		filebench_log(LOG_FATAL,
		    "Cannot allocate shm: %s", strerror(errno));
		exit(1);
	}

	/* LINTED E_BAD_PTR_CAST_ALIGN */
	if ((filebench_shm = (filebench_shm_t *)mmap((caddr_t)0,
	    sizeof (filebench_shm_t), PROT_READ | PROT_WRITE,
	    MAP_SHARED, shmfd, 0)) == NULL) {
		filebench_log(LOG_FATAL, "Cannot mmap shm");
		exit(1);
	}

#else
	if ((filebench_shm =
	    (filebench_shm_t *)malloc(sizeof (filebench_shm_t))) == NULL) {
		filebench_log(LOG_FATAL, "Cannot malloc shm");
		exit(1);
	}
#endif /* USE_PROCESS_MODEL */

	c1 = (caddr_t)filebench_shm;
	c2 = (caddr_t)&filebench_shm->marker;

	(void) memset(filebench_shm, 0, c2 - c1);
	filebench_shm->epoch = gethrtime();
	filebench_shm->debug_level = LOG_VERBOSE;
	filebench_shm->shm_rmode = FILEBENCH_MODE_TIMEOUT;
	filebench_shm->string_ptr = &filebench_shm->strings[0];
	filebench_shm->shm_ptr = (char *)filebench_shm->shm_addr;
	filebench_shm->path_ptr = &filebench_shm->filesetpaths[0];

	/* Setup mutexes for object lists */
	(void) pthread_mutex_init(&filebench_shm->fileset_lock,
	    ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->procflow_lock,
	    ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->threadflow_lock,
	    ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->flowop_lock, ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->msg_lock, ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->eventgen_lock,
	    ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->malloc_lock, ipc_mutexattr());
	(void) pthread_mutex_init(&filebench_shm->ism_lock, ipc_mutexattr());
	(void) pthread_cond_init(&filebench_shm->eventgen_cv, ipc_condattr());
	(void) pthread_rwlock_init(&filebench_shm->flowop_find_lock,
	    ipc_rwlockattr());
	(void) pthread_rwlock_init(&filebench_shm->run_lock, ipc_rwlockattr());
	(void) pthread_rwlock_rdlock(&filebench_shm->run_lock);

	(void) ipc_mutex_lock(&filebench_shm->ism_lock);

	/* Create semaphore */
	if ((key = ftok(shmpath, 1)) < 0) {
		filebench_log(LOG_ERROR, "cannot create sem: %s",
		    strerror(errno));
		exit(1);
	}

#ifdef HAVE_SEM_RMID
	if ((semid = semget(key, 0, 0)) != -1)
		(void) semctl(semid, 0, IPC_RMID);
#endif

	filebench_shm->semkey = key;
	filebench_shm->log_fd = -1;
	filebench_shm->dump_fd = -1;
	filebench_shm->eventgen_hz = 0;
	filebench_shm->shm_id = -1;

	free(buf);
}
示例#7
0
struct posset *
posset_alloc(avd_t name, avd_t type, avd_t seed, avd_t max, avd_t entries)
{
	struct posset *ps;
	int ret;

	ps = (struct posset *)ipc_malloc(FILEBENCH_POSSET);
	if (!ps) {
		filebench_log(LOG_ERROR, "posset_alloc: " 
				"can't malloc posset in IPC region");
		return NULL;
	}

	/* we do not support any possets except "rnd" at the moment */
	if (!strcmp(avd_get_str(type), "rnd")) {
		ps->ps_type = avd_int_alloc(POSSET_TYPE_RND);
	} else if (!strcmp(avd_get_str(type), "collection")) {
		ps->ps_type = avd_int_alloc(POSSET_TYPE_COLLECTION);
	} else {
		filebench_log(LOG_ERROR, "posset_alloc: wrong posset type");
		ipc_free(FILEBENCH_POSSET, (char *)ps);
		return NULL;
	}

	ps->ps_name = name;
	ps->ps_rnd_seed = seed;
	ps->ps_rnd_max = max;
	ps->ps_entries = entries;

	if (avd_get_int(ps->ps_entries) > POSSET_MAX_ENTRIES) {
		filebench_log(LOG_ERROR, "posset_alloc: the number of posset "
							"entries is too high");
		ipc_free(FILEBENCH_POSSET, (char *)ps);
		return NULL;
	}

	/* depending on the posset type generate (or load) positions */
	switch (avd_get_int(ps->ps_type)) {
	case(POSSET_TYPE_RND):
		ret = posset_rnd_fill(ps);
		break;
	case(POSSET_TYPE_COLLECTION):
		ret = posset_collection_fill(ps);
		break;
	default:
		filebench_log(LOG_ERROR, "posset_alloc: wrong posset type");
		ipc_free(FILEBENCH_POSSET, (char *)ps);
		return NULL;
	}

	if (ret < 0) {
		filebench_log(LOG_ERROR, "posset_alloc: could not fill posset");
		ipc_free(FILEBENCH_POSSET, (char *)ps);
		return NULL;
	}

	/* add posset to the global list */
	(void)ipc_mutex_lock(&filebench_shm->shm_posset_lock);
	if (filebench_shm->shm_possetlist == NULL) {
		filebench_shm->shm_possetlist = ps;
		ps->ps_next = NULL;
	} else {
		ps->ps_next = filebench_shm->shm_possetlist;
		filebench_shm->shm_possetlist = ps;
	}
	(void)ipc_mutex_unlock(&filebench_shm->shm_posset_lock);


	return ps;
}
示例#8
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);
	}
}
示例#9
0
/*
 * Create a pool of shared memory to fit the per-thread
 * allocations. Uses shmget() to create a shared memory region
 * of size "size", attaches to it using shmat(), and stores
 * the returned address of the region in filebench_shm->shm_addr.
 * The pool is only created on the first call. The routine
 * returns 0 if successful or the pool already exists,
 * -1 otherwise.
 */
int
ipc_ismcreate(size_t size)
{
#ifdef HAVE_SHM_SHARE_MMU
	int flag = SHM_SHARE_MMU;
#else
	int flag = 0;
#endif /* HAVE_SHM_SHARE_MMU */

	int tmp_shmid;

	/* Already done? */
	if (filebench_shm->shm_id != -1)
		return (0);

	filebench_log(LOG_VERBOSE,
	    "Creating %zd bytes of ISM Shared Memory...", size);

	/* 
	 * We map a temp shared memory in place to force a gap
         * above any heap/anon allocations, to ensure we can
	 * remap the shm at the same address in the slave procs
	 *
	 */
	if ((tmp_shmid =
	    shmget(0, 1048576, IPC_CREAT | 0666)) == -1) {
		filebench_log(LOG_ERROR,
		    "Failed to create %zd bytes of ISM shared memory", 1048576);
		return (-1);
	}

	if ((filebench_shm->shm_addr = 
		(caddr_t)shmat(tmp_shmid, 0, flag)) == (void *)-1) {
		filebench_log(LOG_ERROR,
		    "Failed to attach %zd bytes of created ISM shared memory, id %lld",
		    filebench_shm->shm_id, size);
		return (-1);
	}

	if ((filebench_shm->shm_id =
	    shmget(0, size, IPC_CREAT | 0666)) == -1) {
		filebench_log(LOG_ERROR,
		    "Failed to create %zd bytes of ISM shared memory", size);
		return (-1);
	}

	/* Remove the temp shm */
	(void) shmctl(tmp_shmid, IPC_RMID, 0);

	if ((filebench_shm->shm_addr = (caddr_t)shmat(filebench_shm->shm_id,
	    0, flag)) == (void *)-1) {
		filebench_log(LOG_ERROR,
		    "Failed to attach %zd bytes of created ISM shared memory, id %lld",
		    size, filebench_shm->shm_id);
		return (-1);
	}

	filebench_shm->shm_ptr = (char *)filebench_shm->shm_addr;

	filebench_log(LOG_VERBOSE,
	    "Allocated %zd bytes of ISM Shared Memory... at %zx, id %zd",
	    size, filebench_shm->shm_addr, filebench_shm->shm_id);

	/* Locked until allocated to block allocs */
	(void) ipc_mutex_unlock(&filebench_shm->ism_lock);

	return (0);
}