Files
sics/devexec.c

971 lines
25 KiB
C

/*-------------------------------------------------------------------------
D E V I C E E X E C U T E R
Mark Koennecke, December 1996
Substantial rewrite: Mark Koennecke, February 1997
revised: Mark Koennecke, June 1997
revised for use with tasker: Mark Koennecke, September 1997
Locking added: Mark Koennecke, August 2002
Refactored and instrumentation for instrument statistics added.
Mark Koennecke, July 2006
Reworked to use copied connection objects instead of context pushes.
Mark Koennecke, January 2009
Modified to accommodate run levels
Mark Koennecke, April 2009
Heavily restructured to use separate tasks for each action
Mark Koennecke, February 2013
Copyright:
Labor fuer Neutronenstreuung
Paul Scherrer Institut
CH-5423 Villigen-PSI
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <sys/time.h>
#include "fortify.h"
#include "sics.h"
#include "nserver.h"
#include "motor.h"
#include "countdriv.h"
#include "counter.h"
#include "devexec.h"
#include "status.h"
#include "lld.h"
#include "ifile.h"
/*
#define DEBUG 1
*/
/*======================== Logging stuff ==================================*/
static FILE *devLog = NULL;
/*-------------------------------------------------------------------------*/
int openDevexecLog()
{
char *fileName = NULL;
char fileBuffer[1024];
time_t iDate;
struct tm *psTime;
if (devLog == NULL) {
fileName = IFindOption(pSICSOptions, "devexeclog");
if (fileName != NULL) {
strlcpy(fileBuffer, fileName,1024);
} else {
iDate = time(NULL);
psTime = localtime(&iDate);
fileBuffer[0] = '\0';
fileName = getenv("HOME");
if (fileName != NULL) {
snprintf(fileBuffer, 1023, "%s/log/devexec%4.4d.log",
fileName, psTime->tm_year + 1900);
}
}
devLog = fopen(fileBuffer, "a+");
}
if (devLog == NULL) {
return 0;
} else {
return 1;
}
}
/*-------------------------------------------------------------------------*/
void DevexecLog(char *operation, char *device)
{
struct timeval tv;
struct timezone tm;
if (devLog != NULL) {
gettimeofday(&tv, &tm);
fprintf(devLog, "DEVEXEC:%s:%s:%ld:%ld\n", operation, device,
(long) tv.tv_sec, (long) tv.tv_usec);
fflush(devLog);
}
traceDevice("devexec","%s:%s",device, operation);
}
/* ----------------- The Executor himself ---------------------------------*/
typedef struct __EXELIST {
pObjectDescriptor pDes;
SConnection *pOwner;
int iRun;
int iStatus;
int drivePrint;
long lTask;
long waitID;
long runID;
pTaskMan pTask;
int iLock;
pICallBack pCall;
time_t lastRun;
int paused;
int taskRunning;
int instStatus;
} ExeList;
static pExeList pExecutor = NULL;
/*--------------------------------------------------------------------------*/
static void *DevexecInterface(void *pData, int iInter)
{
pExeList self = NULL;
self = (pExeList) pData;
assert(self);
if (iInter == CALLBACKINTERFACE) {
return self->pCall;
}
return NULL;
}
/*--------------------------------------------------------------------------*/
pExeList CreateExeList(pTaskMan pTask)
{
pExeList pRes = NULL;
assert(pTask);
pRes = (pExeList) malloc(sizeof(ExeList));
if (!pRes) {
return NULL;
}
pRes->pOwner = NULL;
pRes->pDes = CreateDescriptor("DeviceExecutor");
if (!pRes->pDes) {
free(pRes);
return NULL;
}
pRes->iRun = 0;
pRes->iStatus = DEVDONE;
pRes->pTask = pTask;
pRes->lTask = -1;
pRes->waitID = -1;
pRes->runID = -1;
pRes->iLock = 0;
pRes->drivePrint = 0;
pRes->paused = 0;
pRes->taskRunning = 0;
pRes->pCall = CreateCallBackInterface();
pRes->lastRun = time(NULL);
pRes->pDes->GetInterface = DevexecInterface;
pRes->instStatus = eEager;
return pRes;
}
/*-------------------------------------------------------------------------*/
void DeleteExeList(void *pData)
{
pExeList self;
assert(pData);
self = (pExeList) pData;
if (self->pDes)
DeleteDescriptor(self->pDes);
ClearExecutor(self);
if (self->pCall)
DeleteCallBackInterface(self->pCall);
if (self->pOwner) {
SCDeleteConnection(self->pOwner);
self->pOwner = NULL;
}
free(self);
pServ->pExecutor = NULL;
if (devLog != NULL) {
fclose(devLog);
devLog = NULL;
}
}
/*--------------------------------------------------------------------------*/
void ExeInterest(pExeList self, char *name, char *text)
{
char buf[128];
snprintf(buf, sizeof(buf), "%s %s", name, text);
InvokeCallBack(self->pCall, DRIVSTAT, buf);
}
/*------------------------------------------------------------------------*/
void InvokeNewTarget(pExeList self, char *name, float target)
{
NewTarget targetEvent;
targetEvent.name = strdup(name);
targetEvent.target = target;
InvokeCallBack(self->pCall, NEWTARGET, &targetEvent);
if(targetEvent.name != NULL){
free(targetEvent.name);
}
}
/*------------------------------------------------------------------------*/
int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
void *pData, SConnection * pCon, int level, float fNew)
{
int iRet;
char pBueffel[132], pError[80];
pIDrivable pDrivInt = NULL;
pICountable pCountInt = NULL;
static int overwriteOwner = -1;
char *overwriteOption;
float oldVal;
long taskID;
assert(self);
assert(pDes);
assert(pCon);
/* may we? */
if (self->pOwner != NULL) {
if (SCGetIdent(pCon) != SCGetIdent(self->pOwner)) {
/* this hack helps on rita2, when using the sendsics script
which opens a client for every command */
if (overwriteOwner < 0) {
overwriteOption = IFindOption(pSICSOptions, "overwriteOwner");
overwriteOwner = overwriteOption && *overwriteOption != '0';
}
if (overwriteOwner) {
SCDeleteConnection(self->pOwner);
self->pOwner = SCCopyConnection(pCon);
} else {
SCWrite(pCon,
"ERROR: somebody else is still driving, Request rejected",
eLogError);
return 0;
}
}
}
if (self->iLock == 1) {
SCWrite(pCon, "ERROR: instrument is locked", eError);
return 0;
}
EndDriveTask(pData); /* BEGIN experimental: stop pending drive task for this objects immediately */
SetDevexecStatus(self,DEVDONE);
if(self->waitID < 0 && level == RUNDRIVE){
self->waitID = GetTaskGroupID(pServ->pTasker);
self->iStatus = DEVBUSY;
} else if(self->runID < 0 && level == RUNRUN){
self->runID = GetTaskGroupID(pServ->pTasker);
self->iStatus = DEVBUSY;
}
if((pDrivInt = pDes->GetInterface(pData,DRIVEID)) != NULL){
taskID = StartDriveTask(pData, pCon, name, fNew);
if(taskID > 0 && self->instStatus != eCounting){
self->instStatus = eDriving;
}
if(taskID > 0 && self->drivePrint == 1){
oldVal = pDrivInt->GetValue(pData, pCon);
snprintf(pBueffel, 131, "Driving %s from %8.3f to %8.3f",
name, oldVal, fNew);
SCWrite(pCon, pBueffel, eValue);
}
} else if(pDes->GetInterface(pData,COUNTID) != NULL){
taskID = StartCountTask(pData,pCon,name);
if(taskID > 0){
self->instStatus = eCounting;
}
} else {
SCPrintf(pCon,eLogError, "ERROR: type unkonw, cannot start %s", name);
return 0;
}
if(taskID > 0){
if(self->pOwner == NULL){
self->pOwner = SCCopyConnection(pCon);
}
self->lastRun = time(NULL);
if(level == RUNRUN){
AddTaskToGroup(pServ->pTasker, taskID, self->runID);
} else {
AddTaskToGroup(pServ->pTasker, taskID, self->waitID);
}
self->iRun = 1;
self->iStatus = DEVBUSY;
if(self->lTask < 0) {
self->lTask = TaskRegisterN(self->pTask,"devexec",
DevExecTask,
DevExecSignal,
NULL, self,TASK_PRIO_HIGH);
}
SCSetConStatus(pCon,HWBusy);
return 1;
} else {
snprintf(pBueffel,131, "ERROR: cannot start device %s", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
return 0;
}
/*------------------------------------------------------------------------
* This is a hacking thing to bypass the whole access checking thing. I
* need it at POLDI to run the fucking high voltage while the instrument is
* still counting.
*/
static int ForceStartDevice(pExeList self, char *name, pObjectDescriptor pDes,
void *pData, SConnection * pCon, float fNew)
{
long taskID;
pIDrivable pDrivInt = NULL;
if((pDrivInt = pDes->GetInterface(pData,DRIVEID)) != NULL){
taskID = StartDriveTask(pData, pCon, name, fNew);
} else if(pDes->GetInterface(pData,COUNTID) != NULL){
taskID = StartCountTask(pData,pCon,name);
} else {
SCPrintf(pCon,eLogError, "ERROR: type unkonw, cannot start %s", name);
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon,
char *name, int level, float fVal)
{
pDummy pMot = NULL;
CommandList *pCom = NULL;
char pBueffel[256];
assert(self);
assert(pSics);
assert(name);
pCom = FindCommand(pSics, name);
if (!pCom) {
snprintf(pBueffel,255, "ERROR: cannot find motor %s", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
pMot = (pDummy) pCom->pData;
if (!pMot) {
snprintf(pBueffel,255, "ERROR: %s is no motor ", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (!pMot->pDescriptor) {
snprintf(pBueffel,255, "ERROR: cannot find motor %s", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (!pMot->pDescriptor->GetInterface(pMot, DRIVEID)) {
snprintf(pBueffel, 255, "ERROR: %s is no motor", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
return StartDevice(self, name, pMot->pDescriptor, (void *) pMot, pCon,
level, fVal);
}
/*---------------------------------------------------------------------------*/
int StartCounter(pExeList self, SicsInterp * pSics, SConnection * pCon,
int level, char *name)
{
pCounter pCter = NULL;
CommandList *pCom = NULL;
char pBueffel[256];
assert(self);
assert(pSics);
assert(name);
pCom = FindCommand(pSics, name);
if (!pCom) {
snprintf(pBueffel,255, "ERROR: cannot find counter %s", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
pCter = (pCounter) pCom->pData;
if (!pCter) {
snprintf(pBueffel,255, "ERROR: %s is no counter ", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (!pCter->pDes) {
snprintf(pBueffel, 255, "ERROR: cannot find counter %s", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (!pCter->pDes->GetInterface(pCter, COUNTID)) {
snprintf(pBueffel,255, "ERROR: %s is no counter", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
return StartDevice(self, name, pCter->pDes, (void *) pCter,
pCon, level, pCter->pDriv->fPreset);
}
/*---------------------------------------------------------------------------*/
int DevExecLevelRunning(pExeList self, int level)
{
if(level == RUNRUN){
if(isTaskGroupRunning(self->pTask, self->runID)){
return 1;
}
} else if(level == RUNDRIVE){
if(isTaskGroupRunning(self->pTask, self->waitID)){
return 1;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
int Wait4Success(pExeList self)
{
int iRet;
assert(self);
/* do nothing if not running */
if (self->lTask < 0) {
printf("Nothing to wait for.... \n");
self->iRun = 0; /* not sure if this is needed here, but does not harm */
return self->iStatus;
}
/* wait for Devexec task to finish */
/*TaskWait(self->pTask, self->lTask); */
while(isTaskIDRunning(self->pTask,self->lTask)){
TaskYield(self->pTask);
}
#ifdef DEBUG
printf("Wait4Success finished\n");
#endif
self->iRun = 0;
return self->iStatus;
}
/* -----------------------------------------------------------------------*/
long GetDevexecID(pExeList self)
{
assert(self);
return self->lTask;
}
/*--------------------------------------------------------------------------*/
int StopExe(pExeList self, char *name)
{
int interrupt = 3;
assert(self);
/* if not active, nothing to do */
if (self->pOwner == NULL ) {
self->iRun = 0;
return 1;
}
if (strcasecmp(name, "run") == 0) {
TaskSignalGroup(self->pTask, SICSINT, &interrupt, self->runID);
return 1;
}
TaskSignalGroup(self->pTask, SICSINT, &interrupt, self->waitID);
return 1;
}
/*-------------------------------------------------------------------------*/
int StopExeWait(pExeList self)
{
StopExe(self, "all");
while(isTaskIDRunning(self->pTask, self->lTask)){
TaskYield(self->pTask);
}
return 1;
}
/*--------------------------------------------------------------------------*/
int PauseExecution(pExeList self)
{
int interrupt = 0;
assert(self);
if(IsCounting(self)){
TaskSignalGroup(self->pTask, IPAUSE, &interrupt, self->waitID);
TaskSignalGroup(self->pTask, IPAUSE, &interrupt, self->runID);
}
return 1;
}
/*------------------------------------------------------------------------
check, may be obsolete
*/
int IsCounting(pExeList self)
{
assert(self);
/* step through the list */
if(self->instStatus == eCounting){
return 1;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int ContinueExecution(pExeList self)
{
int interrupt = 0;
assert(self);
if(GetStatus() == ePaused){
TaskSignalGroup(self->pTask, CONTINUE, &interrupt, self->waitID);
TaskSignalGroup(self->pTask, CONTINUE, &interrupt, self->runID);
}
return 1;
}
/*------------------------------------------------------------------------*/
void ClearExecutor(pExeList self)
{
int iRet;
assert(self);
if (self->pOwner) {
if (SCGetInterrupt(self->pOwner) > eContinue) {
self->iStatus = DEVINT;
}
SCDeleteConnection(self->pOwner);
}
self->pOwner = NULL;
self->lTask = -1;
self->waitID = -1;
self->iRun = 0;
self->iLock = 0;
}
/*-------------------------------------------------------------------------*/
int StopCommand(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pExeList self = NULL;
int iRet;
char pBueffel[132];
assert(pCon);
assert(pSics);
assert(pData);
/* check Privilege: Muggers may do it */
if (!SCMatchRights(pCon, usUser)) {
SCWrite(pCon, "ERROR: NO Privilege to Stop operation ", eError);
return 0;
}
argtolower(argc, argv);
self = (pExeList) pData;
iRet = StopExe(self, argv[1]);
if (!iRet) {
snprintf(pBueffel,131, "ERROR: %s not found, so could not halt", argv[1]);
SCWrite(pCon, pBueffel, eError);
}
return iRet;
}
/*------------------- The CallBack function for interest ------------------*/
static int DrivStatCallback(int iEvent, void *text, void *pCon)
{
assert(pCon);
assert(text);
SConnection *con = (SConnection *) pCon;
if (con == NULL || !SCisConnected(con)) {
return -1;
}
SCWrite(pCon, text, eLog);
return 1;
}
/*---------------------------------------------------------------------------*/
int ListPending(pExeList self, SConnection *pCon)
{
pDynString buffer;
pTaskHead it = NULL;
long id;
if(self->lTask < 0){
SCWrite(pCon,"Machine Idle",eValue);
return 1;
}
buffer = CreateDynString(128,128);
if(buffer == NULL){
SCWrite(pCon,"ERROR: out of memory in Listpending",eError);
return 0;
}
for(it = TaskIteratorStart(self->pTask); it != NULL; it = TaskIteratorNext(it)){
id = GetGroupID(it);
if(id == self->waitID || id == self->runID){
DynStringConcat(buffer,(char *)GetTaskName(it));
DynStringConcatChar(buffer,'\n');
}
}
SCWrite(pCon,GetCharArray(buffer),eValue);
DeleteDynString(buffer);
return 1;
}
/*--------------------------------------------------------------------------*/
int ListExe(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pExeList self = NULL;
int list;
if (argc == 1) {
return ListPending((pExeList) pData, pCon);
}
argtolower(argc, argv);
self = (pExeList) pData;
assert(self);
if (argc == 2) {
if (strcmp(argv[1], "interest") == 0) {
list = RegisterCallback(self->pCall,
DRIVSTAT, DrivStatCallback,
SCCopyConnection(pCon), NULL);
SCSendOK(pCon);
return 1;
}
if (strcmp(argv[1], "uninterest") == 0) {
RemoveCallbackCon(self->pCall, pCon);
SCSendOK(pCon);
return 1;
}
}
SCWrite(pCon, "ERROR: illegal arguments for ListExe", eError);
return 0;
}
/*-------------------------------------------------------------------------*/
int SicsIdle(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pExeList self = NULL;
int idle;
char pBueffel[80];
self = (pExeList) pData;
assert(self);
idle = time(NULL) - self->lastRun;
snprintf(pBueffel, 79, "sicsidle = %d", idle);
SCWrite(pCon, pBueffel, eValue);
return 1;
}
/*--------------------------------------------------------------------------
Usage:
Success [level]
*/
int Success(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int iRet, level = RUNRUN;
Status eOld;
pExeList self = (pExeList)pData;
eOld = GetStatus();
if(argc > 1){
if(strcmp(argv[1],"RUNDRIVE") == 0){
level = RUNDRIVE;
}
}
if(level == RUNRUN) {
while(isTaskIDRunning(self->pTask,self->lTask)){
TaskYield(self->pTask);
}
} else {
while(DevExecLevelRunning(self, level)){
TaskYield(self->pTask);
}
}
iRet = self->iStatus;
if (iRet == DEVINT) {
if (SCGetInterrupt(pCon) == eAbortOperation) {
SCSetInterrupt(pCon, eContinue);
iRet = 1;
} else {
iRet = 0;
}
} else if (iRet == DEVDONE) {
SCWrite(pCon, "All done", eValue);
self->iRun = 0;
iRet = 1;
} else if (iRet == DEVERROR) {
SCWrite(pCon, "Finished with Problems", eValue);
iRet = 1;
} else if(iRet == DEVBUSY){
/*
some other level may still be running
*/
if(level == RUNRUN){
self->iRun = 0;
}
SCWrite(pCon, "Level done", eValue);
iRet = 1;
}
return iRet;
}
/*-------------------------------------------------------------------------*/
int PauseAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int status;
status = PauseExecution((pExeList) pData);
if (status) {
SCSendOK(pCon);
return 1;
} else {
SCWrite(pCon, "ERROR: failed to pause", eError);
return 0;
}
}
/*---------------------------------------------------------------------*/
int DevexecAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int val;
char pBueffel[256];
void *data = NULL;
pDummy pDum = NULL;
float fTarget;
CommandList *pCom = NULL;
pExeList self = (pExeList) pData;
if (argc < 2) {
SCWrite(pCon, "ERROR: not enough arguments to devexec command",
eError);
return 0;
}
strtolower(argv[1]);
if (strcmp(argv[1], "driveprint") == 0) {
if (argc > 2 && SCMatchRights(pCon, usUser)) {
val = atoi(argv[2]);
self->drivePrint = val;
SCSendOK(pCon);
return 1;
} else {
snprintf(pBueffel, 255, "devexe.drivePrint = %d", self->drivePrint);
SCWrite(pCon, pBueffel, eValue);
return 1;
}
} else if(strcmp(argv[1],"force") == 0) {
if(argc < 4){
SCWrite(pCon,"ERROR: insufficient number of arguments to devexec force",
eError);
return 0;
}
pCom = FindCommand(pSics,argv[2]);
fTarget = atof(argv[3]);
if(pCom == NULL){
SCPrintf(pCon,eError,"ERROR: command %s to force not found", argv[2]);
return 0;
}
data = pCom->pData;
pDum = (pDummy)data;
if(GetDrivableInterface(data) == NULL && GetCountableInterface(data) == NULL ){
SCPrintf(pCon,eError,"ERROR: command %s not startable", argv[2]);
return 0;
}
val = ForceStartDevice(self,argv[2],pDum->pDescriptor,data, pCon, fTarget);
return val;
} else {
SCWrite(pCon, "ERROR: unknown subcommand to devexec", eError);
return 0;
}
}
/*-------------------------------------------------------------------------*/
int ContinueAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int status;
Status eStat;
eStat = GetStatus();
if (eStat != ePaused) {
SCWrite(pCon, "ERROR: Not paused, ignored", eError);
return 0;
}
status = ContinueExecution((pExeList) pData);
if (status) {
SCSendOK(pCon);
return 1;
} else {
SCWrite(pCon, "ERROR: failed to pause", eError);
return 0;
}
}
/*--------------------------------------------------------------------------*/
int isInRunMode(pExeList self)
{
if (self == NULL) {
return 0;
} else {
return self->iRun;
}
}
/*--------------------------------------------------------------------------*/
SConnection *GetExeOwner(pExeList self)
{
if (self == NULL)
return NULL;
return self->pOwner;
}
/*--------------------------------------------------------------------------*/
int DevExecTask(void *pData)
{
pExeList self = NULL;
self = (pExeList) pData;
assert(self != NULL);
if(isTaskGroupRunning(self->pTask,self->waitID)
|| isTaskGroupRunning(self->pTask,self->runID)){
self->iStatus = DEVBUSY;
return 1;
}
/*
We are done, clean up
*/
self->waitID = -1;
self->lTask = -1;
self->iRun = 0;
self->instStatus = eEager;
/*
This is sort of unclean. Setting DEVERROR has to be done in the
device task function as it is the only one that knows about this.
Interrupts always have priority, thus they are dealt with here.
*/
if(SCGetInterrupt(self->pOwner) != eContinue){
self->iStatus = DEVINT;
} else {
if(self->iStatus != DEVERROR){
self->iStatus = DEVDONE;
}
}
SCDeleteConnection(self->pOwner);
self->pOwner = NULL;
return 0;
}
/*---------------------------------------------------------------------------*/
void DevExecSignal(void *pEL, int iSignal, void *pSigData)
{
int *iInt;
pExeList self = NULL;
SConnection *pCon = NULL;
self = (pExeList) pEL;
assert(self);
TaskSignalGroup(self->pTask,iSignal, pSigData, self->waitID);
}
/*--------------------------------------------------------------------*/
void LockDeviceExecutor(pExeList self)
{
assert(self);
self->iLock = 1;
}
/*--------------------------------------------------------------------*/
void UnlockDeviceExecutor(pExeList self)
{
assert(self);
self->iLock = 0;
}
/*--------------------------------------------------------------------*/
void DevExecInit(void)
{
pExeList pExe = pServ->pExecutor;
/* commands to do with the executor. Only StopExe carries the
DeleteFunction in order to avoid double deletion. All the
other commands operate on the same datastructure.
*/
AddCommand(pServ->pSics, "StopExe", StopCommand, DeleteExeList, pExe);
AddCommand(pServ->pSics, "ListExe", ListExe, NULL, pExe);
AddCommand(pServ->pSics, "sicsidle", SicsIdle, NULL, pExe);
AddCommand(pServ->pSics, "Success", Success, NULL, pExe);
AddCommand(pServ->pSics, "pause", PauseAction, NULL, pExe);
AddCommand(pServ->pSics, "continue", ContinueAction, NULL, pExe);
AddCommand(pServ->pSics, "devexec", DevexecAction, NULL, pExe);
}
/*---------------------------------------------------------------------*/
void *GetExecutorCallback(pExeList self)
{
return self->pCall;
}
/*----------------------------------------------------------------------*/
void SetDevexecStatus(pExeList pExe, int code)
{
if(code >= 0 || code <= DEVBUSY){
pExe->iStatus = code;
}
}
/*------------------------------------------------------------------------*/
int GetDevExecInstStatus(pExeList self)
{
if(self->lTask < 0){
return eEager;
} else {
return self->instStatus;
}
}