EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base
From: Ralph Lange <[email protected]>
To: [email protected]
Date: Fri, 11 Oct 2013 00:45:37 -0000
Ralph Lange has proposed merging lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base.

Requested reviews:
  EPICS Core Developers (epics-core)

For more details, see:
https://code.launchpad.net/~epics-core/epics-base/ioc-shutdown/+merge/190512

Add iocBuildNoCA() and iocShutdown() to iocInit API to allow running an IOC from withing a test program that is part of a test harness.

Doc changes in https://code.launchpad.net/~epics-documenters/epics-appdev/ioc-shutdown
-- 
https://code.launchpad.net/~epics-core/epics-base/ioc-shutdown/+merge/190512
Your team EPICS Core Developers is requested to review the proposed merge of lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base.
=== modified file 'src/ioc/db/callback.c'
--- src/ioc/db/callback.c	2012-05-04 22:34:48 +0000
+++ src/ioc/db/callback.c	2013-10-11 00:44:30 +0000
@@ -53,6 +53,8 @@
 static epicsTimerQueueId timerQueue;
 
 /* Shutdown handling */
+enum ctl {ctlInit, ctlRun, ctlPause, ctlExit};
+static volatile enum ctl cbCtl;
 static epicsEventId startStopEvent;
 static void *exitCallback;
 
@@ -101,10 +103,13 @@
     epicsEventSignal(startStopEvent);
 }
 
-static void callbackShutdown(void *arg)
+void callbackShutdown(void)
 {
     int i;
 
+    if (cbCtl == ctlExit) return;
+    cbCtl = ctlExit;
+
     for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
         int lockKey = epicsInterruptLock();
         int ok = epicsRingPointerPush(callbackQ[i], &exitCallback);
@@ -112,6 +117,12 @@
         epicsEventSignal(callbackSem[i]);
         if (ok) epicsEventWait(startStopEvent);
     }
+    epicsTimerQueueRelease(timerQueue);
+}
+
+static void callbackExit(void *arg)
+{
+    callbackShutdown();
 }
 
 static void callbackInitOnce(void *arg)
@@ -119,6 +130,7 @@
     int i;
 
     startStopEvent = epicsEventMustCreate(epicsEventEmpty);
+    cbCtl = ctlRun;
     timerQueue = epicsTimerQueueAllocate(0,epicsThreadPriorityScanHigh);
     for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
         epicsThreadId tid;
@@ -137,7 +149,7 @@
         else
             epicsEventWait(startStopEvent);
     }
-    epicsAtExit(callbackShutdown, NULL);
+    epicsAtExit(callbackExit, NULL);
 }
 
 void callbackInit(void)

=== modified file 'src/ioc/db/callback.h'
--- src/ioc/db/callback.h	2010-10-05 19:27:37 +0000
+++ src/ioc/db/callback.h	2013-10-11 00:44:30 +0000
@@ -57,6 +57,7 @@
 
 epicsShareFunc void callbackInit(void);
 epicsShareFunc void callbackRequest(CALLBACK *pCallback);
+epicsShareFunc void callbackShutdown(void);
 epicsShareFunc void callbackSetProcess(
     CALLBACK *pcallback, int Priority, void *pRec);
 epicsShareFunc void callbackRequestProcessCallback(

=== modified file 'src/ioc/db/dbCa.c'
--- src/ioc/db/dbCa.c	2012-06-22 23:16:26 +0000
+++ src/ioc/db/dbCa.c	2013-10-11 00:44:30 +0000
@@ -173,15 +173,22 @@
     dbScanUnlock(pdbCommon);
 }
 
