Added new initHook states for iocPause and iocRun commands.

Added a mutex to protect the initHook.c routines.
This commit is contained in:
Andrew Johnson
2009-04-16 18:38:20 +00:00
parent b9886c7faa
commit 8015df9e1f
3 changed files with 89 additions and 32 deletions

View File

@@ -1,12 +1,12 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* src/db/initHooks.c */
/* $Id$ */
/*
* Authors: Benjamin Franksen (BESY) and Marty Kraimer
* Date: 06-01-91
@@ -20,6 +20,7 @@
#include "dbDefs.h"
#include "ellLib.h"
#include "epicsThread.h"
#include "epicsMutex.h"
#define epicsExportSharedSymbols
#include "initHooks.h"
@@ -29,6 +30,7 @@ typedef struct initHookLink {
} initHookLink;
static ELLLIST functionList;
static epicsMutexId listLock;
/*
* Lazy initialization functions
@@ -36,6 +38,7 @@ static ELLLIST functionList;
static void initHookOnce(void *arg)
{
ellInit(&functionList);
listLock = epicsMutexMustCreate();
}
static void initHookInit(void)
@@ -51,39 +54,53 @@ int initHookRegister(initHookFunction func)
{
initHookLink *newHook;
if (!func) return 0;
initHookInit();
newHook = (initHookLink *)malloc(sizeof(initHookLink));
if (newHook == NULL) {
if (!newHook) {
printf("Cannot malloc a new initHookLink\n");
return -1;
}
newHook->func = func;
epicsMutexMustLock(listLock);
ellAdd(&functionList, &newHook->node);
epicsMutexUnlock(listLock);
return 0;
}
/*
* Called by iocInit at various points during initialization.
* Do not call this function from any other function than iocInit.
* This function must only be called by iocInit and relatives.
*/
void initHooks(initHookState state)
void initHookAnnounce(initHookState state)
{
initHookLink *hook;
initHookInit();
epicsMutexMustLock(listLock);
hook = (initHookLink *)ellFirst(&functionList);
epicsMutexUnlock(listLock);
while (hook != NULL) {
hook->func(state);
epicsMutexMustLock(listLock);
hook = (initHookLink *)ellNext(&hook->node);
epicsMutexUnlock(listLock);
}
}
/*
* Call any time you want to print out a state name.
*/
const char *initHookName(initHookState state)
const char *initHookName(int state)
{
const char *stateName[] = {
"initHookAtIocBuild",
"initHookAtBeginning",
"initHookAfterCallbackInit",
"initHookAfterCaLinkInit",
@@ -94,10 +111,20 @@ const char *initHookName(initHookState state)
"initHookAfterFinishDevSup",
"initHookAfterScanInit",
"initHookAfterInitialProcess",
"initHookAfterCaServerInit",
"initHookAfterIocBuilt",
"initHookAtIocRun",
"initHookAfterDatabaseRunning",
"initHookAfterCaServerRunning",
"initHookAfterIocRunning",
"initHookAtIocPause",
"initHookAfterCaServerPaused",
"initHookAfterDatabasePaused",
"initHookAfterIocPaused",
"initHookAfterInterruptAccept",
"initHookAtEnd"
};
if (state < initHookAtBeginning || state > initHookAtEnd) {
if (state < 0 || state > NELEMENTS(stateName)) {
return "Not an initHookState";
}
return stateName[state];

View File

@@ -1,12 +1,12 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* src/db/initHooks.h */
/* $Id$ */
/*
* Authors: Benjamin Franksen (BESY) and Marty Kraimer
* Date: 06-01-91
@@ -18,8 +18,13 @@
#include "shareLib.h"
#ifdef __cplusplus
extern "C" {
#endif
/* This enum must agree with the array of names defined in initHookName() */
typedef enum {
initHookAtIocBuild = 0, /* Start of iocBuild/iocInit commands */
initHookAtBeginning,
initHookAfterCallbackInit,
initHookAfterCaLinkInit,
@@ -30,18 +35,32 @@ typedef enum {
initHookAfterFinishDevSup,
initHookAfterScanInit,
initHookAfterInitialProcess,
initHookAfterInterruptAccept,
initHookAtEnd
}initHookState;
initHookAfterCaServerInit,
initHookAfterIocBuilt, /* End of iocBuild command */
#ifdef __cplusplus
extern "C" {
#endif
initHookAtIocRun, /* Start of iocRun command */
initHookAfterDatabaseRunning,
initHookAfterCaServerRunning,
initHookAfterIocRunning, /* End of iocRun/iocInit commands */
initHookAtIocPause, /* Start of iocPause command */
initHookAfterCaServerPaused,
initHookAfterDatabasePaused,
initHookAfterIocPaused, /* End of iocPause command */
/* Deprecated states, provided for backwards compatibility.
* These states are announced at the same point they were before,
* but will not be repeated if the IOC gets paused and restarted.
*/
initHookAfterInterruptAccept, /* After initHookAfterDatabaseRunning */
initHookAtEnd, /* Before initHookAfterIocRunning */
} initHookState;
typedef void (*initHookFunction)(initHookState state);
epicsShareFunc int initHookRegister(initHookFunction func);
epicsShareFunc void initHooks(initHookState state);
epicsShareFunc const char *initHookName(initHookState state);
epicsShareFunc void initHookAnnounce(initHookState state);
epicsShareFunc const char *initHookName(int state);
#ifdef __cplusplus
}
#endif

View File

@@ -6,7 +6,6 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* iocInit.c */
/* $Id$ */
/*
* Original Author: Marty Kraimer
@@ -52,7 +51,7 @@
#include "recSup.h"
#include "envDefs.h"
#include "rsrv.h"
epicsShareFunc int epicsShareAPI asInit (void);
#include "asDbLib.h"
#include "dbStaticLib.h"
#include "db_access_routines.h"
#include "initHooks.h"
@@ -91,6 +90,7 @@ int iocBuild(void)
errlogPrintf("iocBuild: IOC can only be initialized once\n");
return -1;
}
initHookAnnounce(initHookAtIocBuild);
if (!epicsThreadIsOkToBlock()) {
epicsThreadSetOkToBlock(1);
@@ -102,7 +102,7 @@ int iocBuild(void)
return -1;
}
epicsSignalInstallSigHupIgnore();
initHooks(initHookAtBeginning);
initHookAnnounce(initHookAtBeginning);
coreRelease();
/* After this point, further calls to iocInit() are disallowed. */
@@ -110,27 +110,27 @@ int iocBuild(void)
taskwdInit();
callbackInit();
initHooks(initHookAfterCallbackInit);
initHookAnnounce(initHookAfterCallbackInit);
dbCaLinkInit();
initHooks(initHookAfterCaLinkInit);
initHookAnnounce(initHookAfterCaLinkInit);
initDrvSup();
initHooks(initHookAfterInitDrvSup);
initHookAnnounce(initHookAfterInitDrvSup);
initRecSup();
initHooks(initHookAfterInitRecSup);
initHookAnnounce(initHookAfterInitRecSup);
initDevSup();
initHooks(initHookAfterInitDevSup);
initHookAnnounce(initHookAfterInitDevSup);
initDatabase();
dbLockInitRecords(pdbbase);
dbBkptInit();
initHooks(initHookAfterInitDatabase);
initHookAnnounce(initHookAfterInitDatabase);
finishDevSup();
initHooks(initHookAfterFinishDevSup);
initHookAnnounce(initHookAfterFinishDevSup);
scanInit();
if (asInit()) {
@@ -139,15 +139,17 @@ int iocBuild(void)
}
dbPutNotifyInit();
epicsThreadSleep(.5);
initHooks(initHookAfterScanInit);
initHookAnnounce(initHookAfterScanInit);
initialProcess();
initHooks(initHookAfterInitialProcess);
initHookAnnounce(initHookAfterInitialProcess);
/* Start CA server threads */
rsrv_init();
initHookAnnounce(initHookAfterCaServerInit);
iocState = iocBuilt;
initHookAnnounce(initHookAfterIocBuilt);
return 0;
}
@@ -157,21 +159,25 @@ int iocRun(void)
errlogPrintf("iocRun: IOC not paused\n");
return -1;
}
initHookAnnounce(initHookAtIocRun);
/* Enable scan tasks and some driver support functions. */
scanRun();
dbCaRun();
initHookAnnounce(initHookAfterDatabaseRunning);
if (iocState == iocBuilt)
initHooks(initHookAfterInterruptAccept);
initHookAnnounce(initHookAfterInterruptAccept);
rsrv_run();
initHookAnnounce(initHookAfterCaServerRunning);
if (iocState == iocBuilt)
initHooks(initHookAtEnd);
initHookAnnounce(initHookAtEnd);
errlogPrintf("iocRun: %s\n", iocState == iocBuilt ?
"All initialization complete" :
"IOC restarted");
iocState = iocRunning;
initHookAnnounce(initHookAfterIocRunning);
return 0;
}
@@ -181,13 +187,18 @@ int iocPause(void)
errlogPrintf("iocPause: IOC not running\n");
return -1;
}
initHookAnnounce(initHookAtIocPause);
rsrv_pause();
initHookAnnounce(initHookAfterCaServerPaused);
dbCaPause();
scanPause();
iocState = iocPaused;
initHookAnnounce(initHookAfterDatabasePaused);
iocState = iocPaused;
errlogPrintf("iocPause: IOC suspended\n");
initHookAnnounce(initHookAfterIocPaused);
return 0;
}