flowop.c revision f2fc321be9b4df7748e8c31a5edd154b0177b139
/*
* 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
* 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"
#include "config.h"
#ifdef HAVE_LWPS
#endif
#include <fcntl.h>
#include "filebench.h"
#include "flowop.h"
#include "stats.h"
#ifdef LINUX_PORT
#endif
/*
* A collection of flowop support functions. The actual code that
* implements the various flowops is in flowop_library.c.
*
* Routines for defining, creating, initializing and destroying
* flowops, cyclically invoking the flowops on each threadflow's flowop
* list, collecting statistics about flowop execution, and other
* housekeeping duties are included in this file.
*/
/*
* Prints the name and instance number of each flowop in
* the supplied list to the filebench log.
*/
int
{
while (flowop) {
}
return (0);
}
/*
* Puts current high resolution time in start time entry
* for threadflow and may also calculate running filebench
* overhead statistics.
*/
void
{
#ifdef HAVE_PROCFS
char procname[128];
}
sizeof (struct prusage), 0);
/* Compute overhead time in this thread around op */
}
#endif
/* Start of op for this thread */
}
static int controlstats_zeroed = 0;
/*
* Updates flowop's latency statistics, using saved start
* time and current high resolution time. Updates flowop's
* io count and transferred bytes statistics. Also updates
* threadflow's and flowop's cumulative read or write byte
* and io count statistics.
*/
void
{
hrtime_t t;
#ifdef HAVE_PROCFS
t =
#endif
}
}
}
/*
* Calls the flowop's initialization function, pointed to by
* flowop->fo_init.
*/
static int
{
return (-1);
}
return (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
{
int ret = 0;
#ifdef HAVE_PROCFS
if (noproc == 0) {
char procname[128];
int pfd;
}
#endif
if (!controlstats_zeroed) {
controlstats_zeroed = 1;
}
/* Hold the flowop find lock as reader to prevent lookups */
/*
* 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.
*/
/* Create the runtime flowops from those defined by the script */
while (flowop) {
flowop, 1, 0);
return;
if (flowop_initflow(newflowop) < 0) {
}
}
/* Release the find lock as reader to allow lookups */
/* Set to the start of the new flowop list */
threadflow->tf_abort = 0;
/* If we are going to use ISM, allocate later */
threadflow->tf_mem =
} else {
}
#ifdef HAVE_LWPS
_lwp_self());
#endif
/* Main filebench worker loop */
/* CONSTCOND */
while (1) {
int i;
/* Abort if asked */
threadflow->tf_running = 0;
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);
return;
}
if (threadflow->tf_memsize == 0) {
"Zero memory size for thread %s",
return;
}
/* Execute the flowop for fo_iters times */
/* Return value > 0 means "stop the filebench run" */
if (ret > 0) {
"%s: exiting flowop %s-%d",
threadflow->tf_running = 0;
break;
}
/*
* Return value < 0 means "flowop failed, stop the
* filebench run"
*/
if (ret < 0) {
threadflow->tf_running = 0;
break;
}
}
/* advance to next flowop */
/* but if at end of list, start over from the beginning */
}
}
#ifdef HAVE_LWPS
_lwp_self());
#endif
pthread_exit(&ret);
}
void
flowop_init(void)
{
}
/*
* Calls the flowop's destruct function, pointed to by
* flowop->fo_destruct.
*/
static void
{
}
/*
* Delete the designated flowop from the thread's flowop list.
* After removal from the list, the flowop is destroyed with
* flowop_destructflow().
*/
static void
{
int found = 0;
/* Delete from thread's flowop list */
if (flowop == *flowoplist) {
/* First on list */
"Delete0 flowop: (%s-%d)",
} else {
while (entry->fo_threadnext) {
"Delete0 flowop: (%s-%d) == (%s-%d)",
/* Delete */
"Deleted0 flowop: (%s-%d)",
break;
}
}
}
/* Call destructor */
#ifdef HAVE_PROCFS
/* Close /proc stats */
#endif
/* Delete from global list */
/* First on list */
found = 1;
} else {
"Delete flowop: (%s-%d) == (%s-%d)",
/* Delete */
found = 1;
break;
}
}
}
if (found) {
"Deleted flowop: (%s-%d)",
} else {
}
}
/*
* Deletes all the flowops from a flowop list.
*/
void
{
while (flowop) {
}
flowop = *flowoplist;
while (flowop) {
if (flowop->fo_instance &&
continue;
}
}
}
/*
* Allocates a flowop entity and initializes it with inherited
* contents from the "inherit" flowop, if it is supplied, or
* with zeros otherwise. In either case the file descriptor
* (fo_fd) is set to -1, and the fo_next and fo_threadnext
* pointers are set to NULL, and fo_thread is set to point to
* the owning threadflow. The initialized flowop is placed at
* the head of the global flowop list, and also placed on the
* tail of thethreadflow's tf_ops list. The routine locks the
* flowop's fo_lock and leaves it held on return. If successful,
* it returns a pointer to the allocated and initialized flowop,
* otherwise NULL.
*
* filebench_shm->flowop_lock must be held by caller.
*/
static flowop_t *
{
return (NULL);
"flowop_define: Can't malloc flowop");
return (NULL);
}
return (NULL);
if (inherit) {
} else {
}
/* Create backpointer to thread */
/* Add flowop to global list */
} else {
}
if (threadflow == NULL)
return (flowop);
/* Add flowop to thread op list */
} else {
/* Find the end of the thread list */
}
return (flowop);
}
/*
* Calls flowop_define_common() to allocate and initialize a
* flowop, and holds the shared flowop_lock during the call.
* It releases the created flowop's fo_lock when done.
*/
flowop_t *
{
return (NULL);
return (flowop);
}
/*
* Attempts to take a write lock on the flowop_find_lock that is
* defined in interprocess shared memory. Since each call to
* flowop_start() holds a read lock on flowop_find_lock, this
* routine effectively blocks until all instances of
* flowop_start() have finished. The flowop_find() routine calls
* this routine so that flowops won't be searched for until all
* flowops have been created by flowop_start.
*/
static void
flowop_find_barrier(void)
{
/* Block on wrlock to ensure find waits for all creates */
}
/*
* Returns a list of flowops named "name" from the master
* flowop list.
*/
flowop_t *
flowop_find(char *name)
{
while (flowop) {
/* Add flowop to result list */
} else {
}
}
}
return (result);
}
/*
* Returns a pointer to the specified instance of flowop
* "name" from the list returned by flowop_find().
*/
flowop_t *
{
while (result) {
break;
}
return (result);
}