-static void dbCaShutdown(void *arg)
+void dbCaShutdown(void)
 {
-    if (dbCaCtl == ctlRun) {
+    if (dbCaCtl == ctlRun || dbCaCtl == ctlPause) {
         dbCaCtl = ctlExit;
         epicsEventSignal(workListEvent);
         epicsEventMustWait(startStopEvent);
+        epicsEventDestroy(startStopEvent);
+        epicsEventDestroy(workListEvent);
     }
 }
 
+static void dbCaExit(void *arg)
+{
+    dbCaShutdown();
+}
+
 void dbCaLinkInit(void)
 {
     dbServiceIOInit();
@@ -194,19 +201,23 @@
         epicsThreadGetStackSize(epicsThreadStackBig),
         dbCaTask, NULL);
     epicsEventMustWait(startStopEvent);
-    epicsAtExit(dbCaShutdown, NULL);
+    epicsAtExit(dbCaExit, NULL);
 }
 
 void dbCaRun(void)
 {
-    dbCaCtl = ctlRun;
-    epicsEventSignal(workListEvent);
+    if (dbCaCtl == ctlPause) {
+        dbCaCtl = ctlRun;
+        epicsEventSignal(workListEvent);
+    }
 }
 
 void dbCaPause(void)
 {
-    dbCaCtl = ctlPause;
-    epicsEventSignal(workListEvent);
+    if (dbCaCtl == ctlRun) {
+        dbCaCtl = ctlPause;
+        epicsEventSignal(workListEvent);
+    }
 }
 
 void dbCaAddLinkCallback(struct link *plink,

=== modified file 'src/ioc/db/dbCa.h'
--- src/ioc/db/dbCa.h	2012-04-27 17:21:47 +0000
+++ src/ioc/db/dbCa.h	2013-10-11 00:44:30 +0000
@@ -26,6 +26,7 @@
 epicsShareFunc void dbCaLinkInit(void);
 epicsShareFunc void dbCaRun(void);
 epicsShareFunc void dbCaPause(void);
+epicsShareFunc void dbCaShutdown(void);
 
 epicsShareFunc void dbCaAddLinkCallback(struct link *plink,
     dbCaCallback connect, dbCaCallback monitor, void *userPvt);

=== modified file 'src/ioc/db/dbScan.c'
--- src/ioc/db/dbScan.c	2013-04-23 15:38:57 +0000
+++ src/ioc/db/dbScan.c	2013-10-11 00:44:30 +0000
@@ -3,6 +3,8 @@
 *     National Laboratory.
 * Copyright (c) 2002 The Regents of the University of California, as
 *     Operator of Los Alamos National Laboratory.
+* Copyright (c) 2013 Helmholtz-Zentrum Berlin
+*     für Materialien und Energie GmbH.
 * EPICS BASE is distributed subject to a Software License Agreement found
 * in file LICENSE that is included with this distribution. 
 \*************************************************************************/
@@ -129,6 +131,7 @@
 static void initOnce(void);
 static void periodicTask(void *arg);
 static void initPeriodic(void);
+static void deletePeriodic(void);
 static void spawnPeriodic(int ind);
 static void initEvent(void);
 static void eventCallback(CALLBACK *pcallback);
@@ -139,10 +142,13 @@
 static void addToList(struct dbCommon *precord, scan_list *psl);
 static void deleteFromList(struct dbCommon *precord, scan_list *psl);
 
-static void scanShutdown(void *arg)
+void scanShutdown(void)
 {
     int i;
 
+    if (scanCtl == ctlExit) return;
+    scanCtl = ctlExit;
+
     interruptAccept = FALSE;
 
     for (i = 0; i < nPeriodic; i++) {
@@ -153,6 +159,15 @@
 
     scanOnce((dbCommon *)&exitOnce);
     epicsEventWait(startStopEvent);
+
+    deletePeriodic();
+
+    epicsEventDestroy(startStopEvent);
+}
+
+static void scanExit(void *arg)
+{
+    scanShutdown();
 }
 
 long scanInit(void)
@@ -169,7 +184,7 @@
     for (i = 0; i < nPeriodic; i++)
         spawnPeriodic(i);
 
-    epicsAtExit(scanShutdown, NULL);
+    epicsAtExit(scanExit, NULL);
     return 0;
 }
 
@@ -672,6 +687,28 @@
     }
 }
 
+static void deletePeriodic(void)
+{
+    int i;
+    scan_element *pse;
+
+    for (i = 0; i < nPeriodic; i++) {
+        periodic_scan_list *ppsl = papPeriodic[i];
+
+        for (pse = (scan_element *)ellFirst(&ppsl->scan_list.list);
+             pse;
+             pse = (scan_element *)ellNext(&pse->node)) {
+            ellDelete(&ppsl->scan_list.list, (ELLNODE *)pse);
+            free(pse);
+        }
+        epicsEventDestroy(ppsl->loopEvent);
+        epicsMutexDestroy(ppsl->scan_list.lock);
+        free(ppsl);
+    }
+
+    free(papPeriodic);
+}
+
 static void spawnPeriodic(int ind)
 {
     periodic_scan_list *ppsl;
@@ -778,23 +815,25 @@
 {
     dbRecordType *pdbRecordType;
 
-    /*Look for first record*/
     for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
          pdbRecordType;
          pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
         dbRecordNode *pdbRecordNode;
+
         for (pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
              pdbRecordNode;
              pdbRecordNode = (dbRecordNode *)ellNext(&pdbRecordNode->node)) {
             dbCommon *precord = pdbRecordNode->precord;
+
             if (!precord->name[0] ||
                 pdbRecordNode->flags & DBRN_FLAGS_ISALIAS)
                 continue;
+
             scanAdd(precord);
         }
     }
 }
