lm_queue.c revision d1d2228c6cf3ec632d28262810ab7902932a5d33
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <pthread.h>
#include <time.h>
#include "lm.h"
#include <lm_proto.h>
static void *lm_q_worker(void *arg);
/*
*
* lm_queue_init()
*
* Parameters:
* - cq Ptr to main work queue structure used for processing
* the LMPM commands.
* - threads: The number of worker threads that can be started
* - worker: The routine that is to be used to process items
* on the work queue. In LM that is lm_cmd_handler
*
* Globals:
* None
*
* Initialize a work queue objects that are going to be used by LM to process
* commands sent to it by the MM.
*
* Return Values:
* LM_OK: If function compelete cleanly
* LM_ERROR: If an error was encountered during the queue init.
*
*/
int
{
return (LM_ERROR);
}
PTHREAD_CREATE_DETACHED) != 0) {
return (LM_ERROR);
}
return (LM_ERROR);
}
return (LM_ERROR);
}
return (LM_OK);
}
/*
*
* lm_queue_clean()
*
* Parameters:
*
* Globals:
*
* This function will go through the work queue and delete all commands
* that are pending. It will send a error final response for the commands
* with an error code of abort. This function is used when LM is told to
* disable, reset, or exit.
*
* Return Values:
*
*/
void
{
char msg_str[256];
char rsp_str[512];
return;
}
/* Events and internal commands do not get final */
/* response sent to MM, just skip and ignore */
"lm_queue_clean: %s command does not "
"need to be aborted",
continue;
}
"lm_queue_clean: %s command was aborted, final "
"response for %s command failed",
return;
}
}
}
}
/*
*
* lm_queue_add()
*
* Parameters:
* cq Ptr to main work queue structure used for processing the
* LMPM commands.
* cmd Pointer to parse tree of the LMPM command that is to be
* processed by one of the worker threads.
* tid The task id of the LMPM command being added to work queue.
* index The index into the lm_cmdData[] of the LMPM command
*
* Globals:
* None
*
* This functions adds the cmd to the work queue. It also determines if
* a worker thread is available to processes the cmd. If no worker threads
* can process the cmd and another worker thread can be started, the
* function will start another worker thread.
*
* Return Values:
* LM_OK: If function compelete cleanly
* LM_ERROR: If an error was encountered during adding the cmd
* to the work queue.
*
*/
int
{
== NULL) {
return (LM_ERROR);
}
else
return (LM_ERROR);
}
return (LM_ERROR);
}
return (LM_ERROR);
}
/*
* Add the command to the end of the queue
*/
else
/* If any threads are idle, wake them up, or if allowed start a */
/* new worker thread */
/* A thread is idle, wake it up to handle cmd */
"handle new command");
return (LM_ERROR);
}
/* Create new thread to handle cmd */
"lm_queue_add: Creating new command processing "
"thread");
(void *)cq) != 0) {
return (LM_ERROR);
}
cq->lmq_counter++;
}
return (LM_ERROR);
}
return (LM_OK);
}
/*
*
* lm_q_worker()
*
* Parameters:
* - arg Ptr to main work queue structure used for processing
* the LMPM commands.
*
* Globals:
* None
*
* This function is the wrapper that pulls the command off the work queue
* and then calls the actual function lm_cmd_handler() to process the command.
* This routine takes care of the thread processing part of the command
* processing so that the actual command processor does not need to worry
* about how it got the command.
*
* Return Values:
* NULL: If function compelete cleanly
* NULL: If an error was encountered during processing.
*
*/
static void *
lm_q_worker(void *arg)
{
int rc;
int timedout;
return ((void *)NULL);
}
/* LINTED constant in conditional context */
while (1) {
timedout = 0;
"lm_q_worker: Worker thread looking for work");
"lm_q_worker: Worker thread waiting on "
"work");
"lm_q_worker: Worker thread "
"waiting for work timed out");
timedout = 1;
break;
} else if (rc != 0) {
"failed, %d", rc);
cq->lmq_counter--;
!= 0)
"unlock failed, errno - %s",
return ((void *)NULL);
} else {
"lm_q_worker: Worker thread "
"woke up to handle work");
}
}
return ((void *)NULL);
}
"lm_q_worker: Worker thread calling "
"cmd processing routine");
"failed, errno - %s",
return ((void *)NULL);
}
}
"lm_q_worker: Worker thread shutting "
"down");
cq->lmq_counter--;
if (cq->lmq_counter == 0)
!= 0)
"cond_broadcast failed, "
return ((void *)NULL);
}
"terminating due to timeout being reached");
cq->lmq_counter--;
break;
}
}
"lm_q_worker: mutex_unlock failed, errno - %s",
return ((void *)NULL);
}