summaryrefslogtreecommitdiff
path: root/usr/src/cmd/filebench/common/eventgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/filebench/common/eventgen.c')
-rw-r--r--usr/src/cmd/filebench/common/eventgen.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/usr/src/cmd/filebench/common/eventgen.c b/usr/src/cmd/filebench/common/eventgen.c
new file mode 100644
index 0000000000..bff586e17d
--- /dev/null
+++ b/usr/src/cmd/filebench/common/eventgen.c
@@ -0,0 +1,173 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * The event generator in this module is the producer half of a
+ * metering system which blocks flows using consumer routines in the
+ * flowop_library.c module. Four routines in that module can limit rates
+ * by event rate (flowoplib_eventlimit), by I/O operations rate
+ * (flowoplib_iopslimit()), by operations rate (flowoplib_opslimit),
+ * or by I/O bandwidth limit (flowoplib_bwlimit). By setting appropriate
+ * event generation rates, required calls per second, I/O ops per second,
+ * file system ops per second, or I/O bandwidth per second limits can
+ * be set. Note, the generated events are shared with all consumer
+ * flowops, of which their will be one for each process / thread
+ * instance which has a consumer flowop defined in it.
+ */
+
+#include <sys/time.h>
+#include "vars.h"
+#include "eventgen.h"
+#include "filebench.h"
+#include "flowop.h"
+#include "ipc.h"
+
+/*
+ * Prints "how to use" information for the eventgen module
+ */
+void
+eventgen_usage(void)
+{
+ (void) fprintf(stderr, "eventgen rate=<rate>\n");
+ (void) fprintf(stderr, "\n");
+}
+
+/*
+ * The producer side of the event system.
+ * Once eventgen_hz has been set by eventgen_setrate(),
+ * the routine sends eventgen_hz events per second until
+ * the program terminates. Events are posted by incrementing
+ * filebench_shm->eventgen_q by the number of generated
+ * events then signalling the condition variable
+ * filebench_shm->eventgen_cv to indicate to event consumers
+ * that more events are available.
+ *
+ * Eventgen_thread attempts to sleep for 10 event periods,
+ * then, once awakened, determines how many periods actually
+ * passed since sleeping, and issues a set of events equal
+ * to the number of periods that it slept, thus keeping the
+ * average rate at the requested rate.
+ */
+static void
+eventgen_thread(void)
+{
+ hrtime_t last;
+
+ last = gethrtime();
+
+ /* CONSTCOND */
+ while (1) {
+ struct timespec sleeptime;
+ hrtime_t delta;
+ int count;
+
+ if (filebench_shm->eventgen_hz == 0) {
+ (void) sleep(1);
+ continue;
+ }
+ /* Sleep for 10xperiod */
+ sleeptime.tv_sec = 0;
+ sleeptime.tv_nsec = 1000000000UL / filebench_shm->eventgen_hz;
+ sleeptime.tv_nsec *= 10;
+ if (sleeptime.tv_nsec < 1000UL)
+ sleeptime.tv_nsec = 1000UL;
+ sleeptime.tv_sec = sleeptime.tv_nsec / 1000000000UL;
+ if (sleeptime.tv_sec > 0)
+ sleeptime.tv_nsec -= (sleeptime.tv_sec * 1000000000UL);
+ (void) nanosleep(&sleeptime, NULL);
+ delta = gethrtime() - last;
+ last = gethrtime();
+ count = (filebench_shm->eventgen_hz * delta) / 1000000000;
+
+ filebench_log(LOG_DEBUG_SCRIPT,
+ "delta %lldms count %d", delta / 1000000, count);
+
+ /* Send 'count' events */
+ (void) ipc_mutex_lock(&filebench_shm->eventgen_lock);
+ /* Keep the producer with a max of 5 second depth */
+ if (filebench_shm->eventgen_q <
+ (5 * filebench_shm->eventgen_hz))
+ filebench_shm->eventgen_q += count;
+
+ (void) pthread_cond_signal(&filebench_shm->eventgen_cv);
+
+ (void) ipc_mutex_unlock(&filebench_shm->eventgen_lock);
+ }
+}
+
+/*
+ * Creates a thread to run the event generator eventgen_thread
+ * routine. Shuts down filebench if the eventgen thread cannot
+ * be created.
+ */
+void
+eventgen_init(void)
+{
+ /*
+ * Linux does not like it if the first
+ * argument to pthread_create is null. It actually
+ * segv's. -neel
+ */
+ pthread_t tid;
+
+ if (pthread_create(&tid, NULL,
+ (void *(*)(void*))eventgen_thread, 0) != 0) {
+ filebench_log(LOG_ERROR, "create timer thread failed: %s",
+ strerror(errno));
+ filebench_shutdown(1);
+ }
+}
+
+/*
+ * Puts the current event rate in the integer portion of the
+ * supplied var_t. Returns a pointer to the var_t.
+ */
+var_t *
+eventgen_ratevar(var_t *var)
+{
+ var->var_integer = filebench_shm->eventgen_hz;
+ return (var);
+}
+
+/*
+ * Sets the event generator rate to that supplied by
+ * vinteger_t rate.
+ */
+void
+eventgen_setrate(vinteger_t rate)
+{
+ filebench_shm->eventgen_hz = rate;
+}
+
+/*
+ * Turns off the event generator by setting the rate to zero
+ */
+void
+eventgen_reset(void)
+{
+ filebench_shm->eventgen_q = 0;
+}