-
+
 static void addToList(struct dbCommon *precord, scan_list *psl)
 {
     scan_element *pse, *ptemp;

=== modified file 'src/ioc/db/dbScan.h'
--- src/ioc/db/dbScan.h	2012-04-10 22:10:50 +0000
+++ src/ioc/db/dbScan.h	2013-10-11 00:44:30 +0000
@@ -44,6 +44,7 @@
 epicsShareFunc long scanInit(void);
 epicsShareFunc void scanRun(void);
 epicsShareFunc void scanPause(void);
+epicsShareFunc void scanShutdown(void);
 
 epicsShareFunc EVENTPVT eventNameToHandle(const char* event);
 epicsShareFunc void postEvent(EVENTPVT epvt);

=== modified file 'src/ioc/misc/iocInit.c'
--- src/ioc/misc/iocInit.c	2013-05-30 20:00:37 +0000
+++ src/ioc/misc/iocInit.c	2013-10-11 00:44:30 +0000
@@ -3,6 +3,8 @@
 *     National Laboratory.
 * Copyright (c) 2002 The Regents of the University of California, as
 *     Operator of Los Alamos National Laboratory.
+* Copyright (c) 2013 Helmholtz-Zentrum Berlin
+*     für Materialien und Energie GmbH.
 * EPICS BASE is distributed subject to a Software License Agreement found
 * in file LICENSE that is included with this distribution. 
 \*************************************************************************/
@@ -88,10 +90,10 @@
     return iocBuild() || iocRun();
 }
 
-int iocBuild(void)
+static int iocBuild_1(void)
 {
-    if (iocState != iocVirgin) {
-        errlogPrintf("iocBuild: IOC can only be initialized once\n");
+    if (iocState != iocVirgin && iocState != iocStopped) {
+        errlogPrintf("iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
         return -1;
     }
     initHookAnnounce(initHookAtIocBuild);
@@ -109,14 +111,17 @@
     initHookAnnounce(initHookAtBeginning);
 
     coreRelease();
-    /* After this point, further calls to iocInit() are disallowed.  */
     iocState = iocBuilding;
 
     taskwdInit();
     callbackInit();
     initHookAnnounce(initHookAfterCallbackInit);
 
-    dbCaLinkInit();
+    return 0;
+}
+
+static int iocBuild_2(void)
+{
     initHookAnnounce(initHookAfterCaLinkInit);
 
     initDrvSup();
@@ -147,9 +152,11 @@
 
     initialProcess();
     initHookAnnounce(initHookAfterInitialProcess);
+    return 0;
+}
 
-    /* Start CA server threads */
-    rsrv_init();
+static int iocBuild_3(void)
+{
     initHookAnnounce(initHookAfterCaServerInit);
 
     iocState = iocBuilt;
@@ -157,6 +164,39 @@
     return 0;
 }
 
+int iocBuild(void)
+{
+    int status;
+
+    status = iocBuild_1();
+    if (status) return status;
+
+    dbCaLinkInit();
+
+    status = iocBuild_2();
+    if (status) return status;
+
+    /* Start CA server threads */
+    rsrv_init();
+
+    status = iocBuild_3();
+    return status;
+}
+
+int iocBuildNoCA(void)
+{
+    int status;
+
+    status = iocBuild_1();
+    if (status) return status;
+
+    status = iocBuild_2();
+    if (status) return status;
+
+    status = iocBuild_3();
+    return status;
+}
+
 int iocRun(void)
 {
     if (iocState != iocPaused && iocState != iocBuilt) {
@@ -599,8 +639,19 @@
     }
 }
 
-static void exitDatabase(void *dummy)
+int iocShutdown(void)
 {
+    if (iocState == iocVirgin || iocState == iocStopped) return 0;
     iterateRecords(doCloseLinks, NULL);
+    scanShutdown();
+    callbackShutdown();
+    taskwdShutdown();
+    errlogShutdown();
     iocState = iocStopped;
+    return 0;
+}
+
+static void exitDatabase(void *dummy)
+{
+    iocShutdown();
 }

=== modified file 'src/ioc/misc/iocInit.h'
--- src/ioc/misc/iocInit.h	2009-06-10 20:19:32 +0000
+++ src/ioc/misc/iocInit.h	2013-10-11 00:44:30 +0000
@@ -19,8 +19,10 @@
 
 epicsShareFunc int iocInit(void);
 epicsShareFunc int iocBuild(void);
+epicsShareFunc int iocBuildNoCA(void);
 epicsShareFunc int iocRun(void);
 epicsShareFunc int iocPause(void);
+epicsShareFunc int iocShutdown(void);
 
 #ifdef __cplusplus
 }

=== modified file 'src/libCom/error/errlog.c'
--- src/libCom/error/errlog.c	2013-06-28 17:35:43 +0000
+++ src/libCom/error/errlog.c	2013-10-11 00:44:30 +0000
@@ -447,8 +447,9 @@
 }
 
 
