threadflow.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"
#include <pthread.h>
#ifdef HAVE_LWPS
#endif
#include <signal.h>
#include "threadflow.h"
#include "filebench.h"
#include "flowop.h"
#include "ipc.h"
/*
* Threadflows are filebench entities which manage operating system
* threads. Each worker threadflow spawns a separate filebench thread,
* with attributes inherited from a FLOW_MASTER threadflow created during
* f model language parsing. This section contains routines to define,
* create, control, and delete threadflows.
*
* Each thread defined in the f model creates a FLOW_MASTER
* threadflow which encapsulates the defined attributes and flowops of
* the f language thread, including the number of instances to create.
* At runtime, a worker threadflow instance with an associated filebench
* thread is created, which runs until told to quit or is specifically
* deleted.
*/
/*
* Prints information about threadflow syntax.
*/
void
threadflow_usage(void)
{
}
/*
* Creates a thread for the supplied threadflow. If interprocess
* shared memory is desired, then increments the amount of shared
* memory needed by the amount specified in the threadflow's
* tf_memsize parameter. The thread starts in routine
* flowop_start() with a poineter to the threadflow supplied
* as the argument.
*/
static int
{
int fp = 0;
*threadflow->tf_memsize);
(void *(*)(void*))flowop_start, threadflow) != 0) {
}
/* XXX */
return (fp < 0);
}
#ifndef USE_PROCESS_MODEL
static procflow_t *my_procflow;
/*
* Terminates (exits) all the threads of the procflow (process).
* The procflow is determined from a process private pointer
* initialized by threadflow_init().
*/
/* ARGSUSED */
static void
threadflow_cancel(int arg1)
{
#ifdef HAVE_LWPS
_lwp_self());
#endif
my_procflow->pf_running = 0;
exit(0);
while (threadflow) {
if (threadflow->tf_tid) {
threadflow->tf_tid);
}
}
}
#endif /* USE_PROCESS_MODEL */
/*
* Creates threads for the threadflows associated with a procflow.
* The routine iterates through the list of threadflows in the
* supplied procflow's pf_threads list. For each threadflow on
* the list, it defines tf_instances number of cloned
* threadflows, and then calls threadflow_createthread() for
* each to create and start the actual operating system thread.
* Note that each of the newly defined threadflows will be linked
* into the procflows threadflow list, but at the head of the
* list, so they will not become part of the supplied set. After
* all the threads have been created, threadflow_init enters
* a join loop for all the threads in the newly defined
* threadflows. Once all the created threads have exited,
* threadflow_init will return 0. If errors are encountered, it
* will return a non zero value.
*/
int
{
int ret = 0;
#ifndef USE_PROCESS_MODEL
#endif
while (threadflow) {
int i;
"Starting %lld %s threads",
*(threadflow->tf_instances),
/* Create threads */
return (-1);
}
threadflow, 1);
return (-1);
/* Create threads */
}
while (threadflow) {
void *status;
if (threadflow->tf_tid)
}
procflow->pf_running = 0;
return (ret);
}
/*
* Tells the threadflow's thread to stop and optionally signals
* its associated process to end the thread.
*/
static void
{
/* Tell thread to finish */
#ifdef USE_PROCESS_MODEL
#ifdef HAVE_SIGSEND
#else
#endif
#else /* USE_PROCESS_MODEL */
#endif /* USE_PROCESS_MODEL */
}
/*
* Deletes the specified threadflow from the specified threadflow
* list after first terminating the threadflow's thread, deleting
* the threadflow's flowops, and finally freeing the threadflow
* entity. It also subtracts the threadflow's shared memory
* requirements from the total amount required, shm_required. If
* the specified threadflow is found, returns 0, otherwise
* returns -1.
*/
static int
{
}
if (threadflow == *threadlist) {
/* First on list */
return (0);
}
"Delete thread: (%s-%d) == (%s-%d)",
/* Delete */
"Deleted thread: (%s-%d)",
return (0);
}
}
return (-1);
}
/*
* Given a pointer to the thread list of a procflow, cycles
* through all the threadflows on the list, deleting each one
* except the FLOW_MASTER.
*/
void
{
while (threadflow) {
if (threadflow->tf_instance &&
continue;
}
}
}
/*
* Waits till all threadflows are started, or a timeout occurs.
* Checks through the list of threadflows, waiting up to 10
* seconds for each one to set its tf_running flag to 1. If not
* set after 10 seconds, continues on to the next threadflow
* anyway.
*/
void
{
while (threadflow) {
int waits;
if ((threadflow->tf_instance == 0) ||
continue;
}
pid,
waits = 10;
(void) ipc_mutex_unlock(
if (waits < 3)
"Waiting for pid %d thread %s-%d",
pid,
(void) sleep(1);
waits--;
}
}
}
/*
* Create an in-memory thread object linked to a parent procflow.
* A threadflow entity is allocated from shared memory and
* initialized from the "inherit" threadflow if supplied,
* otherwise to zeros. The threadflow is assigned a unique
* thread id, the supplied instance number, the supplied name
* and added to the procflow's pf_thread list. If no name is
* supplied or the threadflow can't be allocated, NULL is
* returned Otherwise a pointer to the newly allocated threadflow
* is returned.
*
* The filebench_shm->threadflow_lock must be held by the caller.
*/
static threadflow_t *
{
return (NULL);
if (threadflow == NULL)
return (NULL);
if (inherit)
else
/* Add threadflow to list */
if (*threadlistp == NULL) {
} else {
}
return (threadflow);
}
/*
* Create an in memory FLOW_MASTER thread object as described
* by the syntax. Acquire the filebench_shm->threadflow_lock and
* call threadflow_define_common() to create a threadflow entity.
* Set the number of instances to create at runtime,
* tf_instances, to "instances". Return the threadflow pointer
* returned by the threadflow_define_common call.
*/
{
return (NULL);
return (threadflow);
}
/*
* Searches the provided threadflow list for the named threadflow.
* A pointer to the threadflow is returned, or NULL if threadflow
* is not found.
*/
{
while (threadflow) {
(void) ipc_mutex_unlock(
return (threadflow);
}
}
return (NULL);
}