From 8015df9e1fa4e0ffcaed3f658d3b91420d4cbc95 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 16 Apr 2009 18:38:20 +0000 Subject: [PATCH] Added new initHook states for iocPause and iocRun commands. Added a mutex to protect the initHook.c routines. --- src/db/initHooks.c | 41 ++++++++++++++++++++++++++++++++++------- src/db/initHooks.h | 39 +++++++++++++++++++++++++++++---------- src/misc/iocInit.c | 41 ++++++++++++++++++++++++++--------------- 3 files changed, 89 insertions(+), 32 deletions(-) diff --git a/src/db/initHooks.c b/src/db/initHooks.c index 9af727d65..caf2a04d9 100644 --- a/src/db/initHooks.c +++ b/src/db/initHooks.c @@ -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]; diff --git a/src/db/initHooks.h b/src/db/initHooks.h index a6325fa27..8b72a4c78 100644 --- a/src/db/initHooks.h +++ b/src/db/initHooks.h @@ -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 diff --git a/src/misc/iocInit.c b/src/misc/iocInit.c index 5db3d6de6..a4745a248 100644 --- a/src/misc/iocInit.c +++ b/src/misc/iocInit.c @@ -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; }