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  6084  aw148015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  5184  ek110237  * Use is subject to license terms.
     24  5184  ek110237  */
     25  5184  ek110237 
     26  5184  ek110237 #include "config.h"
     27  5184  ek110237 
     28  5184  ek110237 #include <stdio.h>
     29  5184  ek110237 #include <fcntl.h>
     30  5184  ek110237 #include <sys/mman.h>
     31  5184  ek110237 #include <sys/ipc.h>
     32  5184  ek110237 #include <sys/sem.h>
     33  5184  ek110237 #include <sys/errno.h>
     34  5184  ek110237 #include <signal.h>
     35  5184  ek110237 #include <pthread.h>
     36  5184  ek110237 #include <sys/shm.h>
     37  5184  ek110237 #include "filebench.h"
     38  5184  ek110237 
     39  5184  ek110237 /* IPC Hub and Simple memory allocator */
     40  5184  ek110237 
     41  5184  ek110237 static int shmfd;
     42  5184  ek110237 filebench_shm_t *filebench_shm = NULL;
     43  5184  ek110237 
     44  5184  ek110237 /*
     45  5184  ek110237  * Interprocess Communication mechanisms. If multiple processes
     46  5184  ek110237  * are used, filebench opens a shared file in memory mapped mode to hold
     47  5184  ek110237  * a variety of global variables and data structures. If only using
     48  5184  ek110237  * multiple threads, it just allocates a region of local memory. A
     49  5184  ek110237  * region of interprocess shared memory and a set of shared semaphores
     50  5184  ek110237  * are also created. Routines are provided to manage the creation,
     51  5184  ek110237  * destruction, and allocation of these resoures.
     52  5184  ek110237  */
     53  5184  ek110237 
     54  5184  ek110237 
     55  5184  ek110237 /*
     56  5184  ek110237  * Locks a mutex and logs any errors.
     57  5184  ek110237  */
     58  5184  ek110237 int
     59  5184  ek110237 ipc_mutex_lock(pthread_mutex_t *mutex)
     60  5184  ek110237 {
     61  5184  ek110237 	int error;
     62  5184  ek110237 
     63  5184  ek110237 	error = pthread_mutex_lock(mutex);
     64  5184  ek110237 
     65  5184  ek110237 #ifdef HAVE_ROBUST_MUTEX
     66  5184  ek110237 	if (error == EOWNERDEAD) {
     67  5184  ek110237 		if (pthread_mutex_consistent_np(mutex) != 0) {
     68  5184  ek110237 			filebench_log(LOG_FATAL, "mutex make consistent "
     69  5184  ek110237 			    "failed: %s", strerror(error));
     70  5184  ek110237 			return (-1);
     71  5184  ek110237 		}
     72  5184  ek110237 		return (0);
     73  5184  ek110237 	}
     74  5184  ek110237 #endif /* HAVE_ROBUST_MUTEX */
     75  5184  ek110237 
     76  5184  ek110237 	if (error != 0) {
     77  5184  ek110237 		filebench_log(LOG_FATAL, "mutex lock failed: %s",
     78  5184  ek110237 		    strerror(error));
     79  5184  ek110237 	}
     80  5184  ek110237 
     81  5184  ek110237 	return (error);
     82  5184  ek110237 }
     83  5184  ek110237 
     84  5184  ek110237 /*
     85  5184  ek110237  * Unlocks a mutex and logs any errors.
     86  5184  ek110237  */
     87  5184  ek110237 int
     88  5184  ek110237 ipc_mutex_unlock(pthread_mutex_t *mutex)
     89  5184  ek110237 {
     90  5184  ek110237 	int error;
     91  5184  ek110237 
     92  5184  ek110237 	error = pthread_mutex_unlock(mutex);
     93  5184  ek110237 
     94  5184  ek110237 #ifdef HAVE_ROBUST_MUTEX
     95  5184  ek110237 	if (error == EOWNERDEAD) {
     96  5184  ek110237 		if (pthread_mutex_consistent_np(mutex) != 0) {
     97  5184  ek110237 			filebench_log(LOG_FATAL, "mutex make consistent "
     98  5184  ek110237 			    "failed: %s", strerror(error));
     99  5184  ek110237 			return (-1);
    100  5184  ek110237 		}
    101  5184  ek110237 		return (0);
    102  5184  ek110237 	}
    103  5184  ek110237 #endif /* HAVE_ROBUST_MUTEX */
    104  5184  ek110237 
    105  5184  ek110237 	if (error != 0) {
    106  5184  ek110237 		filebench_log(LOG_FATAL, "mutex unlock failed: %s",
    107  5184  ek110237 		    strerror(error));
    108  5184  ek110237 	}
    109  5184  ek110237 
    110  5184  ek110237 	return (error);
    111  5184  ek110237 }
    112  5184  ek110237 
    113  5184  ek110237 /*
    114  7556    Andrew  * Initialize mutex attributes for the various flavors of mutexes
    115  7556    Andrew  */
    116  7556    Andrew static void
    117  7556    Andrew ipc_mutexattr_init(int mtx_type)
    118  7556    Andrew {
    119  7556    Andrew 	pthread_mutexattr_t *mtx_attrp;
    120  7556    Andrew 
    121  7556    Andrew 	mtx_attrp = &(filebench_shm->shm_mutexattr[mtx_type]);
    122  7556    Andrew 
    123  7556    Andrew 	(void) pthread_mutexattr_init(mtx_attrp);
    124  7556    Andrew 
    125  7556    Andrew #ifdef USE_PROCESS_MODEL
    126  7556    Andrew #ifdef HAVE_PROCSCOPE_PTHREADS
    127  7556    Andrew 	if (pthread_mutexattr_setpshared(mtx_attrp,
    128  7556    Andrew 	    PTHREAD_PROCESS_SHARED) != 0) {
    129  7556    Andrew 		filebench_log(LOG_ERROR, "cannot set mutex attr "
    130  7556    Andrew 		    "PROCESS_SHARED on this platform");
    131  7556    Andrew 		filebench_shutdown(1);
    132  7556    Andrew 	}
    133  7556    Andrew #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
    134  7556    Andrew 	if (mtx_type & IPC_MUTEX_PRIORITY) {
    135  7556    Andrew 		if (pthread_mutexattr_setprotocol(mtx_attrp,
    136  7556    Andrew 		    PTHREAD_PRIO_INHERIT) != 0) {
    137  7556    Andrew 			filebench_log(LOG_ERROR,
    138  7556    Andrew 			    "cannot set mutex attr "
    139  7556    Andrew 			    "PTHREAD_PRIO_INHERIT on this platform");
    140  7556    Andrew 			filebench_shutdown(1);
    141  7556    Andrew 		}
    142  7556    Andrew 	}
    143  7556    Andrew #endif /* HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL */
    144  7556    Andrew #endif /* HAVE_PROCSCOPE_PTHREADS */
    145  7556    Andrew #ifdef HAVE_ROBUST_MUTEX
    146  7556    Andrew 	if (mtx_type & IPC_MUTEX_ROBUST) {
    147  7556    Andrew 		if (pthread_mutexattr_setrobust_np(mtx_attrp,
    148  7556    Andrew 		    PTHREAD_MUTEX_ROBUST_NP) != 0) {
    149  7556    Andrew 			filebench_log(LOG_ERROR,
    150  7556    Andrew 			    "cannot set mutex attr "
    151  7556    Andrew 			    "PTHREAD_MUTEX_ROBUST_NP on this platform");
    152  7556    Andrew 			filebench_shutdown(1);
    153  7556    Andrew 		}
    154  7556    Andrew 		if (pthread_mutexattr_settype(mtx_attrp,
    155  7556    Andrew 		    PTHREAD_MUTEX_ERRORCHECK) != 0) {
    156  7556    Andrew 			filebench_log(LOG_ERROR,
    157  7556    Andrew 			    "cannot set mutex attr "
    158  7556    Andrew 			    "PTHREAD_MUTEX_ERRORCHECK "
    159  7556    Andrew 			    "on this platform");
    160  7556    Andrew 			filebench_shutdown(1);
    161  7556    Andrew 		}
    162  7556    Andrew 	}
    163  7556    Andrew #endif /* HAVE_ROBUST_MUTEX */
    164  7556    Andrew #endif /* USE_PROCESS_MODEL */
    165  7556    Andrew }
    166  7556    Andrew 
    167  7556    Andrew /*
    168  5184  ek110237  * On first invocation, allocates a mutex attributes structure
    169  5184  ek110237  * and initializes it with appropriate attributes. In all cases,
    170  5184  ek110237  * returns a pointer to the structure.
    171  5184  ek110237  */
    172  5184  ek110237 pthread_mutexattr_t *
    173  7556    Andrew ipc_mutexattr(int mtx_type)
    174  5184  ek110237 {
    175  7556    Andrew 	if ((mtx_type >= IPC_NUM_MUTEX_ATTRS) ||
    176  7556    Andrew 	    (mtx_type < IPC_MUTEX_NORMAL)) {
    177  7556    Andrew 		filebench_log(LOG_ERROR,
    178  7556    Andrew 		    "ipc_mutexattr called with undefined attr selector %d",
    179  7556    Andrew 		    mtx_type);
    180  7556    Andrew 		return (&(filebench_shm->shm_mutexattr[IPC_MUTEX_NORMAL]));
    181  7556    Andrew 	}
    182  5184  ek110237 
    183  7556    Andrew 	return (&(filebench_shm->shm_mutexattr[mtx_type]));
    184  5184  ek110237 }
    185  5184  ek110237 
    186  5184  ek110237 static pthread_condattr_t *condattr = NULL;
    187  5184  ek110237 
    188  5184  ek110237 /*
    189  5184  ek110237  * On first invocation, allocates a condition variable attributes
    190  5184  ek110237  * structure and initializes it with appropriate attributes. In
    191  5184  ek110237  * all cases, returns a pointer to the structure.
    192  5184  ek110237  */
    193  5184  ek110237 pthread_condattr_t *
    194  5184  ek110237 ipc_condattr(void)
    195  5184  ek110237 {
    196  5184  ek110237 #ifdef USE_PROCESS_MODEL
    197  5184  ek110237 	if (condattr == NULL) {
    198  5184  ek110237 		if ((condattr = malloc(sizeof (pthread_condattr_t))) == NULL) {
    199  5184  ek110237 			filebench_log(LOG_ERROR, "cannot alloc cond attr");
    200  5184  ek110237 			filebench_shutdown(1);
    201  5184  ek110237 		}
    202  5184  ek110237 #ifdef HAVE_PROCSCOPE_PTHREADS
    203  5184  ek110237 		(void) pthread_condattr_init(condattr);
    204  5184  ek110237 		if (pthread_condattr_setpshared(condattr,
    205  5184  ek110237 		    PTHREAD_PROCESS_SHARED) != 0) {
    206  5184  ek110237 			filebench_log(LOG_ERROR,
    207  5184  ek110237 			    "cannot set cond attr PROCESS_SHARED");
    208  5184  ek110237 			filebench_shutdown(1);
    209  5184  ek110237 		}
    210  5184  ek110237 #endif /* HAVE_PROCSCOPE_PTHREADS */
    211  5184  ek110237 	}
    212  5184  ek110237 #endif /* USE_PROCESS_MODEL */
    213  5184  ek110237 	return (condattr);
    214  5184  ek110237 }
    215  5184  ek110237 
    216  5184  ek110237 static pthread_rwlockattr_t *rwlockattr = NULL;
    217  5184  ek110237 
    218  5184  ek110237 /*
    219  5184  ek110237  * On first invocation, allocates a readers/writers attributes
    220  5184  ek110237  * structure and initializes it with appropriate attributes.
    221  5184  ek110237  * In all cases, returns a pointer to the structure.
    222  5184  ek110237  */
    223  5184  ek110237 static pthread_rwlockattr_t *
    224  5184  ek110237 ipc_rwlockattr(void)
    225  5184  ek110237 {
    226  5184  ek110237 #ifdef USE_PROCESS_MODEL
    227  5184  ek110237 	if (rwlockattr == NULL) {
    228  5184  ek110237 		if ((rwlockattr =
    229  5184  ek110237 		    malloc(sizeof (pthread_rwlockattr_t))) == NULL) {
    230  5184  ek110237 			filebench_log(LOG_ERROR, "cannot alloc rwlock attr");
    231  5184  ek110237 			filebench_shutdown(1);
    232  5184  ek110237 		}
    233  5184  ek110237 #ifdef HAVE_PROCSCOPE_PTHREADS
    234  5184  ek110237 		(void) pthread_rwlockattr_init(rwlockattr);
    235  5184  ek110237 		if (pthread_rwlockattr_setpshared(rwlockattr,
    236  5184  ek110237 		    PTHREAD_PROCESS_SHARED) != 0) {
    237  5184  ek110237 			filebench_log(LOG_ERROR,
    238  5184  ek110237 			    "cannot set rwlock attr PROCESS_SHARED");
    239  5184  ek110237 			filebench_shutdown(1);
    240  5184  ek110237 		}
    241  5184  ek110237 #endif /* HAVE_PROCSCOPE_PTHREADS */
    242  5184  ek110237 	}
    243  5184  ek110237 #endif /* USE_PROCESS_MODEL */
    244  5184  ek110237 	return (rwlockattr);
    245  5184  ek110237 }
    246  5184  ek110237 
    247  5184  ek110237 char *shmpath = NULL;
    248  5184  ek110237 
    249  5184  ek110237 /*
    250  5184  ek110237  * Calls semget() to get a set of shared system V semaphores.
    251  5184  ek110237  */
    252  5184  ek110237 void
    253  5184  ek110237 ipc_seminit(void)
    254  5184  ek110237 {
    255  6391  aw148015 	key_t key = filebench_shm->shm_semkey;
    256  6391  aw148015 	int sys_semid;
    257  5184  ek110237 
    258  5184  ek110237 	/* Already done? */
    259  6391  aw148015 	if (filebench_shm->shm_sys_semid >= 0)
    260  5184  ek110237 		return;
    261  5184  ek110237 
    262  6391  aw148015 	if ((sys_semid = semget(key, FILEBENCH_NSEMS, IPC_CREAT |
    263  5184  ek110237 	    S_IRUSR | S_IWUSR)) == -1) {
    264  5184  ek110237 		filebench_log(LOG_ERROR,
    265  5184  ek110237 		    "could not create sysv semaphore set "
    266  5184  ek110237 		    "(need to increase sems?): %s",
    267  5184  ek110237 		    strerror(errno));
    268  6391  aw148015 		filebench_shutdown(1);
    269  5184  ek110237 	}
    270  6391  aw148015 
    271  6391  aw148015 	filebench_shm->shm_sys_semid = sys_semid;
    272  5184  ek110237 }
    273  5184  ek110237 
    274  5184  ek110237 /*
    275  5184  ek110237  * Initialize the Interprocess Communication system and its
    276  5184  ek110237  * associated shared memory structure. It first creates a
    277  5184  ek110237  * temporary file using either the mkstemp() function or the
    278  5184  ek110237  * tempnam() and open() functions. If the process model is in
    279  5184  ek110237  * use,it than sets the file large enough to hold the
    280  5184  ek110237  * filebench_shm and an additional Megabyte. The file is then
    281  5184  ek110237  * memory mapped. If the process model is not in use, it simply
    282  5184  ek110237  * mallocs a region of sizeof (filebench_shm_t).
    283  5184  ek110237  *
    284  5184  ek110237  * Once the shared memory region / file is created, ipc_init
    285  5184  ek110237  * initializes various locks pointers, and variables in the
    286  5184  ek110237  * shared memory. It also uses ftok() to get a shared memory
    287  5184  ek110237  * semaphore key for later use in allocating shared semaphores.
    288  5184  ek110237  */
    289  5184  ek110237 void
    290  5184  ek110237 ipc_init(void)
    291  5184  ek110237 {
    292  5184  ek110237 	filebench_shm_t *buf = malloc(MB);
    293  5184  ek110237 	key_t key;
    294  5184  ek110237 	caddr_t c1;
    295  5184  ek110237 	caddr_t c2;
    296  5184  ek110237 #ifdef HAVE_SEM_RMID
    297  6391  aw148015 	int sys_semid;
    298  5184  ek110237 #endif
    299  5184  ek110237 
    300  5184  ek110237 #ifdef HAVE_MKSTEMP
    301  5184  ek110237 	shmpath = (char *)malloc(128);
    302  5184  ek110237 	(void) strcpy(shmpath, "/var/tmp/fbenchXXXXXX");
    303  5184  ek110237 	shmfd = mkstemp(shmpath);
    304  5184  ek110237 #else
    305  5184  ek110237 	shmfd   = open(shmpath, O_CREAT | O_RDWR | O_TRUNC, 0666);
    306  5184  ek110237 	shmpath = tempnam("/var/tmp", "fbench");
    307  5184  ek110237 #endif	/* HAVE_MKSTEMP */
    308  5184  ek110237 
    309  5184  ek110237 #ifdef USE_PROCESS_MODEL
    310  5184  ek110237 
    311  5184  ek110237 	if (shmfd  < 0) {
    312  5184  ek110237 		filebench_log(LOG_FATAL, "Cannot open shm %s: %s",
    313  5184  ek110237 		    shmpath,
    314  5184  ek110237 		    strerror(errno));
    315  5184  ek110237 		exit(1);
    316  5184  ek110237 	}
    317  5184  ek110237 
    318  5184  ek110237 	(void) lseek(shmfd, sizeof (filebench_shm_t), SEEK_SET);
    319  5184  ek110237 	if (write(shmfd, buf, MB) != MB) {
    320  5184  ek110237 		filebench_log(LOG_FATAL,
    321  5184  ek110237 		    "Cannot allocate shm: %s", strerror(errno));
    322  5184  ek110237 		exit(1);
    323  5184  ek110237 	}
    324  5184  ek110237 
    325  5184  ek110237 	/* LINTED E_BAD_PTR_CAST_ALIGN */
    326  5184  ek110237 	if ((filebench_shm = (filebench_shm_t *)mmap((caddr_t)0,
    327  5673  aw148015 	    sizeof (filebench_shm_t), PROT_READ | PROT_WRITE,
    328  5673  aw148015 	    MAP_SHARED, shmfd, 0)) == NULL) {
    329  5184  ek110237 		filebench_log(LOG_FATAL, "Cannot mmap shm");
    330  5184  ek110237 		exit(1);
    331  5184  ek110237 	}
    332  5184  ek110237 
    333  5184  ek110237 #else
    334  5184  ek110237 	if ((filebench_shm =
    335  5184  ek110237 	    (filebench_shm_t *)malloc(sizeof (filebench_shm_t))) == NULL) {
    336  5184  ek110237 		filebench_log(LOG_FATAL, "Cannot malloc shm");
    337  5184  ek110237 		exit(1);
    338  5184  ek110237 	}
    339  5184  ek110237 #endif /* USE_PROCESS_MODEL */
    340  5184  ek110237 
    341  5184  ek110237 	c1 = (caddr_t)filebench_shm;
    342  6305  aw148015 	c2 = (caddr_t)&filebench_shm->shm_marker;
    343  5184  ek110237 
    344  5184  ek110237 	(void) memset(filebench_shm, 0, c2 - c1);
    345  6391  aw148015 	filebench_shm->shm_epoch = gethrtime();
    346  6391  aw148015 	filebench_shm->shm_debug_level = LOG_VERBOSE;
    347  6084  aw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_TIMEOUT;
    348  6305  aw148015 	filebench_shm->shm_string_ptr = &filebench_shm->shm_strings[0];
    349  5184  ek110237 	filebench_shm->shm_ptr = (char *)filebench_shm->shm_addr;
    350  6305  aw148015 	filebench_shm->shm_path_ptr = &filebench_shm->shm_filesetpaths[0];
    351  5184  ek110237 
    352  5184  ek110237 	/* Setup mutexes for object lists */
    353  7556    Andrew 	ipc_mutexattr_init(IPC_MUTEX_NORMAL);
    354  7556    Andrew 	ipc_mutexattr_init(IPC_MUTEX_PRIORITY);
    355  7556    Andrew 	ipc_mutexattr_init(IPC_MUTEX_ROBUST);
    356  7556    Andrew 	ipc_mutexattr_init(IPC_MUTEX_PRI_ROB);
    357  6391  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_fileset_lock,
    358  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    359  6391  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_procflow_lock,
    360  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    361  6701  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_procs_running_lock,
    362  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    363  6391  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_threadflow_lock,
    364  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    365  6391  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_flowop_lock,
    366  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    367  6391  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_msg_lock,
    368  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    369  6391  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_eventgen_lock,
    370  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_PRI_ROB));
    371  6305  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_malloc_lock,
    372  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    373  6305  aw148015 	(void) pthread_mutex_init(&filebench_shm->shm_ism_lock,
    374  7556    Andrew 	    ipc_mutexattr(IPC_MUTEX_NORMAL));
    375  6391  aw148015 	(void) pthread_cond_init(&filebench_shm->shm_eventgen_cv,
    376  6391  aw148015 	    ipc_condattr());
    377  6391  aw148015 	(void) pthread_rwlock_init(&filebench_shm->shm_flowop_find_lock,
    378  5184  ek110237 	    ipc_rwlockattr());
    379  7556    Andrew #ifdef USE_PROCESS_MODEL
    380  7556    Andrew 	(void) pthread_cond_init(&filebench_shm->shm_procflow_procs_cv,
    381  7556    Andrew 	    ipc_condattr());
    382  7556    Andrew #endif
    383  6391  aw148015 	(void) pthread_rwlock_init(&filebench_shm->shm_run_lock,
    384  6391  aw148015 	    ipc_rwlockattr());
    385  6391  aw148015 	(void) pthread_rwlock_rdlock(&filebench_shm->shm_run_lock);
    386  5184  ek110237 
    387  6305  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_ism_lock);
    388  5184  ek110237 
    389  5184  ek110237 	/* Create semaphore */
    390  5184  ek110237 	if ((key = ftok(shmpath, 1)) < 0) {
    391  5184  ek110237 		filebench_log(LOG_ERROR, "cannot create sem: %s",
    392  5184  ek110237 		    strerror(errno));
    393  5184  ek110237 		exit(1);
    394  5184  ek110237 	}
    395  5184  ek110237 
    396  5184  ek110237 #ifdef HAVE_SEM_RMID
    397  6391  aw148015 	if ((sys_semid = semget(key, 0, 0)) != -1)
    398  6391  aw148015 		(void) semctl(sys_semid, 0, IPC_RMID);
    399  5184  ek110237 #endif
    400  5184  ek110237 
    401  6391  aw148015 	filebench_shm->shm_semkey = key;
    402  6391  aw148015 	filebench_shm->shm_sys_semid = -1;
    403  6391  aw148015 	filebench_shm->shm_log_fd = -1;
    404  6391  aw148015 	filebench_shm->shm_dump_fd = -1;
    405  6391  aw148015 	filebench_shm->shm_eventgen_hz = 0;
    406  5184  ek110237 	filebench_shm->shm_id = -1;
    407  5184  ek110237 
    408  5184  ek110237 	free(buf);
    409  5184  ek110237 }
    410  5184  ek110237 
    411  5184  ek110237 /*
    412  5184  ek110237  * If compiled to use process model, just unlinks the shmpath.
    413  5184  ek110237  * Otherwise a no-op.
    414  5184  ek110237  */
    415  5184  ek110237 void
    416  6750  ek110237 ipc_fini(void)
    417  5184  ek110237 {
    418  5184  ek110237 #ifdef USE_PROCESS_MODEL
    419  5184  ek110237 	(void) unlink(shmpath);
    420  5184  ek110237 #endif /* USE_PROCESS_MODEL */
    421  6750  ek110237 
    422  6750  ek110237 #ifdef HAVE_SEM_RMID
    423  6750  ek110237 	if (filebench_shm->shm_sys_semid != -1) {
    424  6750  ek110237 		(void) semctl(filebench_shm->shm_sys_semid, 0, IPC_RMID);
    425  6750  ek110237 		filebench_shm->shm_sys_semid = -1;
    426  6750  ek110237 	}
    427  6750  ek110237 #endif
    428  5184  ek110237 }
    429  5184  ek110237 
    430  5184  ek110237 /*
    431  5184  ek110237  * Attach to shared memory. Used by worker processes to open
    432  5184  ek110237  * and mmap the shared memory region. If successful, it
    433  5184  ek110237  * initializes the worker process' filebench_shm to point to
    434  5184  ek110237  * the region and returns 0. Otherwise it returns -1.
    435  5184  ek110237  */
    436  5184  ek110237 int
    437  5184  ek110237 ipc_attach(caddr_t shmaddr)
    438  5184  ek110237 {
    439  5184  ek110237 	if ((shmfd = open(shmpath, O_RDWR, 0666)) < 0) {
    440  5184  ek110237 		filebench_log(LOG_ERROR, "Cannot open shm");
    441  5184  ek110237 		return (-1);
    442  5184  ek110237 	}
    443  5184  ek110237 
    444  5184  ek110237 	/* LINTED E_BAD_PTR_CAST_ALIGN */
    445  5184  ek110237 	if ((filebench_shm = (filebench_shm_t *)mmap(shmaddr,
    446  5184  ek110237 	    sizeof (filebench_shm_t), PROT_READ | PROT_WRITE,
    447  5184  ek110237 	    MAP_SHARED | MAP_FIXED, shmfd, 0)) == NULL) {
    448  5184  ek110237 		filebench_log(LOG_ERROR, "Cannot mmap shm");
    449  5184  ek110237 		return (-1);
    450  5184  ek110237 	}
    451  5184  ek110237 
    452  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL, "addr = %zx", filebench_shm);
    453  5184  ek110237 
    454  5184  ek110237 	return (0);
    455  5184  ek110237 }
    456  5184  ek110237 
    457  5184  ek110237 static int filebench_sizes[] = {
    458  6212  aw148015 	FILEBENCH_NPROCFLOWS,		/* number of procflows */
    459  6212  aw148015 	FILEBENCH_NTHREADFLOWS,		/* number of threadflows */
    460  6212  aw148015 	FILEBENCH_NFLOWOPS,		/* number of flowops */
    461  6212  aw148015 	(FILEBENCH_NVARS * 2),		/* number of attribute value dscrs */
    462  6212  aw148015 	FILEBENCH_NVARS,		/* number of variables */
    463  6212  aw148015 	FILEBENCH_NFILESETS,		/* number of filesets */
    464  6212  aw148015 	FILEBENCH_NFILESETENTRIES,	/* number of fileset entries */
    465  6212  aw148015 	FILEBENCH_NRANDDISTS};		/* number of random distributions */
    466  5184  ek110237 
    467  5184  ek110237 /*
    468  5184  ek110237  * Allocates filebench objects from pre allocated region of
    469  5184  ek110237  * shareable memory. The memory region is partitioned into sets
    470  5184  ek110237  * of objects during initialization. This routine scans for
    471  5184  ek110237  * the first unallocated object of type "type" in the set of
    472  5184  ek110237  * available objects, and makes it as allocated. The routine
    473  5184  ek110237  * returns a pointer to the object, or NULL if all objects have
    474  5184  ek110237  * been allocated.
    475  5184  ek110237  */
    476  5184  ek110237 void *
    477  5184  ek110237 ipc_malloc(int type)
    478  5184  ek110237 {
    479  5184  ek110237 	int i;
    480  5184  ek110237 	int max = filebench_sizes[type];
    481  6305  aw148015 	int start_idx = filebench_shm->shm_lastbitmapindex[type];
    482  5184  ek110237 
    483  6305  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_malloc_lock);
    484  5184  ek110237 
    485  6305  aw148015 	i = start_idx;
    486  6305  aw148015 	do {
    487  6305  aw148015 		i++;
    488  6305  aw148015 		if (i >= max)
    489  6305  aw148015 			i = 0;
    490  6305  aw148015 
    491  6305  aw148015 		if (filebench_shm->shm_bitmap[type][i] == 0)
    492  5184  ek110237 			break;
    493  5184  ek110237 
    494  6305  aw148015 	} while (i != start_idx);
    495  6305  aw148015 
    496  6305  aw148015 	if (i == start_idx) {
    497  5184  ek110237 		filebench_log(LOG_ERROR, "Out of shared memory (%d)!", type);
    498  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    499  5184  ek110237 		return (NULL);
    500  5184  ek110237 	}
    501  5184  ek110237 
    502  6305  aw148015 	filebench_shm->shm_bitmap[type][i] = 1;
    503  6305  aw148015 	filebench_shm->shm_lastbitmapindex[type] = i;
    504  5184  ek110237 
    505  5184  ek110237 	switch (type) {
    506  5184  ek110237 	case FILEBENCH_FILESET:
    507  6305  aw148015 		(void) memset((char *)&filebench_shm->shm_fileset[i], 0,
    508  5184  ek110237 		    sizeof (fileset_t));
    509  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    510  6305  aw148015 		return ((char *)&filebench_shm->shm_fileset[i]);
    511  5184  ek110237 
    512  5184  ek110237 	case FILEBENCH_FILESETENTRY:
    513  6305  aw148015 		(void) memset((char *)&filebench_shm->shm_filesetentry[i], 0,
    514  5184  ek110237 		    sizeof (filesetentry_t));
    515  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    516  6305  aw148015 		return ((char *)&filebench_shm->shm_filesetentry[i]);
    517  5184  ek110237 
    518  5184  ek110237 	case FILEBENCH_PROCFLOW:
    519  6305  aw148015 		(void) memset((char *)&filebench_shm->shm_procflow[i], 0,
    520  5184  ek110237 		    sizeof (procflow_t));
    521  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    522  6305  aw148015 		return ((char *)&filebench_shm->shm_procflow[i]);
    523  5184  ek110237 
    524  5184  ek110237 	case FILEBENCH_THREADFLOW:
    525  6305  aw148015 		(void) memset((char *)&filebench_shm->shm_threadflow[i], 0,
    526  5184  ek110237 		    sizeof (threadflow_t));
    527  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    528  6305  aw148015 		return ((char *)&filebench_shm->shm_threadflow[i]);
    529  5184  ek110237 
    530  5184  ek110237 	case FILEBENCH_FLOWOP:
    531  6305  aw148015 		(void) memset((char *)&filebench_shm->shm_flowop[i], 0,
    532  5184  ek110237 		    sizeof (flowop_t));
    533  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    534  6305  aw148015 		return ((char *)&filebench_shm->shm_flowop[i]);
    535  5184  ek110237 
    536  6212  aw148015 	case FILEBENCH_AVD:
    537  6212  aw148015 		filebench_shm->shm_avd_ptrs[i].avd_type = AVD_INVALID;
    538  6212  aw148015 		filebench_shm->shm_avd_ptrs[i].avd_val.varptr = NULL;
    539  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    540  6212  aw148015 		return ((char *)&filebench_shm->shm_avd_ptrs[i]);
    541  5184  ek110237 
    542  5184  ek110237 	case FILEBENCH_VARIABLE:
    543  6305  aw148015 		(void) memset((char *)&filebench_shm->shm_var[i], 0,
    544  5184  ek110237 		    sizeof (var_t));
    545  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    546  6305  aw148015 		return ((char *)&filebench_shm->shm_var[i]);
    547  6212  aw148015 
    548  6212  aw148015 	case FILEBENCH_RANDDIST:
    549  6212  aw148015 		(void) memset((char *)&filebench_shm->shm_randdist[i], 0,
    550  6212  aw148015 		    sizeof (randdist_t));
    551  6305  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    552  6212  aw148015 		return ((char *)&filebench_shm->shm_randdist[i]);
    553  5184  ek110237 	}
    554  5184  ek110237 
    555  5184  ek110237 	filebench_log(LOG_ERROR, "Attempt to ipc_malloc unknown type (%d)!",
    556  5184  ek110237 	    type);
    557  5184  ek110237 	return (NULL);
    558  5184  ek110237 }
    559  5184  ek110237 
    560  5184  ek110237 /*
    561  5184  ek110237  * Frees a filebench object of type "type" at the location
    562  5184  ek110237  * pointed to by "addr". It uses the type and address to
    563  5184  ek110237  * calculate which object is being freed, and clears its
    564  5184  ek110237  * allocation map entry.
    565  5184  ek110237  */
    566  5184  ek110237 void
    567  5184  ek110237 ipc_free(int type, char *addr)
    568  5184  ek110237 {
    569  5184  ek110237 	int item;
    570  5184  ek110237 	caddr_t base;
    571  5184  ek110237 	size_t offset;
    572  5184  ek110237 	size_t size;
    573  5184  ek110237 
    574  5184  ek110237 	if (addr == NULL) {
    575  5184  ek110237 		filebench_log(LOG_ERROR, "Freeing type %d %zx", type, addr);
    576  5184  ek110237 		return;
    577  5184  ek110237 	}
    578  5184  ek110237 
    579  5184  ek110237 	switch (type) {
    580  5184  ek110237 
    581  5184  ek110237 	case FILEBENCH_FILESET:
    582  6305  aw148015 		base = (caddr_t)&filebench_shm->shm_fileset[0];
    583  5184  ek110237 		size = sizeof (fileset_t);
    584  5184  ek110237 		break;
    585  5184  ek110237 
    586  5184  ek110237 	case FILEBENCH_FILESETENTRY:
    587  6305  aw148015 		base = (caddr_t)&filebench_shm->shm_filesetentry[0];
    588  5184  ek110237 		size = sizeof (filesetentry_t);
    589  5184  ek110237 		break;
    590  5184  ek110237 
    591  5184  ek110237 	case FILEBENCH_PROCFLOW:
    592  6305  aw148015 		base = (caddr_t)&filebench_shm->shm_procflow[0];
    593  5184  ek110237 		size = sizeof (procflow_t);
    594  5184  ek110237 		break;
    595  5184  ek110237 
    596  5184  ek110237 	case FILEBENCH_THREADFLOW:
    597  6305  aw148015 		base = (caddr_t)&filebench_shm->shm_threadflow[0];
    598  5184  ek110237 		size = sizeof (threadflow_t);
    599  5184  ek110237 		break;
    600  5184  ek110237 
    601  5184  ek110237 	case FILEBENCH_FLOWOP:
    602  6305  aw148015 		base = (caddr_t)&filebench_shm->shm_flowop[0];
    603  5184  ek110237 		size = sizeof (flowop_t);
    604  5184  ek110237 		break;
    605  5184  ek110237 
    606  6212  aw148015 	case FILEBENCH_AVD:
    607  6212  aw148015 		base = (caddr_t)&filebench_shm->shm_avd_ptrs[0];
    608  6212  aw148015 		size = sizeof (avd_t);
    609  5184  ek110237 		break;
    610  5184  ek110237 
    611  5184  ek110237 	case FILEBENCH_VARIABLE:
    612  6305  aw148015 		base = (caddr_t)&filebench_shm->shm_var[0];
    613  5184  ek110237 		size = sizeof (var_t);
    614  6212  aw148015 		break;
    615  6212  aw148015 
    616  6212  aw148015 	case FILEBENCH_RANDDIST:
    617  6212  aw148015 		base = (caddr_t)&filebench_shm->shm_randdist[0];
    618  6212  aw148015 		size = sizeof (randdist_t);
    619  5184  ek110237 		break;
    620  5184  ek110237 	}
    621  5184  ek110237 
    622  5184  ek110237 	offset = ((size_t)addr - (size_t)base);
    623  5184  ek110237 	item = offset / size;
    624  5184  ek110237 
    625  6305  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_malloc_lock);
    626  6305  aw148015 	filebench_shm->shm_bitmap[type][item] = 0;
    627  6305  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_malloc_lock);
    628  5184  ek110237 }
    629  5184  ek110237 
    630  5184  ek110237 /*
    631  5184  ek110237  * Allocate a string from filebench string memory. The length
    632  5184  ek110237  * of the allocated string is the same as the length of the
    633  5184  ek110237  * supplied string "string", and the contents of string are
    634  5184  ek110237  * copied to the newly allocated string.
    635  5184  ek110237  */
    636  5184  ek110237 char *
    637  5184  ek110237 ipc_stralloc(char *string)
    638  5184  ek110237 {
    639  6305  aw148015 	char *allocstr = filebench_shm->shm_string_ptr;
    640  5184  ek110237 
    641  6305  aw148015 	filebench_shm->shm_string_ptr += strlen(string) + 1;
    642  5184  ek110237 
    643  6305  aw148015 	if ((filebench_shm->shm_string_ptr - &filebench_shm->shm_strings[0]) >
    644  5184  ek110237 	    FILEBENCH_STRINGMEMORY) {
    645  5184  ek110237 		filebench_log(LOG_ERROR, "Out of ipc string memory");
    646  5184  ek110237 		return (NULL);
    647  5184  ek110237 	}
    648  5184  ek110237 
    649  5184  ek110237 	(void) strncpy(allocstr, string, strlen(string));
    650  5184  ek110237 
    651  5184  ek110237 	return (allocstr);
    652  5184  ek110237 }
    653  5184  ek110237 
    654  5184  ek110237 /*
    655  5184  ek110237  * Allocate a path string from filebench path string memory.
    656  5184  ek110237  * Specifically used for allocating fileset paths. The length
    657  5184  ek110237  * of the allocated path string is the same as the length of
    658  5184  ek110237  * the supplied path string "path", and the contents of path
    659  5184  ek110237  * are copied to the newly allocated path string. Checks for
    660  5184  ek110237  * out-of-path-string-memory condition and returns NULL if so.
    661  5184  ek110237  * Otherwise it returns a pointer to the newly allocated path
    662  5184  ek110237  * string.
    663  5184  ek110237  */
    664  5184  ek110237 char *
    665  5184  ek110237 ipc_pathalloc(char *path)
    666  5184  ek110237 {
    667  6305  aw148015 	char *allocpath = filebench_shm->shm_path_ptr;
    668  5184  ek110237 
    669  6305  aw148015 	filebench_shm->shm_path_ptr += strlen(path) + 1;
    670  5184  ek110237 
    671  6305  aw148015 	if ((filebench_shm->shm_path_ptr -
    672  6305  aw148015 	    &filebench_shm->shm_filesetpaths[0]) >
    673  5184  ek110237 	    FILEBENCH_FILESETPATHMEMORY) {
    674  5184  ek110237 		filebench_log(LOG_ERROR, "Out of fileset path memory");
    675  5184  ek110237 		return (NULL);
    676  5184  ek110237 	}
    677  5184  ek110237 
    678  5184  ek110237 	(void) strncpy(allocpath, path, strlen(path));
    679  5184  ek110237 
    680  5184  ek110237 	return (allocpath);
    681  5184  ek110237 }
    682  5184  ek110237 
    683  5184  ek110237 /*
    684  5184  ek110237  * This is a limited functionality deallocator for path
    685  5184  ek110237  * strings - it can only free all path strings at once,
    686  5184  ek110237  * in order to avoid fragmentation.
    687  5184  ek110237  */
    688  5184  ek110237 void
    689  5184  ek110237 ipc_freepaths(void)
    690  5184  ek110237 {
    691  6305  aw148015 	filebench_shm->shm_path_ptr = &filebench_shm->shm_filesetpaths[0];
    692  5184  ek110237 }
    693  5184  ek110237 
    694  5184  ek110237 /*
    695  5184  ek110237  * Allocates a semid from the table of semids for pre intialized
    696  5184  ek110237  * semaphores. Searches for the first available semaphore, and
    697  5184  ek110237  * sets the entry in the table to "1" to indicate allocation.
    698  5184  ek110237  * Returns the allocated semid. Stops the run if all semaphores
    699  5184  ek110237  * are already in use.
    700  5184  ek110237  */
    701  5184  ek110237 int
    702  5184  ek110237 ipc_semidalloc(void)
    703  5184  ek110237 {
    704  5184  ek110237 	int semid;
    705  5184  ek110237 
    706  6391  aw148015 	for (semid = 0; filebench_shm->shm_semids[semid] == 1; semid++)
    707  5184  ek110237 		;
    708  5184  ek110237 	if (semid == FILEBENCH_NSEMS) {
    709  5184  ek110237 		filebench_log(LOG_ERROR,
    710  5184  ek110237 		    "Out of semaphores, increase system tunable limit");
    711  5184  ek110237 		filebench_shutdown(1);
    712  5184  ek110237 	}
    713  6391  aw148015 	filebench_shm->shm_semids[semid] = 1;
    714  5184  ek110237 	return (semid);
    715  5184  ek110237 }
    716  5184  ek110237 
    717  5184  ek110237 /*
    718  5184  ek110237  * Frees up the supplied semid by seting its position in the
    719  5184  ek110237  * allocation table to "0".
    720  5184  ek110237  */
    721  5184  ek110237 void
    722  5184  ek110237 ipc_semidfree(int semid)
    723  5184  ek110237 {
    724  6391  aw148015 	filebench_shm->shm_semids[semid] = 0;
    725  5184  ek110237 }
    726  5184  ek110237 
    727  5184  ek110237 /*
    728  5184  ek110237  * Create a pool of shared memory to fit the per-thread
    729  5184  ek110237  * allocations. Uses shmget() to create a shared memory region
    730  5184  ek110237  * of size "size", attaches to it using shmat(), and stores
    731  5184  ek110237  * the returned address of the region in filebench_shm->shm_addr.
    732  5184  ek110237  * The pool is only created on the first call. The routine
    733  5184  ek110237  * returns 0 if successful or the pool already exists,
    734  5184  ek110237  * -1 otherwise.
    735  5184  ek110237  */
    736  5184  ek110237 int
    737  5184  ek110237 ipc_ismcreate(size_t size)
    738  5184  ek110237 {
    739  5184  ek110237 #ifdef HAVE_SHM_SHARE_MMU
    740  5184  ek110237 	int flag = SHM_SHARE_MMU;
    741  5184  ek110237 #else
    742  5184  ek110237 	int flag = 0;
    743  5184  ek110237 #endif /* HAVE_SHM_SHARE_MMU */
    744  5184  ek110237 
    745  5184  ek110237 	/* Already done? */
    746  5184  ek110237 	if (filebench_shm->shm_id != -1)
    747  5184  ek110237 		return (0);
    748  5184  ek110237 
    749  5184  ek110237 	filebench_log(LOG_VERBOSE,
    750  5184  ek110237 	    "Creating %zd bytes of ISM Shared Memory...", size);
    751  5184  ek110237 
    752  5184  ek110237 	if ((filebench_shm->shm_id =
    753  5184  ek110237 	    shmget(0, size, IPC_CREAT | 0666)) == -1) {
    754  5184  ek110237 		filebench_log(LOG_ERROR,
    755  5184  ek110237 		    "Failed to create %zd bytes of ISM shared memory", size);
    756  5184  ek110237 		return (-1);
    757  5184  ek110237 	}
    758  5184  ek110237 
    759  5184  ek110237 	if ((filebench_shm->shm_addr = (caddr_t)shmat(filebench_shm->shm_id,
    760  5184  ek110237 	    0, flag)) == (void *)-1) {
    761  5184  ek110237 		filebench_log(LOG_ERROR,
    762  5184  ek110237 		    "Failed to attach %zd bytes of created ISM shared memory",
    763  5184  ek110237 		    size);
    764  5184  ek110237 		return (-1);
    765  5184  ek110237 	}
    766  5184  ek110237 
    767  5184  ek110237 	filebench_shm->shm_ptr = (char *)filebench_shm->shm_addr;
    768  5184  ek110237 
    769  5184  ek110237 	filebench_log(LOG_VERBOSE,
    770  5184  ek110237 	    "Allocated %zd bytes of ISM Shared Memory... at %zx",
    771  5184  ek110237 	    size, filebench_shm->shm_addr);
    772  5184  ek110237 
    773  5184  ek110237 	/* Locked until allocated to block allocs */
    774  6305  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_ism_lock);
    775  5184  ek110237 
    776  5184  ek110237 	return (0);
    777  5184  ek110237 }
    778  5184  ek110237 
    779  5184  ek110237 /* Per addr space ism */
    780  5184  ek110237 static int ism_attached = 0;
    781  5184  ek110237 
    782  5184  ek110237 /*
    783  5184  ek110237  * Attach to interprocess shared memory. If already attached
    784  5184  ek110237  * just return, otherwise use shmat() to attached to the region
    785  5184  ek110237  * with ID of filebench_shm->shm_id. Returns -1 if shmat()
    786  5184  ek110237  * fails, otherwise 0.
    787  5184  ek110237  */
    788  5184  ek110237 static int
    789  5184  ek110237 ipc_ismattach(void)
    790  5184  ek110237 {
    791  5184  ek110237 #ifdef HAVE_SHM_SHARE_MMU
    792  5184  ek110237 	int flag = SHM_SHARE_MMU;
    793  5184  ek110237 #else
    794  5184  ek110237 	int flag = 0;
    795  5184  ek110237 #endif /* HAVE_SHM_SHARE_MMU */
    796  5184  ek110237 
    797  5184  ek110237 
    798  5184  ek110237 	if (ism_attached)
    799  5184  ek110237 		return (0);
    800  5184  ek110237 
    801  5184  ek110237 	/* Does it exist? */
    802  5184  ek110237 	if (filebench_shm->shm_id == 999)
    803  5184  ek110237 		return (0);
    804  5184  ek110237 
    805  5184  ek110237 	if (shmat(filebench_shm->shm_id, filebench_shm->shm_addr,
    806  5184  ek110237 	    flag) == NULL)
    807  5184  ek110237 		return (-1);
    808  5184  ek110237 
    809  5184  ek110237 	ism_attached = 1;
    810  5184  ek110237 
    811  5184  ek110237 	return (0);
    812  5184  ek110237 }
    813  5184  ek110237 
    814  5184  ek110237 /*
    815  5184  ek110237  * Allocate from interprocess shared memory. Attaches to ism
    816  5184  ek110237  * if necessary, then allocates "size" bytes, updates allocation
    817  5184  ek110237  * information and returns a pointer to the allocated memory.
    818  5184  ek110237  */
    819  5184  ek110237 /*
    820  5184  ek110237  * XXX No check is made for out-of-memory condition
    821  5184  ek110237  */
    822  5184  ek110237 char *
    823  5184  ek110237 ipc_ismmalloc(size_t size)
    824  5184  ek110237 {
    825  5184  ek110237 	char *allocstr;
    826  5184  ek110237 
    827  6305  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_ism_lock);
    828  5184  ek110237 
    829  5184  ek110237 	/* Map in shared memory */
    830  5184  ek110237 	(void) ipc_ismattach();
    831  5184  ek110237 
    832  5184  ek110237 	allocstr = filebench_shm->shm_ptr;
    833  5184  ek110237 
    834  5184  ek110237 	filebench_shm->shm_ptr += size;
    835  5184  ek110237 	filebench_shm->shm_allocated += size;
    836  5184  ek110237 
    837  6305  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_ism_lock);
    838  5184  ek110237 
    839  5184  ek110237 	return (allocstr);
    840  5184  ek110237 }
    841  5184  ek110237 
    842  5184  ek110237 /*
    843  5184  ek110237  * Deletes shared memory region and resets shared memory region
    844  5184  ek110237  * information in filebench_shm.
    845  5184  ek110237  */
    846  5184  ek110237 void
    847  5184  ek110237 ipc_ismdelete(void)
    848  5184  ek110237 {
    849  5184  ek110237 	if (filebench_shm->shm_id == -1)
    850  5184  ek110237 		return;
    851  5184  ek110237 
    852  5184  ek110237 	filebench_log(LOG_VERBOSE, "Deleting ISM...");
    853  5184  ek110237 
    854  6305  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_ism_lock);
    855  5184  ek110237 #ifdef HAVE_SEM_RMID
    856  5184  ek110237 	(void) shmctl(filebench_shm->shm_id, IPC_RMID, 0);
    857  5184  ek110237 #endif
    858  5184  ek110237 	filebench_shm->shm_ptr = (char *)filebench_shm->shm_addr;
    859  5184  ek110237 	filebench_shm->shm_id = -1;
    860  5184  ek110237 	filebench_shm->shm_allocated = 0;
    861  6305  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_ism_lock);
    862  5184  ek110237 }
    863