-static void exitHandler(void *pvt)
+void errlogShutdown(void)
 {
+    if (pvtData.atExit) return;
     pvtData.atExit = 1;
     epicsEventSignal(pvtData.waitForWork);
     epicsEventMustWait(pvtData.waitForExit);
@@ -463,6 +464,11 @@
     epicsEventDestroy(pvtData.waitForExit);
 }
 
+static void exitHandler(void *pvt)
+{
+    errlogShutdown();
+}
+
 struct initArgs {
     int bufsize;
     int maxMsgSize;

=== modified file 'src/libCom/error/errlog.h'
--- src/libCom/error/errlog.h	2013-06-28 17:35:43 +0000
+++ src/libCom/error/errlog.h	2013-10-11 00:44:30 +0000
@@ -64,6 +64,7 @@
 epicsShareFunc int errlogSetConsole(FILE *stream);
 
 epicsShareFunc int epicsShareAPI errlogInit(int bufsize);
+epicsShareFunc void epicsShareAPI errlogShutdown(void);
 epicsShareFunc int epicsShareAPI errlogInit2(int bufsize, int maxMsgSize);
 epicsShareFunc void epicsShareAPI errlogFlush(void);
 

=== modified file 'src/libCom/taskwd/taskwd.c'
--- src/libCom/taskwd/taskwd.c	2012-05-04 18:38:59 +0000
+++ src/libCom/taskwd/taskwd.c	2013-10-11 00:44:30 +0000
@@ -70,7 +70,7 @@
 
 /* Watchdog task control */
 static volatile enum {
-    twdctlInit, twdctlRun, twdctlDisable, twdctlExit
+    ctlInit, ctlRun, ctlDisable, ctlExit
 } twdCtl;
 static epicsEventId loopEvent;
 static epicsEventId exitEvent;
@@ -90,8 +90,8 @@
     struct tNode *pt;
     struct mNode *pm;
 
-    while (twdCtl != twdctlExit) {
-        if (twdCtl == twdctlRun) {
+    while (twdCtl != ctlExit) {
+        if (twdCtl == ctlRun) {
             epicsMutexMustLock(tLock);
             pt = (struct tNode *)ellFirst(&tList);
             while (pt) {
@@ -127,14 +127,20 @@
     epicsEventSignal(exitEvent);
 }
 
-
-static void twdShutdown(void *arg)
+void taskwdShutdown(void)
 {
-    twdCtl = twdctlExit;
+    if (twdCtl == ctlExit) return;
+    twdCtl = ctlExit;
+
     epicsEventSignal(loopEvent);
     epicsEventWait(exitEvent);
 }
 
+static void twdExit(void *arg)
+{
+    taskwdShutdown();
+}
+
 static void twdInitOnce(void *arg)
 {
     epicsThreadId tid;
@@ -143,7 +149,7 @@
     mLock = epicsMutexMustCreate();
     fLock = epicsMutexMustCreate();
 
-    twdCtl = twdctlRun;
+    twdCtl = ctlRun;
     loopEvent = epicsEventMustCreate(epicsEventEmpty);
     exitEvent = epicsEventMustCreate(epicsEventEmpty);
 
@@ -153,7 +159,7 @@
     if (tid == 0)
         cantProceed("Failed to spawn task watchdog thread\n");
 
-    epicsAtExit(twdShutdown, NULL);
+    epicsAtExit(twdExit, NULL);
 }
 
 void taskwdInit(void)

=== modified file 'src/libCom/taskwd/taskwd.h'
--- src/libCom/taskwd/taskwd.h	2010-10-05 19:27:37 +0000
+++ src/libCom/taskwd/taskwd.h	2013-10-11 00:44:30 +0000
@@ -28,6 +28,7 @@
 
 /* Initialization, optional */
 epicsShareFunc void taskwdInit(void);
+epicsShareFunc void taskwdShutdown(void);
 
 
 /* For tasks to be monitored */


Replies:
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base Ralph Lange
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base Ralph Lange
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base Andrew Johnson
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base Andrew Johnson
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base Andrew Johnson
Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver

Navigate by Date:
Prev: Re: Enumerated string comparisons Benjamin Franksen
Next: Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: Enumerated string comparisons Eric Norum
Next: Re: [Merge] lp:~epics-core/epics-base/ioc-shutdown into lp:epics-base mdavidsaver
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 05 Dec 2013 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·