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  9801    Andrew  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  5184  ek110237  * Use is subject to license terms.
     24  6613  ek110237  *
     25  6613  ek110237  * Portions Copyright 2008 Denis Cheng
     26  5184  ek110237  */
     27  5184  ek110237 
     28  5184  ek110237 /*
     29  5184  ek110237  * The event generator in this module is the producer half of a
     30  5184  ek110237  * metering system which blocks flows using consumer routines in the
     31  5184  ek110237  * flowop_library.c module. Four routines in that module can limit rates
     32  5184  ek110237  * by event rate (flowoplib_eventlimit), by I/O operations rate
     33  5184  ek110237  * (flowoplib_iopslimit()), by operations rate (flowoplib_opslimit),
     34  5184  ek110237  * or by I/O bandwidth limit (flowoplib_bwlimit). By setting appropriate
     35  5184  ek110237  * event generation rates, required calls per second, I/O ops per second,
     36  5184  ek110237  * file system ops per second, or I/O bandwidth per second limits can
     37  5184  ek110237  * be set. Note, the generated events are shared with all consumer
     38  5184  ek110237  * flowops, of which their will be one for each process / thread
     39  5184  ek110237  * instance which has a consumer flowop defined in it.
     40  5184  ek110237  */
     41  5184  ek110237 
     42  5184  ek110237 #include <sys/time.h>
     43  6613  ek110237 
     44  6613  ek110237 #include "filebench.h"
     45  5184  ek110237 #include "vars.h"
     46  5184  ek110237 #include "eventgen.h"
     47  5184  ek110237 #include "flowop.h"
     48  5184  ek110237 #include "ipc.h"
     49  5184  ek110237 
     50  5184  ek110237 /*
     51  5184  ek110237  * Prints "how to use" information for the eventgen module
     52  5184  ek110237  */
     53  5184  ek110237 void
     54  5184  ek110237 eventgen_usage(void)
     55  5184  ek110237 {
     56  5184  ek110237 	(void) fprintf(stderr, "eventgen rate=<rate>\n");
     57  5184  ek110237 	(void) fprintf(stderr, "\n");
     58  5184  ek110237 }
     59  5184  ek110237 
     60  5184  ek110237 /*
     61  5184  ek110237  * The producer side of the event system.
     62  5184  ek110237  * Once eventgen_hz has been set by eventgen_setrate(),
     63  5184  ek110237  * the routine sends eventgen_hz events per second until
     64  5184  ek110237  * the program terminates. Events are posted by incrementing
     65  6391  aw148015  * filebench_shm->shm_eventgen_q by the number of generated
     66  5184  ek110237  * events then signalling the condition variable
     67  6391  aw148015  * filebench_shm->shm_eventgen_cv to indicate to event consumers
     68  5184  ek110237  * that more events are available.
     69  5184  ek110237  *
     70  5184  ek110237  * Eventgen_thread attempts to sleep for 10 event periods,
     71  5184  ek110237  * then, once awakened, determines how many periods actually
     72  5184  ek110237  * passed since sleeping, and issues a set of events equal
     73  5184  ek110237  * to the number of periods that it slept, thus keeping the
     74  5184  ek110237  * average rate at the requested rate.
     75  5184  ek110237  */
     76  5184  ek110237 static void
     77  5184  ek110237 eventgen_thread(void)
     78  5184  ek110237 {
     79  5184  ek110237 	hrtime_t last;
     80  5184  ek110237 
     81  5184  ek110237 	last = gethrtime();
     82  9801    Andrew 	filebench_shm->shm_eventgen_enabled = FALSE;
     83  5184  ek110237 
     84  5184  ek110237 	/* CONSTCOND */
     85  5184  ek110237 	while (1) {
     86  5184  ek110237 		struct timespec sleeptime;
     87  5184  ek110237 		hrtime_t delta;
     88  7946    Andrew 		int count, rate;
     89  5184  ek110237 
     90  7946    Andrew 		if (filebench_shm->shm_eventgen_hz == NULL) {
     91  5184  ek110237 			(void) sleep(1);
     92  5184  ek110237 			continue;
     93  7946    Andrew 		} else {
     94  7946    Andrew 			rate = avd_get_int(filebench_shm->shm_eventgen_hz);
     95  9801    Andrew 			if (rate > 0) {
     96  9801    Andrew 				filebench_shm->shm_eventgen_enabled = TRUE;
     97  9801    Andrew 			} else {
     98  9801    Andrew 				continue;
     99  9801    Andrew 			}
    100  5184  ek110237 		}
    101  7946    Andrew 
    102  5184  ek110237 		/* Sleep for 10xperiod */
    103  5184  ek110237 		sleeptime.tv_sec = 0;
    104  7946    Andrew 		sleeptime.tv_nsec = FB_SEC2NSEC / rate;
    105  6391  aw148015 
    106  5184  ek110237 		sleeptime.tv_nsec *= 10;
    107  5184  ek110237 		if (sleeptime.tv_nsec < 1000UL)
    108  5184  ek110237 			sleeptime.tv_nsec = 1000UL;
    109  6391  aw148015 
    110  6391  aw148015 		sleeptime.tv_sec = sleeptime.tv_nsec / FB_SEC2NSEC;
    111  5184  ek110237 		if (sleeptime.tv_sec > 0)
    112  6391  aw148015 			sleeptime.tv_nsec -= (sleeptime.tv_sec * FB_SEC2NSEC);
    113  6391  aw148015 
    114  5184  ek110237 		(void) nanosleep(&sleeptime, NULL);
    115  5184  ek110237 		delta = gethrtime() - last;
    116  5184  ek110237 		last = gethrtime();
    117  7946    Andrew 		count = (rate * delta) / FB_SEC2NSEC;
    118  5184  ek110237 
    119  5184  ek110237 		filebench_log(LOG_DEBUG_SCRIPT,
    120  6286  aw148015 		    "delta %llums count %d",
    121  6286  aw148015 		    (u_longlong_t)(delta / 1000000), count);
    122  5184  ek110237 
    123  5184  ek110237 		/* Send 'count' events */
    124  6391  aw148015 		(void) ipc_mutex_lock(&filebench_shm->shm_eventgen_lock);
    125  5184  ek110237 		/* Keep the producer with a max of 5 second depth */
    126  7946    Andrew 		if (filebench_shm->shm_eventgen_q < (5 * rate))
    127  6391  aw148015 			filebench_shm->shm_eventgen_q += count;
    128  5184  ek110237 
    129  6391  aw148015 		(void) pthread_cond_signal(&filebench_shm->shm_eventgen_cv);
    130  5184  ek110237 
    131  6391  aw148015 		(void) ipc_mutex_unlock(&filebench_shm->shm_eventgen_lock);
    132  5184  ek110237 	}
    133  5184  ek110237 }
    134  5184  ek110237 
    135  5184  ek110237 /*
    136  5184  ek110237  * Creates a thread to run the event generator eventgen_thread
    137  5184  ek110237  * routine. Shuts down filebench if the eventgen thread cannot
    138  5184  ek110237  * be created.
    139  5184  ek110237  */
    140  5184  ek110237 void
    141  5184  ek110237 eventgen_init(void)
    142  5184  ek110237 {
    143  5184  ek110237 	/*
    144  5184  ek110237 	 * Linux does not like it if the first
    145  5184  ek110237 	 * argument to pthread_create is null. It actually
    146  5184  ek110237 	 * segv's. -neel
    147  5184  ek110237 	 */
    148  5184  ek110237 	pthread_t tid;
    149  5184  ek110237 
    150  5184  ek110237 	if (pthread_create(&tid, NULL,
    151  5184  ek110237 	    (void *(*)(void*))eventgen_thread, 0) != 0) {
    152  5184  ek110237 		filebench_log(LOG_ERROR, "create timer thread failed: %s",
    153  5184  ek110237 		    strerror(errno));
    154  5184  ek110237 		filebench_shutdown(1);
    155  5184  ek110237 	}
    156  5184  ek110237 }
    157  5184  ek110237 
    158  5184  ek110237 /*
    159  5184  ek110237  * Puts the current event rate in the integer portion of the
    160  5184  ek110237  * supplied var_t. Returns a pointer to the var_t.
    161  5184  ek110237  */
    162  5184  ek110237 var_t *
    163  5184  ek110237 eventgen_ratevar(var_t *var)
    164  5184  ek110237 {
    165  7946    Andrew 	VAR_SET_INT(var, avd_get_int(filebench_shm->shm_eventgen_hz));
    166  5184  ek110237 	return (var);
    167  5184  ek110237 }
    168  5184  ek110237 
    169  5184  ek110237 /*
    170  5184  ek110237  * Sets the event generator rate to that supplied by
    171  7946    Andrew  * var_t *rate.
    172  5184  ek110237  */
    173  5184  ek110237 void
    174  7946    Andrew eventgen_setrate(avd_t rate)
    175  5184  ek110237 {
    176  7946    Andrew 	filebench_shm->shm_eventgen_hz = rate;
    177  7946    Andrew 	if (rate == NULL) {
    178  7946    Andrew 		filebench_log(LOG_ERROR,
    179  7946    Andrew 		    "eventgen_setrate() called without a rate");
    180  7946    Andrew 		return;
    181  7946    Andrew 	}
    182  7946    Andrew 
    183  7946    Andrew 	if (AVD_IS_VAR(rate)) {
    184  7946    Andrew 		filebench_log(LOG_VERBOSE,
    185  7946    Andrew 		    "Eventgen rate taken from variable");
    186  7946    Andrew 	} else {
    187  7946    Andrew 		filebench_log(LOG_VERBOSE, "Eventgen: %llu per second",
    188  7946    Andrew 		    (u_longlong_t)avd_get_int(rate));
    189  7946    Andrew 	}
    190  5184  ek110237 }
    191  5184  ek110237 
    192  5184  ek110237 /*
    193  7946    Andrew  * Clears the event queue so we have a clean start
    194  5184  ek110237  */
    195  5184  ek110237 void
    196  5184  ek110237 eventgen_reset(void)
    197  5184  ek110237 {
    198  6391  aw148015 	filebench_shm->shm_eventgen_q = 0;
    199  5184  ek110237 }
    200