From deb9dbcd7756edeac608948e8cd0568228d4329b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 4 Jun 2019 12:23:13 -0500 Subject: [PATCH 01/47] Added decimation filter, documentation and tests --- documentation/RELEASE_NOTES.html | 17 ++ src/std/filters/Makefile | 1 + src/std/filters/decimate.c | 115 +++++++++ src/std/filters/filters.dbd.pod | 40 +++ src/std/filters/test/Makefile | 6 + src/std/filters/test/decTest.c | 273 +++++++++++++++++++++ src/std/filters/test/epicsRunFilterTests.c | 2 + 7 files changed, 454 insertions(+) create mode 100644 src/std/filters/decimate.c create mode 100644 src/std/filters/test/decTest.c diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 8ed4e04bf..c7fbc02b2 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -16,6 +16,23 @@ +

Added new decimation channel filter

+ +

A new server-side filter has been added to the IOC for reducing the number +and frequency of monitor updates from a channel by a client-specified factor. +The filter's behaviour is quite simplistic, it passes the first monitor event it +sees to the client and then drops the next N-1 events before passing another +event. For example to sample a 60Hz channel at 1Hz, a 10Hz channel every 6 +seconds, or a 1Hz channel once every minute:

+ +
    Hal$ camonitor 'test:channel.{"dec":{"n":60}}'
+    ...
+ +

More information is included in the +filters +documentation +file.

+

Cleaning up with Multiple CA contexts in a Process

Bruno Martins reported a problem with the CA client library at shutdown in a diff --git a/src/std/filters/Makefile b/src/std/filters/Makefile index d4539898f..3a27361f6 100644 --- a/src/std/filters/Makefile +++ b/src/std/filters/Makefile @@ -15,6 +15,7 @@ dbRecStd_SRCS += ts.c dbRecStd_SRCS += dbnd.c dbRecStd_SRCS += arr.c dbRecStd_SRCS += sync.c +dbRecStd_SRCS += decimate.c HTMLS += filters.html diff --git a/src/std/filters/decimate.c b/src/std/filters/decimate.c new file mode 100644 index 000000000..d34884ebe --- /dev/null +++ b/src/std/filters/decimate.c @@ -0,0 +1,115 @@ +/*************************************************************************\ +* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2010 Brookhaven National Laboratory. +* Copyright (c) 2010 Helmholtz-Zentrum Berlin +* fuer Materialien und Energie GmbH. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Authors: Ralph Lange , + * Andrew Johnson + */ + +#include + +#include "freeList.h" +#include "db_field_log.h" +#include "chfPlugin.h" +#include "epicsExport.h" + +typedef struct myStruct { + epicsInt32 n, i; +} myStruct; + +static void *myStructFreeList; + +static const +chfPluginArgDef opts[] = { + chfInt32(myStruct, n, "n", 1, 0), + chfPluginArgEnd +}; + +static void * allocPvt(void) +{ + myStruct *my = (myStruct*) freeListCalloc(myStructFreeList); + return (void *) my; +} + +static void freePvt(void *pvt) +{ + freeListFree(myStructFreeList, pvt); +} + +static int parse_ok(void *pvt) +{ + myStruct *my = (myStruct*) pvt; + + if (my->n < 1) + return -1; + + return 0; +} + +static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) { + db_field_log *passfl = NULL; + myStruct *my = (myStruct*) pvt; + epicsInt32 i = my->i; + + if (pfl->ctx == dbfl_context_read) + return pfl; + + if (i++ == 0) + passfl = pfl; + + if (i >= my->n) + i = 0; + + my->i = i; + return passfl; +} + +static void channelRegisterPre(dbChannel *chan, void *pvt, + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) +{ + *cb_out = filter; + *arg_out = pvt; +} + +static void channel_report(dbChannel *chan, void *pvt, int level, const unsigned short indent) +{ + myStruct *my = (myStruct*) pvt; + printf("%*sDecimate (dec): n=%d, i=%d\n", indent, "", + my->n, my->i); +} + +static chfPluginIf pif = { + allocPvt, + freePvt, + + NULL, /* parse_error, */ + parse_ok, + + NULL, /* channel_open, */ + channelRegisterPre, + NULL, /* channelRegisterPost, */ + channel_report, + NULL /* channel_close */ +}; + +static void decInitialize(void) +{ + static int firstTime = 1; + + if (!firstTime) return; + firstTime = 0; + + if (!myStructFreeList) + freeListInitPvt(&myStructFreeList, sizeof(myStruct), 64); + + chfPluginRegister("dec", &pif, opts); +} + +epicsExportRegistrar(decInitialize); diff --git a/src/std/filters/filters.dbd.pod b/src/std/filters/filters.dbd.pod index f1a848469..d352d0e5c 100644 --- a/src/std/filters/filters.dbd.pod +++ b/src/std/filters/filters.dbd.pod @@ -14,6 +14,8 @@ The following filters are available in this release: =item * L +=item * L + =back =head2 Using Filters @@ -245,3 +247,41 @@ periods only when "blue" is true by using ... =cut + +registrar(decInitialize) + +=head3 Decimation Filter C<"dec"> + +This filter is used to reduce the number or rate of monitor updates from a +channel by an integer factor C that is provided as a filter argument, +discarding the other updates. A true decimation following the original meaning +of the word would be achieved by giving C as 10, to only allow every tenth +update through. + +=head4 Parameters + +=over + +=item Number C<"n"> + +The decimation factor, a positive integer. Giving n=1 is equivalent to a no-op +that allows all updates to be passed to the client. + +=back + +This filter is intentionally very simplistic. It passes on the first monitor +event that it sees after the channel connects, then discards the next N-1 events +before sending the next event. If several clients connect to a channel using the +same filter settings they may see completely different data streams since each +client gets its own instance of the filter whose event counter starts when that +client connects. + +=head4 Example + +To sample a 60Hz channel at 1Hz, a 10Hz channel every 6 seconds or a 1Hz channel +once every minute: + + Hal$ camonitor 'test:channel' 'test:channel.{"dec":{"n":60}}' + ... + +=cut diff --git a/src/std/filters/test/Makefile b/src/std/filters/test/Makefile index 6e6ad79c6..ad77c5d11 100644 --- a/src/std/filters/test/Makefile +++ b/src/std/filters/test/Makefile @@ -56,6 +56,12 @@ syncTest_SRCS += filterTest_registerRecordDeviceDriver.cpp testHarness_SRCS += syncTest.c TESTS += syncTest +TESTPROD_HOST += decTest +decTest_SRCS += decTest.c +decTest_SRCS += filterTest_registerRecordDeviceDriver.cpp +testHarness_SRCS += decTest.c +TESTS += decTest + # epicsRunFilterTests runs all the test programs in a known working order. testHarness_SRCS += epicsRunFilterTests.c diff --git a/src/std/filters/test/decTest.c b/src/std/filters/test/decTest.c new file mode 100644 index 000000000..cc9317eb4 --- /dev/null +++ b/src/std/filters/test/decTest.c @@ -0,0 +1,273 @@ +/*************************************************************************\ +* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2010 Brookhaven National Laboratory. +* Copyright (c) 2010 Helmholtz-Zentrum Berlin +* fuer Materialien und Energie GmbH. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Authors: Ralph Lange , + * Andrew Johnson + */ + +#include + +#include "dbStaticLib.h" +#include "dbAccessDefs.h" +#include "db_field_log.h" +#include "dbCommon.h" +#include "dbChannel.h" +#include "registry.h" +#include "chfPlugin.h" +#include "errlog.h" +#include "dbmf.h" +#include "epicsUnitTest.h" +#include "dbUnitTest.h" +#include "epicsTime.h" +#include "testMain.h" +#include "osiFileName.h" + +void filterTest_registerRecordDeviceDriver(struct dbBase *); + +static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) { + return !(memcmp(pfl1, pfl2, sizeof(db_field_log))); +} + +static void fl_setup(dbChannel *chan, db_field_log *pfl, long val) { + struct dbCommon *prec = dbChannelRecord(chan); + + pfl->ctx = dbfl_context_event; + pfl->type = dbfl_type_val; + pfl->stat = prec->stat; + pfl->sevr = prec->sevr; + pfl->time = prec->time; + pfl->field_type = DBF_LONG; + pfl->no_elements = 1; + /* + * use memcpy to avoid a bus error on + * union copy of char in the db at an odd + * address + */ + memcpy(&pfl->u.v.field, + dbChannelField(chan), + dbChannelFieldSize(chan)); + pfl->u.v.field.dbf_long = val; +} + +static void testHead (char* title) { + testDiag("--------------------------------------------------------"); + testDiag("%s", title); + testDiag("--------------------------------------------------------"); +} + +static void mustDrop(dbChannel *pch, db_field_log *pfl, char* m) { + db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + + testOk(NULL == pfl2, "filter drops field_log (%s)", m); +} + +static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) { + db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + + testOk(pfl == pfl2, "filter passes field_log (%s)", m); +} + +static void checkAndOpenChannel(dbChannel *pch, const chFilterPlugin *plug) { + ELLNODE *node; + chFilter *filter; + chPostEventFunc *cb_out = NULL; + void *arg_out = NULL; + db_field_log fl, fl1; + + testDiag("Test filter structure and open channel"); + + testOk((ellCount(&pch->filters) == 1), "channel has one plugin"); + + fl_setup(pch, &fl, 1); + fl1 = fl; + node = ellFirst(&pch->filters); + filter = CONTAINER(node, chFilter, list_node); + plug->fif->channel_register_pre(filter, &cb_out, &arg_out, &fl1); + testOk(cb_out && arg_out, + "register_pre registers one filter with argument"); + testOk(fl_equal(&fl1, &fl), + "register_pre does not change field_log data type"); + + testOk(!(dbChannelOpen(pch)), "dbChannel with plugin dec opened"); + node = ellFirst(&pch->pre_chain); + filter = CONTAINER(node, chFilter, pre_node); + testOk((ellCount(&pch->pre_chain) == 1 && filter->pre_arg != NULL), + "dec has one filter with argument in pre chain"); + testOk((ellCount(&pch->post_chain) == 0), + "sync has no filter in post chain"); +} + +MAIN(decTest) +{ + dbChannel *pch; + const chFilterPlugin *plug; + char myname[] = "dec"; + db_field_log *pfl[10]; + int i; + dbEventCtx evtctx; + + testPlan(68); + + testdbPrepare(); + + testdbReadDatabase("filterTest.dbd", NULL, NULL); + + filterTest_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("xRecord.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + evtctx = db_init_events(); + + testOk(!!(plug = dbFindFilter(myname, strlen(myname))), + "plugin '%s' registered correctly", myname); + + /* N < 1 */ + testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":-1}}")), + "dbChannel with dec (n=-1) failed"); + testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":0}}")), + "dbChannel with dec (n=0) failed"); + /* Bad parms */ + testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{}}")), + "dbChannel with dec (no parm) failed"); + testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{\"x\":true}}")), + "dbChannel with dec (x=true) failed"); + + /* No Decimation (N=1) */ + + testHead("No Decimation (n=1)"); + testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":1}}")), + "dbChannel with plugin dec (n=1) created"); + + checkAndOpenChannel(pch, plug); + + for (i = 0; i < 5; i++) { + pfl[i] = db_create_read_log(pch); + fl_setup(pch, pfl[i], 10 + i); + } + + testDiag("Test event stream"); + + mustPass(pch, pfl[0], "i=0"); + mustPass(pch, pfl[1], "i=1"); + mustPass(pch, pfl[2], "i=2"); + mustPass(pch, pfl[3], "i=3"); + mustPass(pch, pfl[4], "i=4"); + + for (i = 0; i < 5; i++) + db_delete_field_log(pfl[i]); + + dbChannelDelete(pch); + + /* Decimation (N=2) */ + + testHead("Decimation (n=2)"); + testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":2}}")), + "dbChannel with plugin dec (n=2) created"); + + checkAndOpenChannel(pch, plug); + + for (i = 0; i < 10; i++) { + pfl[i] = db_create_read_log(pch); + fl_setup(pch, pfl[i], 20 + i); + } + + testDiag("Test event stream"); + + mustPass(pch, pfl[0], "i=0"); + mustDrop(pch, pfl[1], "i=1"); + mustPass(pch, pfl[2], "i=2"); + mustDrop(pch, pfl[3], "i=3"); + mustPass(pch, pfl[4], "i=4"); + mustDrop(pch, pfl[5], "i=5"); + mustPass(pch, pfl[6], "i=6"); + mustDrop(pch, pfl[7], "i=7"); + mustPass(pch, pfl[8], "i=8"); + mustDrop(pch, pfl[9], "i=9"); + + for (i = 0; i < 10; i++) + db_delete_field_log(pfl[i]); + + dbChannelDelete(pch); + + /* Decimation (N=3) */ + + testHead("Decimation (n=3)"); + testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":3}}")), + "dbChannel with plugin dec (n=3) created"); + + checkAndOpenChannel(pch, plug); + + for (i = 0; i < 10; i++) { + pfl[i] = db_create_read_log(pch); + fl_setup(pch, pfl[i], 30 + i); + } + + testDiag("Test event stream"); + + mustPass(pch, pfl[0], "i=0"); + mustDrop(pch, pfl[1], "i=1"); + mustDrop(pch, pfl[2], "i=2"); + mustPass(pch, pfl[3], "i=3"); + mustDrop(pch, pfl[4], "i=4"); + mustDrop(pch, pfl[5], "i=5"); + mustPass(pch, pfl[6], "i=6"); + mustDrop(pch, pfl[7], "i=7"); + mustDrop(pch, pfl[8], "i=8"); + mustPass(pch, pfl[9], "i=9"); + + for (i = 0; i < 10; i++) + db_delete_field_log(pfl[i]); + + dbChannelDelete(pch); + + /* Decimation (N=4) */ + + testHead("Decimation (n=4)"); + testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":4}}")), + "dbChannel with plugin dec (n=4) created"); + + checkAndOpenChannel(pch, plug); + + for (i = 0; i < 10; i++) { + pfl[i] = db_create_read_log(pch); + fl_setup(pch, pfl[i], 40 + i); + } + + testDiag("Test event stream"); + + mustPass(pch, pfl[0], "i=0"); + mustDrop(pch, pfl[1], "i=1"); + mustDrop(pch, pfl[2], "i=2"); + mustDrop(pch, pfl[3], "i=3"); + mustPass(pch, pfl[4], "i=4"); + mustDrop(pch, pfl[5], "i=5"); + mustDrop(pch, pfl[6], "i=6"); + mustDrop(pch, pfl[7], "i=7"); + mustPass(pch, pfl[8], "i=8"); + mustDrop(pch, pfl[9], "i=9"); + + for (i = 0; i < 10; i++) + db_delete_field_log(pfl[i]); + + dbChannelDelete(pch); + + db_close_events(evtctx); + + testIocShutdownOk(); + + testdbCleanup(); + + return testDone(); +} diff --git a/src/std/filters/test/epicsRunFilterTests.c b/src/std/filters/test/epicsRunFilterTests.c index 236364391..5737d77dc 100644 --- a/src/std/filters/test/epicsRunFilterTests.c +++ b/src/std/filters/test/epicsRunFilterTests.c @@ -17,6 +17,7 @@ int tsTest(void); int dbndTest(void); int syncTest(void); int arrTest(void); +int decTest(void); void epicsRunFilterTests(void) { @@ -26,6 +27,7 @@ void epicsRunFilterTests(void) runTest(dbndTest); runTest(syncTest); runTest(arrTest); + runTest(decTest); dbmfFreeChunks(); From 5cfff383b265ab99448ce44d39b0e865bf9bdd4d Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Jun 2019 13:16:42 -0500 Subject: [PATCH 02/47] Synchronization hook support for osiClockTime --- src/libCom/osi/osiClockTime.c | 7 +++++++ src/libCom/osi/osiClockTime.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/libCom/osi/osiClockTime.c b/src/libCom/osi/osiClockTime.c index fb9d1532f..8ae43aed8 100644 --- a/src/libCom/osi/osiClockTime.c +++ b/src/libCom/osi/osiClockTime.c @@ -148,6 +148,8 @@ void ClockTime_GetProgramStart(epicsTimeStamp *pDest) /* Synchronization thread */ #if defined(vxWorks) || defined(__rtems__) +CLOCKTIME_SYNCHOOK ClockTime_syncHook = NULL; + static void ClockTimeSync(void *dummy) { taskwdInsert(0, NULL, NULL); @@ -179,11 +181,16 @@ static void ClockTimeSync(void *dummy) ClockTimePvt.syncTime = timeNow; epicsMutexUnlock(ClockTimePvt.lock); + if (ClockTime_syncHook) + ClockTime_syncHook(1); + ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_value; } } ClockTimePvt.synchronized = 0; + if (ClockTime_syncHook) + ClockTime_syncHook(0); taskwdRemove(0); } #endif diff --git a/src/libCom/osi/osiClockTime.h b/src/libCom/osi/osiClockTime.h index 17eacab3e..23598886d 100644 --- a/src/libCom/osi/osiClockTime.h +++ b/src/libCom/osi/osiClockTime.h @@ -19,6 +19,12 @@ void ClockTime_Init(int synchronize); void ClockTime_Shutdown(void *dummy); int ClockTime_Report(int level); +#if defined(vxWorks) || defined(__rtems__) +typedef void (* CLOCKTIME_SYNCHOOK)(int synchronized); + +extern CLOCKTIME_SYNCHOOK ClockTime_syncHook; +#endif + #ifdef __cplusplus } #endif From 30812c23f017cc20daf15ed72364648af04c2ce9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Jun 2019 13:17:35 -0500 Subject: [PATCH 03/47] Internal cleanup in osiClockTime.c --- src/libCom/osi/osiClockTime.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libCom/osi/osiClockTime.c b/src/libCom/osi/osiClockTime.c index 8ae43aed8..01958b20e 100644 --- a/src/libCom/osi/osiClockTime.c +++ b/src/libCom/osi/osiClockTime.c @@ -23,7 +23,8 @@ #include "taskwd.h" #define NSEC_PER_SEC 1000000000 -#define ClockTimeSyncInterval_value 60.0 +#define ClockTimeSyncInterval_initial 1.0 +#define ClockTimeSyncInterval_normal 60.0 static struct { @@ -79,7 +80,7 @@ static void ClockTime_InitOnce(void *pfirst) ClockTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty); ClockTimePvt.lock = epicsMutexCreate(); - ClockTimePvt.ClockTimeSyncInterval = 1.0; /* First sync */ + ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_initial; epicsAtExit(ClockTime_Shutdown, NULL); @@ -184,7 +185,7 @@ static void ClockTimeSync(void *dummy) if (ClockTime_syncHook) ClockTime_syncHook(1); - ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_value; + ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_normal; } } From b0db6568ea26ab41c4610d21b9bf1a901707f834 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Jun 2019 13:24:39 -0500 Subject: [PATCH 04/47] Replace EPICS_TIMEZONE envParam with EPICS_TZ Adjust rtems_init() to use it. --- configure/CONFIG_SITE_ENV | 69 ++++++++++++++++++----------------- src/libCom/RTEMS/rtems_init.c | 24 +++--------- src/libCom/env/envDefs.h | 2 +- 3 files changed, 41 insertions(+), 54 deletions(-) diff --git a/configure/CONFIG_SITE_ENV b/configure/CONFIG_SITE_ENV index 49331f9a4..008467933 100644 --- a/configure/CONFIG_SITE_ENV +++ b/configure/CONFIG_SITE_ENV @@ -24,40 +24,41 @@ # Site-specific environment settings -# Time service: -# EPICS_TIMEZONE -# Local timezone info for vxWorks and RTEMS. The format is -# :::: -# where is only used by strftime() for %Z conversions, -# and and are mmddhh - that is month,day,hour -# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402 -# The future dates below assume the rules don't get changed; -# see http://www.timeanddate.com/time/dst/2018.html to check. -# -# DST for 2018 US: Mar 11 - Nov 04 -# EU: Mar 25 - Oct 28 -EPICS_TIMEZONE = CUS::360:031102:110402 -#EPICS_TIMEZONE = MET::-60:032502:102803 -# -# DST for 2019 US: Mar 10 - Nov 03 -# EU: Mar 31 - Oct 27 -#EPICS_TIMEZONE = CUS::360:031002:110302 -#EPICS_TIMEZONE = MET::-60:033102:102703 -# -# DST for 2020 US: Mar 08 - Nov 01 -# EU: Mar 29 - Oct 25 -#EPICS_TIMEZONE = CUS::360:030802:110102 -#EPICS_TIMEZONE = MET::-60:032902:102503 -# -# DST for 2021 US: Mar 14 - Nov 07 -# EU: Mar 28 - Oct 31 -#EPICS_TIMEZONE = CUS::360:031402:110702 -#EPICS_TIMEZONE = MET::-60:032802:103103 -# -# DST for 2022 US: Mar 13 - Nov 06 -# EU: Mar 27 - Oct 30 -#EPICS_TIMEZONE = CUS::360:031302:110602 -#EPICS_TIMEZONE = MET::-60:032702:103003 +## Time service: +# EPICS_TZ +# Local timezone rules for vxWorks and RTEMS. The value follows the Posix +# TZ environment variable's Mm.n.d/h format (see the IBM link below for +# details). If TZ hasn't already been set when the osdTime timeRegister() +# C++ static constructor runs, this parameter will be copied into the TZ +# environment variable. Once the OS clock has been synchronized to NTP the +# routine tz2timezone() will be run to convert TZ into the TIMEZONE +# variable format that VxWorks needs. +# https://developer.ibm.com/articles/au-aix-posix/ + +# Japan Standard Time, no DST: +#EPICS_TZ = "JST-9" + +# Central European (Summer) Time: +#EPICS_TZ = "CET-1CEST,M3.5.0/2,M10.5.0/3" + +# Greenwich Mean/British Summer Time: +#EPICS_TZ = "GMT0BST,M3.5.0/1,M10.5.0/2" + +# US Eastern Standard/Daylight Time: +#EPICS_TZ = "EST5EDT,M3.2.0/2,M11.1.0/2" + +# US Central Standard/Daylight Time: +EPICS_TZ = "CST6CDT,M3.2.0/2,M11.1.0/2" + +# US Mountain Standard/Daylight Time: +#EPICS_TZ = "MST7MDT,M3.2.0/2,M11.1.0/2" + +# US Pacific Standard/Daylight Time: +#EPICS_TZ = "PST8PDT,M3.2.0/2,M11.1.0/2" + +# US Hawaiian Standard Time, no DST: +#EPICS_TZ = "HST10" + # EPICS_TS_NTP_INET # NTP time server ip address for VxWorks and RTEMS. diff --git a/src/libCom/RTEMS/rtems_init.c b/src/libCom/RTEMS/rtems_init.c index 2b909ab3b..dcb6daaf7 100644 --- a/src/libCom/RTEMS/rtems_init.c +++ b/src/libCom/RTEMS/rtems_init.c @@ -581,25 +581,11 @@ Init (rtems_task_argument ignored) printf ("***** Can't set time: %s\n", rtems_status_text (sc)); } if (getenv("TZ") == NULL) { - const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE); - if (tzp == NULL) { - printf("Warning -- no timezone information available -- times will be displayed as GMT.\n"); - } - else { - char tz[10]; - int minWest, toDst = 0, fromDst = 0; - if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) { - printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp); - } - else { - char posixTzBuf[40]; - char *p = posixTzBuf; - p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60); - if (toDst != fromDst) - p += sprintf(p, "%cDT", tz[0]); - epicsEnvSet("TZ", posixTzBuf); - } - } + const char *tzp = envGetConfigParamPtr(&EPICS_TZ); + if (!tzp || *tzp) + printf("Warning: No timezone information, times will be displayed in UTC.\n"); + else + epicsEnvSet("TZ", tzp); } tzset(); osdTimeRegister(); diff --git a/src/libCom/env/envDefs.h b/src/libCom/env/envDefs.h index 20f0eb2ad..588cecdad 100644 --- a/src/libCom/env/envDefs.h +++ b/src/libCom/env/envDefs.h @@ -61,7 +61,7 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT; epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS; epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS; epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH; -epicsShareExtern const ENV_PARAM EPICS_TIMEZONE; +epicsShareExtern const ENV_PARAM EPICS_TZ; epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET; epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT; epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_INET; From b57f02ece202c71c03d94c9b53990c29ab1a416c Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Jun 2019 13:26:24 -0500 Subject: [PATCH 05/47] epicsTimeTo[GM]TM(): Allow pNSecDest==NULL --- src/libCom/osi/epicsTime.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libCom/osi/epicsTime.cpp b/src/libCom/osi/epicsTime.cpp index af4fae25d..9f544274f 100644 --- a/src/libCom/osi/epicsTime.cpp +++ b/src/libCom/osi/epicsTime.cpp @@ -955,7 +955,8 @@ extern "C" { try { local_tm_nano_sec tmns = epicsTime (*pSrc); *pDest = tmns.ansi_tm; - *pNSecDest = tmns.nSec; + if (pNSecDest) + *pNSecDest = tmns.nSec; } catch (...) { return epicsTimeERROR; @@ -967,7 +968,8 @@ extern "C" { try { gm_tm_nano_sec gmtmns = epicsTime (*pSrc); *pDest = gmtmns.ansi_tm; - *pNSecDest = gmtmns.nSec; + if (pNSecDest) + *pNSecDest = gmtmns.nSec; } catch (...) { return epicsTimeERROR; From 96998f55e01f6472fa41f9db448db768628002bb Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Jun 2019 14:55:26 -0500 Subject: [PATCH 06/47] Have VxWorks call tz2timezone() once clock is sync'd --- src/libCom/osi/Makefile | 2 +- src/libCom/osi/os/vxWorks/osdTime.cpp | 32 ++- src/libCom/osi/os/vxWorks/tz2timezone.c | 278 ++++++++++++++++++++++++ 3 files changed, 303 insertions(+), 9 deletions(-) create mode 100644 src/libCom/osi/os/vxWorks/tz2timezone.c diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile index c06a862ed..e05aec37d 100644 --- a/src/libCom/osi/Makefile +++ b/src/libCom/osi/Makefile @@ -77,7 +77,7 @@ Com_SRCS += epicsGeneralTime.c # Time providers Com_SRCS += osiClockTime.c -Com_SRCS_vxWorks += osiNTPTime.c +Com_SRCS_vxWorks += osiNTPTime.c tz2timezone.c Com_SRCS_RTEMS += osiNTPTime.c ifeq ($(OS_CLASS),vxWorks) diff --git a/src/libCom/osi/os/vxWorks/osdTime.cpp b/src/libCom/osi/os/vxWorks/osdTime.cpp index 4db375fbb..eb144c1b6 100644 --- a/src/libCom/osi/os/vxWorks/osdTime.cpp +++ b/src/libCom/osi/os/vxWorks/osdTime.cpp @@ -24,22 +24,38 @@ #define NTP_REQUEST_TIMEOUT 4 /* seconds */ +extern "C" { + int tz2timezone(void); +} + static char sntp_sync_task[] = "ipsntps"; static char ntp_daemon[] = "ipntpd"; static const char *pserverAddr = NULL; +static CLOCKTIME_SYNCHOOK prevHook; + extern char* sysBootLine; +static void timeSync(int synchronized) { + if (!tz2timezone()) + ClockTime_syncHook = prevHook; /* Don't call me again */ +} + static int timeRegister(void) { - /* If TIMEZONE not defined, set it from EPICS_TIMEZONE */ - if (getenv("TIMEZONE") == NULL) { - const char *timezone = envGetConfigParamPtr(&EPICS_TIMEZONE); - if (timezone == NULL) { - printf("timeRegister: No Time Zone Information\n"); - } else { - epicsEnvSet("TIMEZONE", timezone); + /* If TZ not defined, set it from EPICS_TZ */ + if (getenv("TZ") == NULL) { + const char *tz = envGetConfigParamPtr(&EPICS_TZ); + + if (tz && *tz) { + epicsEnvSet("TZ", tz); + + /* Call tz2timezone() once we know what year it is */ + prevHook = ClockTime_syncHook; + ClockTime_syncHook = timeSync; } + else if (getenv("TIMEZONE") == NULL) + printf("timeRegister: No Time Zone Information available\n"); } // Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider @@ -57,7 +73,7 @@ static int timeRegister(void) } if (useNTP) { - // Start NTP first so it can be used to sync SysTime + // Start NTP first so it can be used to sync ClockTime NTPTime_Init(100); ClockTime_Init(CLOCKTIME_SYNC); } else { diff --git a/src/libCom/osi/os/vxWorks/tz2timezone.c b/src/libCom/osi/os/vxWorks/tz2timezone.c new file mode 100644 index 000000000..df8db8514 --- /dev/null +++ b/src/libCom/osi/os/vxWorks/tz2timezone.c @@ -0,0 +1,278 @@ +/*************************************************************************\ +* Copyright (c) 2009 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Authors: Larry Hoff, Andrew Johnson + */ + +/* + * This file exports a single function "int tz2timezone(void)" which reads + * the TZ environment variable (defined by POSIX) and converts it to the + * TIMEZONE environment variable defined by ANSI. The latter is used by + * VxWorks "time" functions, is largely deprecated in other computing + * environments, has limitations, and is difficult to maintain. This holds + * out the possibility of "pretending" that VxWorks supports "TZ" - until + * such time as it actually does. + * + * For simplicity, only the "POSIX standard form" of TZ will be supported. + * Even that is complicated enough (see following spec). Furthermore, + * only the "M" form of DST start and stop dates are supported. + * + * TZ = zone[-]offset[dst[offset],start[/time],end[/time]] + * + * zone + * A three or more letter name for the timezone in normal (winter) time. + * + * [-]offset + * A signed time giving the offset of the time zone westwards from + * Greenwich. The time has the form hh[:mm[:ss]] with a one of two + * digit hour, and optional two digit minutes and seconds. + * + * dst + * The name of the time zone when daylight saving is in effect. It may + * be followed by an offset giving how big the adjustment is, required + * if different than the default of 1 hour. + * + * start/time,end/time + * Specify the start and end of the daylight saving period. The start + * and end fields indicate on what day the changeover occurs, and must + * be in this format: + * + * Mm.n.d + * This indicates month m, the n-th occurrence of day d, where + * 1 <= m <= 12, 1 <= n <= 5, 0 <= d <= 6, 0=Sunday + * The 5th occurrence means the last occurrence of that day in a + * month. So M4.1.0 is the first Sunday in April, M9.5.0 is the + * last Sunday in September. + * + * The time field indicates what hour the changeover occurs on the given + * day (TIMEZONE only supports switching on the hour). + * + */ + +#include +#include /* getenv() */ +#include /* printf() */ +#include /* strchr() */ +#include /* isalpha() */ + +#include + +/* for reference: TZ syntax, example, and TIMEZONE example + * std offset dst [offset],start[/time],end[/time] + * CST6CDT5,M3.2.0,M11.1.0 + * EST+5EDT,M4.1.0/2,M10.5.0/2 + * + * std offset start stop + * TIMEZONE=EST::300:030802:110102 + */ + +static int extractDate(const char *tz, struct tm *current, char *s) +{ + static const int startdays[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; + static const int molengths[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + int month, week, weekday, hour=2; /* default=2AM */ + int jan1wday, wday, mday; + + /* Require 'M' format */ + if (*++tz != 'M') { + printf("tz2timezone: Unsupported date type, need 'M' format\n"); + return ERROR; + } + tz++; + + if (sscanf(tz, "%d.%d.%d/%d", &month, &week, &weekday, &hour) < 3) + return ERROR; /* something important missing */ + + if (month == 0 || month>12 || + week < 1 || week > 5 || + weekday < 0 || weekday > 6 || + hour < 0 || hour > 23) + return ERROR; + + /* Now for some brute-force calendar calculations... */ + /* start month is in "month", and the day is "weekday", but + we need to know when that weekday first occurs in that month */ + /* Let's start with weekday on Jan. 1 */ + jan1wday = (7 + current->tm_wday - (current->tm_yday % 7)) % 7; + + /* We need to know if it is a leap year (and if it matters) */ + /* Let's assume that we're working with a date between 1901 and 2099, + that way we don't have to think about the "century exception". + If this code is still running (unchanged) in 2100, I'll be stunned + (and 139 years old) */ + wday = (jan1wday + startdays[month-1] + + ((month > 2 && (current->tm_year % 4 == 0)) ? 1 : 0)) % 7; + + /* Let's see on what day-of-the-month the first target weekday occurs + (counting from 1). The result is a number between 1 and 7, inclusive. */ + mday = 1 + ((7 + weekday - wday) % 7); + + /* Next, we add the week offset. If we overflow the month, we subtract + one week */ + mday += 7 * (week - 1); + if (mday > molengths[month-1]) + mday -= 7; + + /* Should I handle Feb 29? I'm willing to gamble that no one in their right + mind would schedule a time change to occur on Feb. 29. If so, we'll be a + week early */ + sprintf(s, "%02d%02d%02d", month, mday, hour); + + return OK; +} + + +static const char *getTime(const char *s, int *time) +{ + /* Time format is [+/-]hh[:mm][:ss] followed by the next zone name */ + + *time = 0; + + if (!isdigit((int) s[0])) + return s; /* no number here... */ + + if (!isdigit((int) s[1])) { /* single digit form */ + *time = s[0] - '0'; + return s + 1; + } + + if (isdigit((int) s[1])) { /* two digit form */ + *time = 10 * (s[0] - '0') + (s[1] - '0'); + return s + 2; + } + + return s; /* does not follow supported form */ +} + +int tz2timezone(void) +{ + const char *tz = getenv("TZ"); + /* Spec. says that zone names must be at least 3 chars. + * I've never seen a longer zone name, but I'll allocate + * 40 chars. If you live in a zone with a longer name, + * you may want to think about the benefits of relocation. + */ + char zone[40]; + char start[10], stop[10]; /* only really need 7 bytes now */ + int hours = 0, minutes = 0, sign = 1; + /* This is more than enough, even with a 40-char zone + * name, and 4-char offset. + */ + char timezone[100]; + int i = 0; /* You *always need an "i" :-) */ + epicsTimeStamp now; + struct tm current; + + /* First let's get the current time. We need the year to + * compute the start/stop dates for DST. + */ + if (epicsTimeGetCurrent(&now) || + epicsTimeToTM(¤t, NULL, &now)) + return ERROR; + + /* Make sure TZ exists. + * Spec. says that ZONE must be at least 3 chars. + */ + if ((!tz) || (strlen(tz) < 3)) + return ERROR; + + /* OK, now a bunch of brute-force parsing. My brain hurts if + * I try to think of an elegant regular expression for the + * string. + */ + + /* Start extracting zone name, must be alpha */ + while ((i < sizeof(zone) - 1) && isalpha((int) *tz)) { + zone[i++] = *tz++; + } + if (i < 3) + return ERROR; /* Too short, not a real zone name? */ + + zone[i] = 0; /* Nil-terminate (for now) */ + + /* Now extract offset time. The format is [+/-]hh[:mm[:ss]] + * Recall that TIMEZONE doesn't support seconds.... + */ + if (*tz == '-') { + sign = -1; + tz++; + } + else if (*tz == '+') { + tz++; + } + + /* Need a digit now */ + if (!isdigit((int) *tz)) + return ERROR; + + /* First get the hours */ + tz = getTime(tz, &hours); + if (hours > 24) + return ERROR; + + if (*tz == ':') { /* There is a minutes part */ + /* Need another digit now */ + if (!isdigit((int) *++tz)) + return ERROR; + + /* Extract the minutes */ + tz = getTime(tz, &minutes); + if (minutes > 60) + return ERROR; + + /* Skip any seconds part */ + if (*tz == ':') { + int seconds; + tz = getTime(tz + 1, &seconds); + } + } + + /* Extract any DST zone name, must be alpha */ + if (isalpha((int) *tz)) { + zone[i++] = '/'; /* Separate the names */ + + while ((i < sizeof(zone) - 1) && isalpha((int) *tz)) { + zone[i++] = *tz++; + } + zone[i] = 0; /* Nil-terminate */ + } + + minutes += hours * 60; + minutes *= sign; + + /* Look for start/stop dates - require neither or both */ + tz = strchr(tz, ','); + if (!tz) { /* No daylight savings time here */ + /* Format the env. variable */ + sprintf(timezone, "TIMEZONE=%s::%d", zone, minutes); + } + else { + if (extractDate(tz, ¤t, start) != OK) + return ERROR; + + tz = strchr(tz + 1, ','); + if (!tz) + return ERROR; + if (extractDate(tz, ¤t, stop) != OK) + return ERROR; + + /* Format the env. variable */ + sprintf(timezone, "TIMEZONE=%s::%d:%s:%s", zone, minutes, start, stop); + } + + /* Make it live! */ + putenv(timezone); + + return OK; +} From d3a8a49552ca7930aa9a5ab34ceb1de9cd25ccf4 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Jun 2019 15:37:46 -0500 Subject: [PATCH 07/47] Release Notes --- documentation/RELEASE_NOTES.html | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 8ed4e04bf..f6daa49d4 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -16,6 +16,38 @@ +

Replace EPICS_TIMEZONE with EPICS_TZ

+ +

The EPICS_TIMEZONE environment parameter provided time-zone +information for the IOC's locale in the old ANSI format expected by VxWorks for +its TIMEZONE environment variable, and can also used by RTEMS to set +its TZ environment variable. However the TIMEZONE value has to +be updated every year since it contains the exact dates of the daylight-savings +time changes. The Posix TZ format that RTEMS uses contains rules that for +calculating those dates, thus its value would only need updating if the rules +(or the locale) are changed.

+ +

This release contains changes that replace the EPICS_TIMEZONE +environment parameter with one called EPICS_TZ and a routine for +VxWorks that calculates the TIMEZONE environment variable from the +current TZ value. This routine will be run once at start-up, when the +EPICS clock has synchronized to its NTP server. The calculations it contains +were worked out and donated to EPICS by Larry Hoff in 2009; it is unforunate +that it has taken 10 years for them to be integrated into Base.

+ +

The default value for the EPICS_TZ environment parameter is set in +the Base configure/CONFIG_SITE_ENV file, which contains example settings for +most EPICS sites that use VxWorks, and a link to a page describing the Posix TZ +format for any locations that I missed.

+ +

If a VxWorks IOC runs continuously without being rebooted from December 31st +to the start of daylight savings time the following year, its TIMEZONE +value will be wrong as it was calculated for the previous year. This only +affects times that are converted to a string on the IOC however and is easily +fixed; just run the command tz2timezone() on the VxWorks shell and the +calculation will be redone for the current year. IOCs that get rebooted at least +once before the start of summer time will not need this to be done.

+

Cleaning up with Multiple CA contexts in a Process

Bruno Martins reported a problem with the CA client library at shutdown in a From 398fdee33ebf2f20bef733653839cbf2118d22fe Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 26 Jun 2019 23:28:51 -0500 Subject: [PATCH 08/47] Added db_available_logs() for filter test code to use Returns the number of items available on the db_field_log free-list. --- src/ioc/db/dbEvent.c | 5 +++++ src/ioc/db/dbEvent.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index fb1f3a168..d1f954834 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -1165,3 +1165,8 @@ void db_delete_field_log (db_field_log *pfl) freeListFree(dbevFieldLogFreeList, pfl); } } + +int db_available_logs(void) +{ + return (int) freeListItemsAvail(dbevFieldLogFreeList); +} diff --git a/src/ioc/db/dbEvent.h b/src/ioc/db/dbEvent.h index fe0e52f90..2e496a726 100644 --- a/src/ioc/db/dbEvent.h +++ b/src/ioc/db/dbEvent.h @@ -78,6 +78,7 @@ epicsShareFunc void db_event_disable (dbEventSubscription es); epicsShareFunc struct db_field_log* db_create_event_log (struct evSubscrip *pevent); epicsShareFunc struct db_field_log* db_create_read_log (struct dbChannel *chan); epicsShareFunc void db_delete_field_log (struct db_field_log *pfl); +epicsShareFunc int db_available_logs(void); #define DB_EVENT_OK 0 #define DB_EVENT_ERROR (-1) @@ -87,4 +88,3 @@ epicsShareFunc void db_delete_field_log (struct db_field_log *pfl); #endif #endif /*INCLdbEventh*/ - From e03c7edfe5ac87f8573d0ad420167eec8d26a7bd Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 26 Jun 2019 23:32:52 -0500 Subject: [PATCH 09/47] Check free-list size to ensure field-logs freed properly Moves where the field-logs get freed into the mustPass/mustDrop routines, where it only happens if the filter didn't free them itself. Filters that save field-logs can't use this code as-is. --- src/std/filters/test/decTest.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/std/filters/test/decTest.c b/src/std/filters/test/decTest.c index cc9317eb4..b6b2276c6 100644 --- a/src/std/filters/test/decTest.c +++ b/src/std/filters/test/decTest.c @@ -64,15 +64,29 @@ static void testHead (char* title) { } static void mustDrop(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(); db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + int newFree = db_available_logs(); testOk(NULL == pfl2, "filter drops field_log (%s)", m); + testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d", + oldFree, newFree); + + if (newFree == oldFree) + db_delete_field_log(pfl); } static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(); db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + int newFree = db_available_logs(); testOk(pfl == pfl2, "filter passes field_log (%s)", m); + testOk(newFree == oldFree, "field_log was not freed - %d => %d", + oldFree, newFree); + + if (newFree == oldFree) + db_delete_field_log(pfl); } static void checkAndOpenChannel(dbChannel *pch, const chFilterPlugin *plug) { @@ -114,7 +128,7 @@ MAIN(decTest) int i; dbEventCtx evtctx; - testPlan(68); + testPlan(103); testdbPrepare(); @@ -165,9 +179,6 @@ MAIN(decTest) mustPass(pch, pfl[3], "i=3"); mustPass(pch, pfl[4], "i=4"); - for (i = 0; i < 5; i++) - db_delete_field_log(pfl[i]); - dbChannelDelete(pch); /* Decimation (N=2) */ @@ -196,9 +207,6 @@ MAIN(decTest) mustPass(pch, pfl[8], "i=8"); mustDrop(pch, pfl[9], "i=9"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); - dbChannelDelete(pch); /* Decimation (N=3) */ @@ -227,9 +235,6 @@ MAIN(decTest) mustDrop(pch, pfl[8], "i=8"); mustPass(pch, pfl[9], "i=9"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); - dbChannelDelete(pch); /* Decimation (N=4) */ @@ -258,9 +263,6 @@ MAIN(decTest) mustPass(pch, pfl[8], "i=8"); mustDrop(pch, pfl[9], "i=9"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); - dbChannelDelete(pch); db_close_events(evtctx); From f79c69f0a0ed7b323af8c16751afe9e25e4914fc Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 26 Jun 2019 23:33:35 -0500 Subject: [PATCH 10/47] Fix the decimate filter, free field-logs when dropping them --- src/std/filters/decimate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/std/filters/decimate.c b/src/std/filters/decimate.c index d34884ebe..502422f55 100644 --- a/src/std/filters/decimate.c +++ b/src/std/filters/decimate.c @@ -63,6 +63,8 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) { if (i++ == 0) passfl = pfl; + else + db_delete_field_log(pfl); if (i >= my->n) i = 0; From 44ea66aaaf83c09a5991f52a13d1c436e61ce937 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 Jul 2019 23:11:21 -0500 Subject: [PATCH 11/47] Add checks and summary of free-list size to decTest.c --- src/std/filters/test/decTest.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/std/filters/test/decTest.c b/src/std/filters/test/decTest.c index b6b2276c6..19aedc6dd 100644 --- a/src/std/filters/test/decTest.c +++ b/src/std/filters/test/decTest.c @@ -72,8 +72,7 @@ static void mustDrop(dbChannel *pch, db_field_log *pfl, char* m) { testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d", oldFree, newFree); - if (newFree == oldFree) - db_delete_field_log(pfl); + db_delete_field_log(pfl2); } static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) { @@ -85,8 +84,7 @@ static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) { testOk(newFree == oldFree, "field_log was not freed - %d => %d", oldFree, newFree); - if (newFree == oldFree) - db_delete_field_log(pfl); + db_delete_field_log(pfl2); } static void checkAndOpenChannel(dbChannel *pch, const chFilterPlugin *plug) { @@ -125,10 +123,10 @@ MAIN(decTest) const chFilterPlugin *plug; char myname[] = "dec"; db_field_log *pfl[10]; - int i; + int i, logsFree, logsFinal; dbEventCtx evtctx; - testPlan(103); + testPlan(104); testdbPrepare(); @@ -164,6 +162,11 @@ MAIN(decTest) testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":1}}")), "dbChannel with plugin dec (n=1) created"); + /* Start the free-list */ + db_delete_field_log(db_create_read_log(pch)); + logsFree = db_available_logs(); + testDiag("%d field_logs on free-list", logsFree); + checkAndOpenChannel(pch, plug); for (i = 0; i < 5; i++) { @@ -181,6 +184,8 @@ MAIN(decTest) dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* Decimation (N=2) */ testHead("Decimation (n=2)"); @@ -209,6 +214,8 @@ MAIN(decTest) dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* Decimation (N=3) */ testHead("Decimation (n=3)"); @@ -237,6 +244,8 @@ MAIN(decTest) dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* Decimation (N=4) */ testHead("Decimation (n=4)"); @@ -265,6 +274,9 @@ MAIN(decTest) dbChannelDelete(pch); + logsFinal = db_available_logs(); + testOk(logsFree == logsFinal, "%d field_logs on free-list", logsFinal); + db_close_events(evtctx); testIocShutdownOk(); From 8ff6ce4821a98c7d0ca22ddbb3155479a535118b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 Jul 2019 23:30:07 -0500 Subject: [PATCH 12/47] Fix leak in sync filter (while, unless modes) Always release field logs when we drop them. Adjust how first and after modes work to make them easier to test. Change stream checking code, fix leaks and double frees. Add mustStash(), mustSwap(), streamReset(), drop mustPassOld(). Modify test code to check free-list count and release all of the field-logs returned by the filter; it must release any of the field-logs that it decides to drop. --- src/std/filters/sync.c | 24 ++-- src/std/filters/test/syncTest.c | 189 +++++++++++++++++++++----------- 2 files changed, 144 insertions(+), 69 deletions(-) diff --git a/src/std/filters/sync.c b/src/std/filters/sync.c index c32e9afbd..6b841eab4 100644 --- a/src/std/filters/sync.c +++ b/src/std/filters/sync.c @@ -109,7 +109,9 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) { passfl = pfl; pfl = NULL; } - break; + else + db_delete_field_log(pfl); + goto save_state; case syncModeLast: if (!actstate && my->laststate) { passfl = my->lastfl; @@ -121,28 +123,34 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) { passfl = pfl; pfl = NULL; } - break; + else + db_delete_field_log(pfl); + goto save_state; case syncModeWhile: - if (actstate) { + if (actstate) passfl = pfl; - } + else + db_delete_field_log(pfl); goto no_shift; case syncModeUnless: - if (!actstate) { + if (!actstate) passfl = pfl; - } + else + db_delete_field_log(pfl); goto no_shift; } if (my->lastfl) db_delete_field_log(my->lastfl); my->lastfl = pfl; - my->laststate = actstate; /* since no copy is made we can't keep a reference to the returned fl */ assert(my->lastfl != passfl); - no_shift: +save_state: + my->laststate = actstate; + +no_shift: return passfl; } diff --git a/src/std/filters/test/syncTest.c b/src/std/filters/test/syncTest.c index 9af44afd7..47d6e268b 100644 --- a/src/std/filters/test/syncTest.c +++ b/src/std/filters/test/syncTest.c @@ -66,31 +66,92 @@ static void testHead (char* title) { testDiag("--------------------------------------------------------"); } -static void mustDrop(dbChannel *pch, db_field_log *pfl2, char* m) { - db_field_log *pfl = dbChannelRunPreChain(pch, pfl2); - testOk(NULL == pfl, "filter drops field_log (%s)", m); +/* + * Use mustDrop() and mustPass() to test filters with no memory + * of previous field_log pointers. + */ +static void mustDrop(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(); + db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + int newFree = db_available_logs(); + + testOk(NULL == pfl2, "filter drops field_log (%s)", m); + testOk(newFree == oldFree + 1, "a field_log was freed - %d+1 => %d", + oldFree, newFree); + + db_delete_field_log(pfl2); } -static void mustPassTwice(dbChannel *pch, db_field_log *pfl2, char* m) { - db_field_log *pfl; +static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(); + db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + int newFree = db_available_logs(); + + testOk(pfl == pfl2, "filter passes field_log (%s)", m); + testOk(newFree == oldFree, "no field_logs were freed - %d => %d", + oldFree, newFree); + + db_delete_field_log(pfl2); +} + +/* + * Use mustStash() and mustSwap() to test filters that save + * field_log pointers and return them later. + * + * mustStash() expects the filter to save the current pointer + * (freeing any previously saved pointer) and return NULL. + * mustSwap() expects the filter to return the previously + * saved pointer and save the current pointer. + */ +static db_field_log *stashed; + +static void streamReset(void) { + stashed = NULL; +} + +static void mustStash(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(); + db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + int newFree = db_available_logs(); + + testOk(NULL == pfl2, "filter stashes field_log (%s)", m); + if (stashed) { + testOk(newFree == oldFree + 1, "a field_log was freed - %d+1 => %d", + oldFree, newFree); + } + else { + testOk(newFree == oldFree, "no field_logs were freed - %d => %d", + oldFree, newFree); + } + stashed = pfl; + db_delete_field_log(pfl2); +} + +static void mustSwap(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(); + db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl); + int newFree = db_available_logs(); + + testOk(stashed == pfl2, "filter returns stashed field log (%s)", m); + testOk(newFree == oldFree, "no field_logs were freed - %d => %d", + oldFree, newFree); + + stashed = pfl; + db_delete_field_log(pfl2); +} + +static void mustPassTwice(dbChannel *pch, db_field_log *pfl, char* m) { + int oldFree = db_available_logs(), newFree; + db_field_log *pfl2; testDiag("%s: filter must pass twice", m); - pfl = dbChannelRunPreChain(pch, pfl2); + pfl2 = dbChannelRunPreChain(pch, pfl); testOk(pfl2 == pfl, "call 1 does not drop or replace field_log"); - pfl = dbChannelRunPreChain(pch, pfl2); + pfl2 = dbChannelRunPreChain(pch, pfl); testOk(pfl2 == pfl, "call 2 does not drop or replace field_log"); -} - -static void mustPassOld(dbChannel *pch, db_field_log *old, db_field_log *cur, char* m) { - db_field_log *pfl = dbChannelRunPreChain(pch, cur); - - testOk(old == pfl, "filter passes previous field log (%s)", m); -} - -static void mustPass(dbChannel *pch, db_field_log *cur, char* m) { - db_field_log *pfl = dbChannelRunPreChain(pch, cur); - - testOk(cur == pfl, "filter passes field_log (%s)", m); + newFree = db_available_logs(); + testOk(newFree == oldFree, "no field_logs were freed - %d => %d", + oldFree, newFree); } static void checkCtxRead(dbChannel *pch, dbStateId id) { @@ -138,10 +199,10 @@ MAIN(syncTest) const chFilterPlugin *plug; char myname[] = "sync"; db_field_log *pfl[10]; - int i; + int i, logsFree, logsFinal; dbEventCtx evtctx; - testPlan(139); + testPlan(214); testdbPrepare(); @@ -176,9 +237,14 @@ MAIN(syncTest) testOk(!!(pch = dbChannelCreate("x.VAL{\"sync\":{\"m\":\"while\",\"s\":\"red\"}}")), "dbChannel with plugin sync (m='while' s='red') created"); + /* Start the free-list */ + db_delete_field_log(db_create_read_log(pch)); + logsFree = db_available_logs(); + testDiag("%d field_logs on free-list", logsFree); + checkAndOpenChannel(pch, plug); - for (i = 0; i < 10; i++) { + for (i = 0; i < 9; i++) { pfl[i] = db_create_read_log(pch); fl_setup(pch, pfl[i], 120 + i); } @@ -198,11 +264,10 @@ MAIN(syncTest) mustDrop(pch, pfl[7], "state=FALSE, log7"); mustDrop(pch, pfl[8], "state=FALSE, log8"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); - dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* mode UNLESS */ testHead("Mode UNLESS (m='unless', s='red')"); @@ -211,7 +276,7 @@ MAIN(syncTest) checkAndOpenChannel(pch, plug); - for (i = 0; i < 10; i++) { + for (i = 0; i < 9; i++) { pfl[i] = db_create_read_log(pch); fl_setup(pch, pfl[i], 120 + i); } @@ -231,11 +296,10 @@ MAIN(syncTest) mustPass(pch, pfl[7], "state=FALSE, log7"); mustPass(pch, pfl[8], "state=FALSE, log8"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); - dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* mode BEFORE */ testHead("Mode BEFORE (m='before', s='red')"); @@ -251,24 +315,25 @@ MAIN(syncTest) testDiag("Test event stream"); + streamReset(); dbStateClear(red); - mustDrop(pch, pfl[0], "state=FALSE, log0"); - mustDrop(pch, pfl[1], "state=FALSE, log1"); - mustDrop(pch, pfl[2], "state=FALSE, log2"); + mustStash(pch, pfl[0], "state=FALSE, log0"); + mustStash(pch, pfl[1], "state=FALSE, log1"); + mustStash(pch, pfl[2], "state=FALSE, log2"); dbStateSet(red); - mustPassOld(pch, pfl[2], pfl[3], "state=TRUE, log3, pass=log2"); - mustDrop(pch, pfl[4], "state=TRUE, log4"); - mustDrop(pch, pfl[5], "state=TRUE, log5"); - mustDrop(pch, pfl[6], "state=TRUE, log6"); + mustSwap(pch, pfl[3], "state=TRUE, log3"); + mustStash(pch, pfl[4], "state=TRUE, log4"); + mustStash(pch, pfl[5], "state=TRUE, log5"); + mustStash(pch, pfl[6], "state=TRUE, log6"); dbStateClear(red); - mustDrop(pch, pfl[7], "state=FALSE, log7"); - mustDrop(pch, pfl[8], "state=FALSE, log8"); - mustDrop(pch, pfl[9], "state=FALSE, log9"); - - db_delete_field_log(pfl[2]); + mustStash(pch, pfl[7], "state=FALSE, log7"); + mustStash(pch, pfl[8], "state=FALSE, log8"); + mustStash(pch, pfl[9], "state=FALSE, log9"); dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* mode FIRST */ testHead("Mode FIRST (m='first', s='red')"); @@ -277,13 +342,14 @@ MAIN(syncTest) checkAndOpenChannel(pch, plug); - for (i = 0; i < 10; i++) { + for (i = 0; i < 9; i++) { pfl[i] = db_create_read_log(pch); fl_setup(pch, pfl[i], 120 + i); } testDiag("Test event stream"); + streamReset(); dbStateClear(red); mustDrop(pch, pfl[0], "state=FALSE, log0"); mustDrop(pch, pfl[1], "state=FALSE, log1"); @@ -297,11 +363,10 @@ MAIN(syncTest) mustDrop(pch, pfl[7], "state=FALSE, log7"); mustDrop(pch, pfl[8], "state=FALSE, log8"); - db_delete_field_log(pfl[3]); - db_delete_field_log(pfl[9]); - dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* mode LAST */ testHead("Mode LAST (m='last', s='red')"); @@ -317,24 +382,25 @@ MAIN(syncTest) testDiag("Test event stream"); + streamReset(); dbStateClear(red); - mustDrop(pch, pfl[0], "state=FALSE, log0"); - mustDrop(pch, pfl[1], "state=FALSE, log1"); - mustDrop(pch, pfl[2], "state=FALSE, log2"); + mustStash(pch, pfl[0], "state=FALSE, log0"); + mustStash(pch, pfl[1], "state=FALSE, log1"); + mustStash(pch, pfl[2], "state=FALSE, log2"); dbStateSet(red); - mustDrop(pch, pfl[3], "state=TRUE, log3"); - mustDrop(pch, pfl[4], "state=TRUE, log4"); - mustDrop(pch, pfl[5], "state=TRUE, log5"); + mustStash(pch, pfl[3], "state=TRUE, log3"); + mustStash(pch, pfl[4], "state=TRUE, log4"); + mustStash(pch, pfl[5], "state=TRUE, log5"); dbStateClear(red); - mustPassOld(pch, pfl[5], pfl[6], "state=TRUE, log6, pass=log5"); - mustDrop(pch, pfl[7], "state=FALSE, log7"); - mustDrop(pch, pfl[8], "state=FALSE, log8"); - mustDrop(pch, pfl[9], "state=FALSE, log9"); - - db_delete_field_log(pfl[5]); + mustSwap(pch, pfl[6], "state=TRUE, log6"); + mustStash(pch, pfl[7], "state=FALSE, log7"); + mustStash(pch, pfl[8], "state=FALSE, log8"); + mustStash(pch, pfl[9], "state=FALSE, log9"); dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* mode AFTER */ testHead("Mode AFTER (m='after', s='red')"); @@ -343,13 +409,14 @@ MAIN(syncTest) checkAndOpenChannel(pch, plug); - for (i = 0; i < 10; i++) { + for (i = 0; i < 9; i++) { pfl[i] = db_create_read_log(pch); fl_setup(pch, pfl[i], 120 + i); } testDiag("Test event stream"); + streamReset(); dbStateClear(red); mustDrop(pch, pfl[0], "state=FALSE, log0"); mustDrop(pch, pfl[1], "state=FALSE, log1"); @@ -363,11 +430,11 @@ MAIN(syncTest) mustDrop(pch, pfl[7], "state=FALSE, log7"); mustDrop(pch, pfl[8], "state=FALSE, log8"); - db_delete_field_log(pfl[6]); - db_delete_field_log(pfl[9]); - dbChannelDelete(pch); + logsFinal = db_available_logs(); + testOk(logsFree == logsFinal, "%d field_logs on free-list", logsFinal); + db_close_events(evtctx); testIocShutdownOk(); From cac3e2dc3bb22b9892729a0eb224f9222daf4544 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 Jul 2019 23:32:12 -0500 Subject: [PATCH 13/47] Add checks of freelist to dbndTest.c --- src/std/filters/test/dbndTest.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/std/filters/test/dbndTest.c b/src/std/filters/test/dbndTest.c index b35b9a6cc..dc0c3e20e 100644 --- a/src/std/filters/test/dbndTest.c +++ b/src/std/filters/test/dbndTest.c @@ -62,6 +62,7 @@ static void changeValue(db_field_log *pfl2, long val) { } static void mustPassOnce(dbChannel *pch, db_field_log *pfl2, char* m, double d, long val) { + int oldFree = db_available_logs(), newFree; db_field_log *pfl; changeValue(pfl2, val); @@ -71,18 +72,26 @@ static void mustPassOnce(dbChannel *pch, db_field_log *pfl2, char* m, double d, testOk(fl_equal(pfl, pfl2), "call 1 does not change field_log data"); pfl = dbChannelRunPreChain(pch, pfl2); testOk(NULL == pfl, "call 2 drops field_log"); + newFree = db_available_logs(); + testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d", + oldFree, newFree); } static void mustDrop(dbChannel *pch, db_field_log *pfl2, char* m, double d, long val) { + int oldFree = db_available_logs(), newFree; db_field_log *pfl; changeValue(pfl2, val); testDiag("mode=%s delta=%g filter must drop", m, d); pfl = dbChannelRunPreChain(pch, pfl2); testOk(NULL == pfl, "call 1 drops field_log"); + newFree = db_available_logs(); + testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d", + oldFree, newFree); } static void mustPassTwice(dbChannel *pch, db_field_log *pfl2, char* m, double d, long val) { + int oldFree = db_available_logs(), newFree; db_field_log *pfl; changeValue(pfl2, val); @@ -93,6 +102,9 @@ static void mustPassTwice(dbChannel *pch, db_field_log *pfl2, char* m, double d, pfl = dbChannelRunPreChain(pch, pfl2); testOk(pfl2 == pfl, "call 2 does not drop or replace field_log"); testOk(fl_equal(pfl, pfl2), "call 2 does not change field_log data"); + newFree = db_available_logs(); + testOk(newFree == oldFree, "field_log was not freed - %d => %d", + oldFree, newFree); } static void testHead (char* title) { @@ -113,8 +125,9 @@ MAIN(dbndTest) db_field_log *pfl2; db_field_log fl1; dbEventCtx evtctx; + int logsFree, logsFinal; - testPlan(59); + testPlan(77); testdbPrepare(); @@ -135,6 +148,11 @@ MAIN(dbndTest) testOk(!!(pch = dbChannelCreate("x.VAL{\"dbnd\":{}}")), "dbChannel with plugin dbnd (delta=0) created"); testOk((ellCount(&pch->filters) == 1), "channel has one plugin"); + /* Start the free-list */ + db_delete_field_log(db_create_read_log(pch)); + logsFree = db_available_logs(); + testDiag("%d field_logs on free-list", logsFree); + memset(&fl, PATTERN, sizeof(fl)); fl1 = fl; node = ellFirst(&pch->filters); @@ -176,6 +194,8 @@ MAIN(dbndTest) dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* Delta = -1: pass any update */ testHead("Delta = -1: pass any update"); @@ -192,6 +212,8 @@ MAIN(dbndTest) db_delete_field_log(pfl2); dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* Delta = absolute */ testHead("Delta = absolute"); @@ -224,6 +246,8 @@ MAIN(dbndTest) dbChannelDelete(pch); + testDiag("%d field_logs on free-list", db_available_logs()); + /* Delta = relative */ testHead("Delta = relative"); @@ -275,6 +299,9 @@ MAIN(dbndTest) dbChannelDelete(pch); + logsFinal = db_available_logs(); + testOk(logsFree == logsFinal, "%d field_logs on free-list", logsFinal); + db_close_events(evtctx); testIocShutdownOk(); From 84c86e67e817e17024cc9fff151a8bfbd61cc89e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 8 Jul 2019 12:55:21 -0500 Subject: [PATCH 14/47] Fix valgrind warnings in filter tests --- src/std/filters/test/dbndTest.c | 2 ++ src/std/filters/test/decTest.c | 2 ++ src/std/filters/test/syncTest.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/std/filters/test/dbndTest.c b/src/std/filters/test/dbndTest.c index dc0c3e20e..4d70f83ad 100644 --- a/src/std/filters/test/dbndTest.c +++ b/src/std/filters/test/dbndTest.c @@ -39,12 +39,14 @@ static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) { static void fl_setup(dbChannel *chan, db_field_log *pfl) { struct dbCommon *prec = dbChannelRecord(chan); + memset(pfl, 0, sizeof(db_field_log)); pfl->ctx = dbfl_context_read; pfl->type = dbfl_type_val; pfl->stat = prec->stat; pfl->sevr = prec->sevr; pfl->time = prec->time; pfl->field_type = dbChannelFieldType(chan); + pfl->field_size = dbChannelFieldSize(chan); pfl->no_elements = dbChannelElements(chan); /* * use memcpy to avoid a bus error on diff --git a/src/std/filters/test/decTest.c b/src/std/filters/test/decTest.c index 19aedc6dd..3b6784248 100644 --- a/src/std/filters/test/decTest.c +++ b/src/std/filters/test/decTest.c @@ -39,12 +39,14 @@ static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) { static void fl_setup(dbChannel *chan, db_field_log *pfl, long val) { struct dbCommon *prec = dbChannelRecord(chan); + memset(pfl, 0, sizeof(db_field_log)); pfl->ctx = dbfl_context_event; pfl->type = dbfl_type_val; pfl->stat = prec->stat; pfl->sevr = prec->sevr; pfl->time = prec->time; pfl->field_type = DBF_LONG; + pfl->field_size = sizeof(epicsInt32); pfl->no_elements = 1; /* * use memcpy to avoid a bus error on diff --git a/src/std/filters/test/syncTest.c b/src/std/filters/test/syncTest.c index 47d6e268b..9be23b05d 100644 --- a/src/std/filters/test/syncTest.c +++ b/src/std/filters/test/syncTest.c @@ -42,12 +42,14 @@ static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) { static void fl_setup(dbChannel *chan, db_field_log *pfl, long val) { struct dbCommon *prec = dbChannelRecord(chan); + memset(pfl, 0, sizeof(db_field_log)); pfl->ctx = dbfl_context_event; pfl->type = dbfl_type_val; pfl->stat = prec->stat; pfl->sevr = prec->sevr; pfl->time = prec->time; pfl->field_type = DBF_LONG; + pfl->field_size = sizeof(epicsInt32); pfl->no_elements = 1; /* * use memcpy to avoid a bus error on From 90d9be1c00ebff5dee4341ab95a57bb92850b2c6 Mon Sep 17 00:00:00 2001 From: Joao Paulo Martins Date: Fri, 6 Sep 2019 11:53:28 +0200 Subject: [PATCH 15/47] Renaming mbbiRecord.dbd with POD file extension --- src/std/rec/{mbbiRecord.dbd => mbbiRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{mbbiRecord.dbd => mbbiRecord.dbd.pod} (100%) diff --git a/src/std/rec/mbbiRecord.dbd b/src/std/rec/mbbiRecord.dbd.pod similarity index 100% rename from src/std/rec/mbbiRecord.dbd rename to src/std/rec/mbbiRecord.dbd.pod From 4f31205188c9ebf3604ad151c5f05bd1386c877b Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 11:56:46 +0200 Subject: [PATCH 16/47] Rename stringinRecord.dbd -> stringinRecord.dbd.pod --- src/std/rec/{stringinRecord.dbd => stringinRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{stringinRecord.dbd => stringinRecord.dbd.pod} (100%) diff --git a/src/std/rec/stringinRecord.dbd b/src/std/rec/stringinRecord.dbd.pod similarity index 100% rename from src/std/rec/stringinRecord.dbd rename to src/std/rec/stringinRecord.dbd.pod From 6905ded0d059d56a3b346956102ac2d9c532c340 Mon Sep 17 00:00:00 2001 From: Joao Paulo Martins Date: Fri, 6 Sep 2019 12:14:55 +0200 Subject: [PATCH 17/47] First version of mbbi POD file --- src/std/rec/mbbiRecord.dbd.pod | 507 +++++++++++++++++++++++++++++++++ 1 file changed, 507 insertions(+) diff --git a/src/std/rec/mbbiRecord.dbd.pod b/src/std/rec/mbbiRecord.dbd.pod index 1f5724c92..2bbda6686 100644 --- a/src/std/rec/mbbiRecord.dbd.pod +++ b/src/std/rec/mbbiRecord.dbd.pod @@ -6,7 +6,186 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 B + +The normal use for the multi-bit binary input record is to read contiguous, +multiple bit inputs from hardware. The binary value represents a state from a +range of up to 16 states. The multi-bit input record interfaces with devices +that use more than one bit. + +Most device support modules obtain values from hardware and place the value in +RVAL. For these device support modules record processing uses RVAL to determine +the current state (VAL is given a value between 0 and 15). Device support +modules may optionally read a value directly into VAL. + +Soft device modules are provided to obtain input via database or channel access +links or via dbPutField or dbPutLink requests. Two soft device support modules +are provided: C<<< Soft Channel >>> allows VAL to be an arbitrary unsigned short +integer. C<<< Raw Soft Channel >>> reads the value into RVAL just like normal +device support modules. + +=head1 L + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=back + +=back + +=begin html + +



+ +=end html + +=recordtype mbbi + +=cut + recordtype(mbbi) { + +=head2 Parameter Fields + +The multi-bit binary input fields fall into the following categories: + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=head3 Scan Parameters + +The multi-bit binary input record has the standard fields for specifying under +what circumstances it will be processed. These fields are listed in L. In addition, L explains how these fields are +used. Note that I/O event scanning is only supported for those card types that +interrupt. + +=head3 Read and Convert Parameters + +The device support routines obtain the record's input from the device or link +specified in the INP field. For records that obtain their input from devices, +the INP field must contain the address of the I/O card, and the DTYP field must +specify the proper device support module. Be aware that the address format +differs according to the I/O bus used. See L
for +information on the format of hardware addresses. + +Two soft device support modules can be specified in DTYP C and +C<<< Raw Soft Channel >>>. + +C<<< Raw Soft Channel >>> reads the value into RVAL, +upon which the normal conversion process is undergone. C<<< Soft Channel >>> +reads any unsigned integer directly into VAL. For a soft mbbi record, the INP +field can be a constant, a database, or a channel access link. If INP is a +constant, then the VAL is initialized to the constant value but can be changed +at run-time via dbPutField or dbPutLink. See L
for +information on the format of database addresses. + +MASK is used by the raw soft channel read routine, and by typical device support +read routines, to select only the desired bits when reading the hardware +register. It is initialized to ((1 EE NOBT) - 1) by record +initialization. The user can configure the NOBT field, but the device support +routines may set it, in which case the value given to it by the user is simply +overridden. The device support routines may also override MASK or shift it +left by SHFT bits. If MASK is non-zero, only the bits specified by MASK will +appear in RVAL. + +Unless the device support routine specifies no conversion, RVAL is used to +determine VAL as follows: + +=over + +=item 1. + +RVAL is assigned to a temporary variable -- rval = RVAL + +=item 2. + +rval is shifted right SHFT number of bits. + +=item 3. + +A match is sought between rval and one of the state value fields, ZRVL-FFVL. + +=back + +Each of the fields, ZRVL-FFVL, represents one of the possible sixteen states +(not all sixteen have to be used). + +Alternatively, the input value can be read as a string, in which case, a match +is sought with one of the strings specified in the ZRST-FFST fields. Then RVAL +is set equal to the corresponding value for that string, and the conversion +process occurs. + +=fields VAL, INP, MASK, NOBT, RVAL, SHFT, ZRVL, ONVL, TWVL, THVL, FRVL, FVVL, SXVL, SVVL, EIVL, NIVL, TEVL, ELVL, TVVL, TTVL, FTVL, FFVL + +=head3 Operator Display Parameters + +These parameters are used to present meaningful data to the operator. They +display the value and other parameters of the mbbi record either textually or +graphically. The ZRST-FFST fields contain strings describing one of the possible +states of the record. The C<<< get_enum_str >>> and C<<< get_enum_strs >>> +record routines retrieve these strings for the operator. C<<< Get_enum_str >>> +gets the string corresponding to the value set in VAL, and C<<< get_enum_strs +>>> retrieves all the strings. + +See L for more on the record name (NAME) and +description (DESC) fields. + +=fields NAME, DESC, ZRST, ONST, TWST, THST, FRST, FVST, SXST, SVST, EIST, NIST, TEST, ELST, TVST, TTST, FTST, FFST + +=cut + include "dbCommon.dbd" field(VAL,DBF_ENUM) { prompt("Current Value") @@ -281,6 +460,30 @@ recordtype(mbbi) { interest(1) size(26) } + +=head3 Alarm Parameters + +The possible alarm conditions for multi-bit binary inputs are the SCAN, READ, +and state alarms. The state alarms are configured in the below severity fields. +These fields have the usual possible values for severity fields: NO_ALARM, +MINOR, and MAJOR. + +The unknown state severity (UNSV) field, if set to MINOR or MAJOR, triggers an +alarm when the record support routine cannot find a matching value in the state +value fields for C<<< rval >>>. + +The change of state severity (COSV) field triggers an alarm when any change of +state occurs, if set to MAJOR or MINOR. + +The other fields, when set to MAJOR or MINOR, trigger an alarm when VAL equals +the corresponding state. See the See L for a complete +explanation of discrete alarms and these fields. L lists other +fields related to a alarms that are common to all record types. + +=fields UNSV, COSV, ZRSV, ONSV, TWSV, THSV, FRSV, FVSV, SXSV, SVSV, EISV, NISV, TESV, ELSV, TVSV, TTSV, FTSV, FFSV + +=cut + field(ZRSV,DBF_MENU) { prompt("State Zero Severity") promptgroup("71 - Alarm 0-7") @@ -417,6 +620,26 @@ recordtype(mbbi) { interest(1) menu(menuAlarmSevr) } + +=head3 Run-time Parameters + +These parameters are used by the run-time code for processing the multi-bit +binary input. + +ORAW is used by record processing to hold the prior RVAL for use in determining +when to post a monitor event for the RVAL field. + +The LALM field implements the change of state alarm severity by holding the +value of VAL when the previous change of state alarm was issued. + +MLST holds the value when the last monitor for value change was triggered. + +SDEF is used by record support to save time if no states are defined. + +=fields ORAW, LALM, MLST, SDEF + +=cut + field(RVAL,DBF_ULONG) { prompt("Raw Value") pp(TRUE) @@ -451,6 +674,16 @@ recordtype(mbbi) { promptgroup("40 - Input") interest(1) } + +=head3 Simulation Mode Parameters + +The following fields are used to operate the mbbi record in the simulation mode. +See L for more information on these fields. + +=fields SIOL, SVAL, SIML, SIMM, SIMS + +=cut + field(SIOL,DBF_INLINK) { prompt("Sim Input Specifctn") promptgroup("90 - Simulate") @@ -475,4 +708,278 @@ recordtype(mbbi) { interest(2) menu(menuAlarmSevr) } + +=pod + +=begin html + +


+ +=end html + +=head2 Record Support + +=head3 Record Support Routines + +=head4 init_record + +This routine initializes SIMM with the value of SIML if SIML type is CONSTANT +link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise +initialized if SIOL is CONSTANT or PV_LINK. + +This routine next checks to see that device support is available and a device +support read routine is defined. If either does not exist, an error message is +issued and processing is terminated. + +Clears MASK and then sets the NOBT low order bits. + +If device support includes C, it is called. + +init_common is then called to determine if any states are defined. If states are +defined, SDEF is set to TRUE. + +=head4 process + +See next section. + +=head4 special + +Calls init_common to compute SDEF when any of the fields ZRVL, ... FFVL change +value. + +=head4 get_enum_str + +Retrieves ASCII string corresponding to VAL. + +=head4 get_enum_strs + +Retrieves ASCII strings for ZRST,...FFST. + +=head4 put_enum_str + +Checks if string matches ZRST,...FFST and if it does, sets VAL. + +=head3 Record Processing + +Routine process implements the following algorithm: + +=over + +=item 1. + +Check to see that the appropriate device support module exists. If it doesn't, +an error message is issued and processing is terminated with the PACT field +still set to TRUE. This ensures that processes will no longer be called for this +record. Thus error storms will not occur. + +=item 2. + +readValue is called. See L for more information. + +=item 3. + +If PACT has been changed to TRUE, the device support read routine has started +but has not completed reading a new input value. In this case, the processing +routine merely returns, leaving PACT TRUE. + +=item 4. + +Convert: + +=over + +=item * status=read_mbbi + +=item * PACT = TRUE + +=item * C is called. + +=item * If status is 0, then determine VAL + +=over + +=item * Set rval = RVAL + +=item * Shift rval right SHFT bits + +=back + +=item * If at least one state value is defined + +=over + +=item * Set UDF to TRUE + +=back + +=item * If RVAL is ZRVL,...,FFVL then set + +=over + +=item * VAL equals index of state + +=item * UDF set to FALSE + +=back + +=item * Else set VAL = undefined + +=over + +=item * Else set VAL = RVAL + +=back + +=item * Set UDF to FALSE + +=over + +=item * If status is 1, return 0 + +=item * If status is 2, set status = 0 + +=back + +=back + +=item 5. + +Check alarms. This routine checks to see if the new VAL causes the alarm status +and severity to change. If so, NSEV, NSTA and LALM are set. + +=item 6. + +Check to see if monitors should be invoked. + +=over + +=item * Alarm monitors are invoked if the alarm status or severity has changed. + +=item * Archive and value change monitors are invoked if MLST is not equal to VAL. + +=item * Monitors for RVAL are checked whenever other monitors are invoked. + +=item * NSEV and NSTA are reset to 0. + +=back + +=item 7. + +Scan forward link if necessary, set PACT FALSE, and return. + +=back + + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each input record must have an associated set of device support routines. + +The primary responsibility of the device support routines is to obtain a new raw +input value whenever read_mbbi is called. The device support routines are +primarily interested in the following fields: + +=fields PACT, DPVT, UDF, NSEV, NSTA, NOBT, VAL, INP, RVAL, MASK, SHFT + +=begin html + +


+ +=end html + +=head3 Device Support Routines + +Device support consists of the following routines: + +=head4 long report(int level) + +This optional routine is called by the IOC command C and is passed the +report level that was requested by the user. +It should print a report on the state of the device support to stdout. +The C parameter may be used to output increasingly more detailed +information at higher levels, or to select different types of information with +different levels. +Level zero should print no more than a small summary. + +=head4 long init(int after) + +This optional routine is called twice at IOC initialization time. +The first call happens before any of the C calls are made, with +the integer parameter C set to 0. +The second call happens after all of the C calls have been made, +with C set to 1. + +=head4 init_record + + init_record(precord) + +This routine is optional. If provided, it is called by the record support +C routine. If it uses MASK, it should shift it as necessary and +also give SHFT a value. + +=head4 get_ioint_info + + get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt) + +This routine is called by the ioEventScan system each time the record is added +or deleted from an I/O event scan list. cmd has the value (0,1) if the record is +being (added to, deleted from) an I/O event list. It must be provided for any +device type that can use the I/O Event scanner. + +=head4 read_mbbi + + read_mbbi(precord) + +This routine must provide a new input value. It returns the following values: + +=over + +=item * + +0: Success. A new raw value is placed in RVAL. The record support module +determines VAL from RVAL, SHFT, and ZEVL ... FFVL. + +=item * + +2: Success, but don't modify VAL. + +=item * + +Other: Error. + +=back + +=head3 Device Support For Soft Records + +Two soft device support modules C<<< Soft Channel >>> and C<<< Raw Soft Channel +>>> are provided for multi-bit binary input records not related to actual +hardware devices. The INP link type must be either CONSTANT, DB_LINK, or +CA_LINK. + +=head4 Soft Channel + +read_mbbi always returns a value of 2, which means that no conversion is +performed. + +If the INP link type is constant, then the constant value is stored into VAL by +C, and UDF is set to FALSE. VAL can be changed via dbPut +requests. If the INP link type is PV_LINK, then dbCaAddInlink is called by +C. + +read_mbbi calls recGblGetLinkValue to read the current value of VAL. See L. + +If the return status of recGblGetLinkValue is zero, then read_mbbi sets UDF to +FALSE. The status of recGblGetLinkValue is returned. + +=head4 Raw Soft Channel + +This module is like the previous except that values are read into RVAL, VAL is +computed from RVAL, and read_mbbi returns a value of 0. Thus the record +processing routine will determine VAL in the normal way. + + +=cut + } From d7d142650b8f218074c3bf067c1b566f0f3e8db3 Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 14:11:20 +0200 Subject: [PATCH 18/47] Adding POD to stringin record --- src/std/rec/stringinRecord.dbd.pod | 301 ++++++++++++++++++++++++++++- 1 file changed, 295 insertions(+), 6 deletions(-) diff --git a/src/std/rec/stringinRecord.dbd.pod b/src/std/rec/stringinRecord.dbd.pod index 5b0b76813..2dd305502 100644 --- a/src/std/rec/stringinRecord.dbd.pod +++ b/src/std/rec/stringinRecord.dbd.pod @@ -6,6 +6,72 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 String Input Record (stringin) + +The string input record retrieves an arbitrary ASCII string of up to 40 +characters. Several device support routines are available, all of which are soft +device support for retrieving values from other records or other software +components. + +=head2 Contents + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=back + +=back + +=begin html + +
+
+
+ +=end html + +=recordtype stringin + +=cut + menu(stringinPOST) { choice(stringinPOST_OnChange,"On Change") choice(stringinPOST_Always,"Always") @@ -19,17 +85,56 @@ recordtype(stringin) { pp(TRUE) size(40) } - field(OVAL,DBF_STRING) { - prompt("Previous Value") - special(SPC_NOMOD) - interest(3) - size(40) - } + +=head2 Parameter Fields + +=head3 Scan Parameters + +The string input record has the standard fields for specifying under what +circumstances it will be processed. These fields are listed in +L. +In addition, +L +explains how these fields are used. + +=head3 Read Parameters + +The INP field determines where the string input record gets its string. It can +be a database or channel access link, or a constant. If constant, the VAL field +is initialized with the constant and can be changed via dbPuts. Otherwise, the +string is read from the specified location each time the record is processed and +placed in the VAL field. The maximum number of characters that the string in VAL +can be is 40. In addition, the appropriate device support module must be entered +into the DTYP field. + +See L
+for information on specifying links. + +=fields VAL, INP, DTYP + +=cut + field(INP,DBF_INLINK) { prompt("Input Specification") promptgroup("40 - Input") interest(1) } + +=head3 Monitor Parameters + +These parameters are used to specify when the monitor post should be sent by +C routine. There are two possible choices: + +=head4 Menu stringinPOST + +=menu stringinPOST + +APST is used for archiver monitors and MPST is for all other type of monitors. + +=fields MPST, APST + +=cut + field(MPST,DBF_MENU) { prompt("Post Value Monitors") promptgroup("80 - Display") @@ -42,6 +147,44 @@ recordtype(stringin) { interest(1) menu(stringinPOST) } + +=head3 Operator Display Parameters + +See L +for more on the record name (NAME) and description (DESC) fields. + +=fields NAME, DESC + +=head3 Alarm Parameters + +The string input record has the alarm parameters common to all record types. +L +lists other fields related to a alarms that are common to all record types. + +=head3 Run-time and Simulation Mode Parameters + +The old value field (OVAL) of the string input is used to implement value change +monitors for VAL. If VAL is not equal to OVAL, then monitors are triggered. + +=fields OVAL + + + +The following fields are used to operate the string input in the simulation +mode. See +L +for more information on simulation mode fields. + +=fields SIOL, SVAL, SIML, SIMM, SIMS + +=cut + + field(OVAL,DBF_STRING) { + prompt("Previous Value") + special(SPC_NOMOD) + interest(3) + size(40) + } field(SIOL,DBF_INLINK) { prompt("Sim Input Specifctn") promptgroup("90 - Simulate") @@ -68,4 +211,150 @@ recordtype(stringin) { interest(2) menu(menuAlarmSevr) } + +=begin html + +
+
+
+ +=end html + +=head2 Record Support + +=head3 Record Support Routines (stringinRecord.c) + +=head4 init_record + + long (*init_record)(struct dbCommon *precord, int pass) + +This routine initializes SIMM with the value of SIML if SIML type is CONSTANT +link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise +initialized if SIOL is CONSTANT or PV_LINK. + +This routine next checks to see that device support is available and a record +support read routine is defined. If either does not exist, an error message is +issued and processing is terminated. + +If device support includes an C routine it is called. + +=head4 process + + long (*process)(struct dbCommon *precord) + +See L. + +=head3 Record Processing + +Routine process implements the following algorithm: + +=over + +=item 1. + +Check to see that the appropriate device support module exists. If it doesn't, +an error message is issued and processing is terminated with the PACT field +still set to TRUE. This ensures that processes will no longer be called for this +record. Thus error storms will not occur. + +=item 2. + +readValue is called. See +L +for more information on simulation mode fields and how they affect input. + +=item 3. + +If PACT has been changed to TRUE, the device support read routine has started +but has not completed reading a new input value. In this case, the processing +routine merely returns, leaving PACT TRUE. + +=item 4. + +C is called. + +=item 5. + +Check to see if monitors should be invoked. + +=over + +=item * + +Alarm monitors are invoked if the alarm status or severity has changed. + +=item * + +Archive and value change monitors are invoked if OVAL is not equal to VAL. + +=item * + +NSEV and NSTA are reset to 0. + +=back + +=item 6. + +Scan forward link if necessary, set PACT FALSE, and return. + +=back + +=begin html + +
+
+
+ +=end html + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each stringin input record must have an associated set of device support +routines. The primary responsibility of the device support routines is to obtain +a new ASCII string value whenever read_stringin is called. The device support +routines are primarily interested in the following fields: + +=fields PACT, DPVT, UDF, VAL, INP + +=head3 Device Support Routines (devSiSoft.c) + +=head4 init_record + + long init_record(stringinRecord *prec) + +This routine is optional. If provided, it is called by the record support +C routine. + +=head4 read_stringin + + long read_stringin(stringinRecord *prec) + +This routine must provide a new input value. It returns the following values: + +=over + +=item * 0: Success. A new ASCII string is stored into VAL. + +=item * Other: Error. + +=back + +=head3 Device Support for Soft Records + +The C<<< Soft Channel >>> module places a value directly in VAL. + +If the INP link type is constant, the double constant, if non-zero, is converted +to a string and stored into VAL by C, and UDF is set to FALSE. If +the INP link type is PV_LINK, then dbCaAddInlink is called by C. + +read_stringin calls recGblGetLinkValue to read the current value of VAL. See +L. + +If the return status of recGblGetLinkValue is zero, then read_stringin sets UDF +to FALSE. The status of recGblGetLinkValue is returned. + +=cut + } From 4f63bf139f085522ce1ab7d629076fef0f67fa9c Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 14:36:36 +0200 Subject: [PATCH 19/47] Rename stateRecord.dbd -> stateRecord.dbd.pod --- src/std/rec/{stateRecord.dbd => stateRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{stateRecord.dbd => stateRecord.dbd.pod} (100%) diff --git a/src/std/rec/stateRecord.dbd b/src/std/rec/stateRecord.dbd.pod similarity index 100% rename from src/std/rec/stateRecord.dbd rename to src/std/rec/stateRecord.dbd.pod From e5f86831448ca1d34563db3d67d55c55b256e5f8 Mon Sep 17 00:00:00 2001 From: Joao Paulo Martins Date: Fri, 6 Sep 2019 15:00:52 +0200 Subject: [PATCH 20/47] Renaming dbd file to dbd.pod --- src/std/rec/{mbboDirectRecord.dbd => mbboDirectRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{mbboDirectRecord.dbd => mbboDirectRecord.dbd.pod} (100%) diff --git a/src/std/rec/mbboDirectRecord.dbd b/src/std/rec/mbboDirectRecord.dbd.pod similarity index 100% rename from src/std/rec/mbboDirectRecord.dbd rename to src/std/rec/mbboDirectRecord.dbd.pod From 4685f7567b32b3d58ae8bf3026b2b5a332022e12 Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 15:13:25 +0200 Subject: [PATCH 21/47] Rename permissiveRecord.dbd -> permissiveRecord.dbd.pod --- src/std/rec/{permissiveRecord.dbd => permissiveRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{permissiveRecord.dbd => permissiveRecord.dbd.pod} (100%) diff --git a/src/std/rec/permissiveRecord.dbd b/src/std/rec/permissiveRecord.dbd.pod similarity index 100% rename from src/std/rec/permissiveRecord.dbd rename to src/std/rec/permissiveRecord.dbd.pod From 9255256f1524fd7cc9cf43639aae65d397ac9cf6 Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 15:48:46 +0200 Subject: [PATCH 22/47] Added POD to permissive record with a note that it is deprecated. --- src/std/rec/permissiveRecord.dbd.pod | 150 +++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 11 deletions(-) diff --git a/src/std/rec/permissiveRecord.dbd.pod b/src/std/rec/permissiveRecord.dbd.pod index 7eb04bf95..8e0747fe9 100644 --- a/src/std/rec/permissiveRecord.dbd.pod +++ b/src/std/rec/permissiveRecord.dbd.pod @@ -6,8 +6,114 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Permissive Record (permissive) + +The permissive record is for communication between a server and a client. An +example would be a sequence program server and an operator interface client. By +using multiple permissive records a sequence program can communicate its current +state to the client. + +B + +=head2 Contents + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=back + +=back + +=begin html + +
+
+
+ +=end html + +=recordtype permissive + +=cut + recordtype(permissive) { include "dbCommon.dbd" + +=head2 Parameter Fields + +=head3 Scan Parameters + +The permissive record has the standard fields for specifying under what +circumstances the record will be processed. These fields are listed in +L. +In addition, +L + explains how these fields are used. Since the permissive record supports + no direct interfaces to hardware, its SCAN field cannot be C<<< I/O Intr >>>. + +=head3 Client-server Parameters + +The client and server communicate through the VAL and watchdog flag (WFLG) +fields. At initialization, both fields are set equal to 0, which means OFF. The +server sets WFLG equal to ON when it is ready to accept a request. The client +monitors WFLG and when WFLG equals 1, the client-server action is performed (a +private matter between server and client). + +When WFLG is off--when the server is busy--the client program may turn the VAL +field from OFF to ON. After the server finishes its task, it will notice that +VAL is ON and will turn both WFLG and VAL OFF and performs the requested +service. + +Note that when WFLG is ON, the client program ''must not'' turn VAL to on. + +=fields VAL, WFLG + +=cut + + field(VAL,DBF_USHORT) { + prompt("Status") + promptgroup("40 - Input") + asl(ASL0) + pp(TRUE) + } + field(WFLG,DBF_USHORT) { + prompt("Wait Flag") + pp(TRUE) + } + +=head3 Operator Display Parameters + +The label field (LABL) contains a string given to it that should describe the +record in further detail. In addition to the DESC field. See +L +for more on the record name (NAME) and description (DESC) fields. + +=fields LABL, NAME, DESC + +=cut + field(LABL,DBF_STRING) { prompt("Button Label") promptgroup("80 - Display") @@ -15,24 +121,46 @@ recordtype(permissive) { interest(1) size(20) } - field(VAL,DBF_USHORT) { - prompt("Status") - promptgroup("40 - Input") - asl(ASL0) - pp(TRUE) - } + +=head3 Alarm Parameters + +The Permissive record has the alarm parameters common to all record types. +L +lists other fields related to a alarms that are common to all record types. + +=head3 Run-time Parameters + +These fields are used to trigger monitors for each field. Monitors for the VAL +field are triggered when OVAL, the old value field, does not equal VAL. +Likewise, OFLG causes monitors to be invoked for WFLG when WFLG does not equal +OLFG. + +=fields OVAL, OFLG + +=cut + field(OVAL,DBF_USHORT) { prompt("Old Status") special(SPC_NOMOD) interest(3) } - field(WFLG,DBF_USHORT) { - prompt("Wait Flag") - pp(TRUE) - } field(OFLG,DBF_USHORT) { prompt("Old Flag") special(SPC_NOMOD) interest(3) } -} + +=head2 Record Support + +=head3 Record Support Routines (permissiveRecord.c) + +=head4 process + + long (*process)(struct dbCommon *precord) + +process sets UDF to FALSE, triggers monitors on VAL and WFLG when they change, +and scans the forward link if necessary. + +=cut + +} \ No newline at end of file From 0d3cc5a20a41fc7af4004585a9555d01d482e211 Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 15:03:23 +0200 Subject: [PATCH 23/47] Added POD to state record with a note that it is deprecated --- src/std/rec/stateRecord.dbd.pod | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/std/rec/stateRecord.dbd.pod b/src/std/rec/stateRecord.dbd.pod index 6e43ddbba..8734f01bd 100644 --- a/src/std/rec/stateRecord.dbd.pod +++ b/src/std/rec/stateRecord.dbd.pod @@ -6,8 +6,93 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 State Record (state) + +The state record is a means for a state program to communicate with the operator +interface. Its only function is to provide a place in the database through which +the state program can inform the operator interface of its state by storing an +arbitrary ASCII string in its VAL field. + +B + +=head2 Contents + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=back + +=back + +=begin html + +
+
+
+ +=end html + +=recordtype state + +=cut + recordtype(state) { include "dbCommon.dbd" + +=head2 Parameter Fields + +=head3 Scan Parameters + +The state record has the standard fields for specifying under what circumstances +it will be processed. These fields are listed in +L. +In addition, +L +explains how these fields are used. + +=head3 Operator Display Parameters + +See L +for more on the record name (NAME) and description (DESC) fields. + +=fields NAME, DESC + +=head3 Alarm Parameters + +The state record has the alarm parameters common to all record types. +L +lists other fields related to a alarms that are common to all record types. + +=head3 Run-time Parameters + +These parameters are used by the application code to convey the state of the +program to the operator interface. The VAL field holds the string retrieved from +the state program. The OVAL is used to implement monitors for the VAL field. +When the string in OVAL differs from the one in VAL, monitors are triggered. +They represent the current state of the sequence program. + +=fields VAL, OVAL + +=cut + field(VAL,DBF_STRING) { prompt("Value") promptgroup("40 - Input") @@ -21,4 +106,18 @@ recordtype(state) { interest(3) size(20) } + +=head2 Record Support + +=head3 Record Support Routines (stateRecord.c) + +=head4 process + + long (*process)(struct dbCommon *precord) + +process triggers monitors on VAL when it changes and scans the forward link if +necessary. + +=cut + } From 9d4b652c5e66145f7fac0bea5e2a90939dc8b6e2 Mon Sep 17 00:00:00 2001 From: Joao Paulo Martins Date: Fri, 6 Sep 2019 17:20:54 +0200 Subject: [PATCH 24/47] First version of mbbo POD file --- src/std/rec/mbboDirectRecord.dbd.pod | 380 +++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) diff --git a/src/std/rec/mbboDirectRecord.dbd.pod b/src/std/rec/mbboDirectRecord.dbd.pod index 0b4285e32..e730bc854 100644 --- a/src/std/rec/mbboDirectRecord.dbd.pod +++ b/src/std/rec/mbboDirectRecord.dbd.pod @@ -6,7 +6,153 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 B + +The mbboDirect record performs the opposite function to that of the mbbiDirect +record. It accumulates bits (in the fields B0 - BF) as unsigned characters, and +converts them to a word which is then written out to hardware. If a bit field is +non-zero, it is interpreted as a binary 1. On the other hand, if it is zero, it +is interpreted as a binary 0. + +=head1 L + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=back + +=back + +=begin html + +


+ +=end html + +=recordtype mbboDirect + +=cut + recordtype(mbboDirect) { + +=head2 Parameter Fields + +The mbboDirect record's fields fall into the following categories: + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=head3 Scan Parameters + +The mbboDirect record has the standard fields for specifying under what +circumstances it will be processed. These fields are listed in L. +In addition, L explains how these fields are used. Note +that I/O event scanning is only supported for those card types that +interrupt. + +=head3 Desired Output Parameters + +The mbboDirect record, like all output records, must specify where its output +originates. The output mode select field (OMSL) determines whether the output +originates from another record or from database access. When set to C<<< +closed_loop >>>, the desired output is retrieved from the link specified in the +desired output (DOL) field--which can specify either a database or channel +access link--and placed into the VAL field. When set to C<<< supervisory >>>, +the DOL field is ignored and the current value of VAL is used. The desired +output can be written into the VAL field via dpPuts at run-time when the record +is in C<<< supervisory >>> mode. DOL can also be a constant, in which case VAL +is initialized to the constant value. Note that OMSL cannot be C<<< closed_loop +>>> when DOL is a constant. See L
for information on how +to specify database links. + +VAL is then converted to RVAL in the routine described in the next section. +However, the C<<< Soft Channel >>> device support module for the mbboDirect +record writes the VAL field's value without any conversion. + +=fields OMSL, DOL, VAL + +=head3 Convert and Write Parameters + +For records that are to write values to hardware devices, the OUT output link +must contain the address of the I/O card, and the DTYP field must specify +the proper device support module. Be aware that the address format differs +according to the I/O bus used. See L
for information +on the format of hardware addresses. + +If the mbboDirect record does not use the C<<< Soft Channel >>> device support +module, then VAL is converted to RVAL, and RVAL is the actual 16-bit word sent +out. RVAL is set equal to VAL and then shifted left by the number of bits +specified in the SHFT field (the SHFT value is set by device support and is not +configurable by the user). RVAL is then sent out to the location specified in +the OUT field. + +For mbboDirect records that specify a database link, a channel access link, or a +constant, the DTYP field must specify either one of two soft device support +routines--{Soft Channel} or C<<< Raw Soft Channel >>>. The difference between +the two is that C<<< Soft Channel >>> writes the desired output value from VAL +directly to the output link while C<<< Raw Soft Channel >>> writes the value +from RVAL to the output link after it has undergone the conversion described +above. See L
for information on how to specify database +links. + +=fields OUT, RVAL, SHFT, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, BA, BB, BC, BD, BE, BF + +=head3 Operator Display Parameters + +See L for more on the record name (NAME) and +description (DESC) fields. + +=fields NAME, DESC + +=cut + include "dbCommon.dbd" field(VAL,DBF_USHORT) { prompt("Word") @@ -184,6 +330,49 @@ recordtype(mbboDirect) { promptgroup("50 - Output") interest(1) } + +=head3 Alarm Parameters + +The possible alarm conditions for mbboDirect records are the SCAN, READ, and +INVALID alarms. The SCAN and READ alarms are not configurable by the user since +they are always of MAJOR severity. See L for a complete +explanation of Scan and Read alarms. + +The IVOA field specifies an action to take when the INVALID alarm is triggered. +There are three possible actions: C<<< Continue normally >>>, C<<< Don't drive +outputs >>>, or C<<< Set output to IVOV >>>. When C<<< Set output to IVOV >>> is +specified and a INVALID alarm is triggered, the record will write the value in +the IVOV field to output. See L for more +information. L lists other fields related to a alarms that are +common to all record types. + +=fields IVOA, IVOV + +=head3 Run-time and Simulation Mode Parameters + +These parameters are used by the run-time code for processing the mbbo Direct +record. + +MASK is used by device support routine to read the hardware register. Record +support sets low order NOBT bits. Device support can shift this value. + +MLST holds the value when the last monitor for value change was triggered. + +=fields NOBT, ORAW, MASK, MLST + +The following fields are used to operate the mbboDirect record in the simulation +mode. See L for more information on the simulation mode fields. + +=fields SIOL, SIML, SIMM, SIMS + +=begin html + +


+ +=end html + +=cut + field(SIOL,DBF_OUTLINK) { prompt("Sim Output Specifctn") promptgroup("90 - Simulate") @@ -216,4 +405,195 @@ recordtype(mbboDirect) { promptgroup("50 - Output") interest(2) } + +=head2 Record Support + +=head3 Record Support Routines + +=head4 init_record + +This routine initializes SIMM if SIML is a constant or creates a channel access +link if SIML is PV_LINK. If SIOL is PV_LINK a channel access link is created. + +This routine next checks to see that device support is available.The routine +next checks to see if the device support write routine is defined. If either +device support or the device support write routine does not exist, an error +message is issued and processing is terminated. + +If DOL is a constant, then VAL is initialized to its value and UDF is set to +FALSE. + +MASK is cleared and then the NOBT low order bits are set. + +If device support includes C, it is called. + +If device support returns success, VAL is then set from RVAL and UDF is set to +FALSE. + +=head4 Process + +See next section. + +=head3 Record Processing + +Routine process implements the following algorithm: + +=over + +=item 1. + +Check to see that the appropriate device support module exists. If it doesn't, +an error message is issued and processing is terminated with the PACT field +still set to TRUE. This ensures that processes will no longer be called for this +record. Thus error storms will not occur. + +=item 2. + +If PACT is FALSE + +=over + +=item * If DOL is DB_LINK and OMSL is CLOSED_LOOP + +=over + +=item * Get value from DOL + +=item * Set PACT to FALSE + +=back + +=back + +=item 3. + +Convert + +=over + +=item * If PACT is FALSE, compute RVAL + +=over + +=item * Set RVAL = VAL + +=item * Shift RVAL left SHFT bits + +=back + +=item * Status=write_mbboDirect + +=back + +=item 4. + +If PACT has been changed to TRUE, the device support write output routine has +started but has not completed writing the new value. In this case, the +processing routine merely returns, leaving PACT TRUE. + +=item 5. + +Check to see if monitors should be invoked. + +=over + +=item * Alarm monitors are invoked if the alarm status or severity has changed. + +=item * Archive and value change monitors are invoked if MLST is not equal to VAL. + +=item * Monitors for RVAL and RBV are checked whenever other monitors are invoked. + +=item * NSEV and NSTA are reset to 0. + +=back + +=item 6. + +Scan forward link if necessary, set PACT FALSE, and return. + +=back + +=begin html + +


+ +=end html + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each mbboDirect record must have an associated set of device support routines. +The primary responsibility of the device support routines is to obtain a new raw +mbbo value whenever write_mbboDirect is called. The device support routines are +primarily interested in the following fields: + +=fields PACT, DPVT, UDF, NSEV, NSTA, NOBT, OUT, RVAL, RBV, MASK, SHFT + +=head3 Device Support Routines + +Device support consists of the following routines: + +=head4 long report(int level) + +This optional routine is called by the IOC command C and is passed the +report level that was requested by the user. +It should print a report on the state of the device support to stdout. +The C parameter may be used to output increasingly more detailed +information at higher levels, or to select different types of information with +different levels. +Level zero should print no more than a small summary. + +=head4 long init(int after) + +This optional routine is called twice at IOC initialization time. +The first call happens before any of the C calls are made, with +the integer parameter C set to 0. +The second call happens after all of the C calls have been made, +with C set to 1. + +=head4 init_record + + init_record(precord) + +This routine is optional. If provided, it is called by the record support +C routine. If MASK is used, it should be shifted if necessary and +SHFT given a value. + +=head4 get_ioint_info + + get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt) + +This routine is called by the ioEventScan system each time the record is added +or deleted from an I/O event scan list. cmd has the value (0,1) if the +record is being (added to, deleted from) an I/O event list. It must be +provided for any device type that can use the ioEvent scanner. + +=head4 write_mbboDirect + + write_mbboDirect(precord) + +This routine must output a new value. It returns the following values: + +=over + +=item * 0: Success. + +=item * Other: Error. + +=back + +=head3 Device Support For Soft Records + +This C<<< SOft Channel >>> module writes the current value of VAL. + +If the OUT link type is PV_LINK, then dbCaAddInlink is called by +C. + +write_mbboDirect calls recGblPutLinkValue to write the current value of VAL. + +See L. + +=cut + } From f08b412a189678f3c63f6ff3216d2cc605a39d19 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 18 Sep 2019 14:43:08 -0500 Subject: [PATCH 25/47] Have CA Repeater cd to / before running to avoid holding the CWD open unnecessarily. --- src/ca/client/caRepeater.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ca/client/caRepeater.cpp b/src/ca/client/caRepeater.cpp index 9879af2b4..03cb8957d 100644 --- a/src/ca/client/caRepeater.cpp +++ b/src/ca/client/caRepeater.cpp @@ -32,10 +32,12 @@ #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #include "epicsAssert.h" +#include "osiUnistd.h" #include "udpiiu.h" int main() { + chdir ( "/" ); ca_repeater (); return ( 0 ); } From 643d58fd0496b03c6ddd1d46bcae8de1ddce5283 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 2 Oct 2019 15:49:12 -0400 Subject: [PATCH 26/47] appveyor-ci: completely remove cygwin builds --- appveyor.yml | 7 ------- ci/appveyor-make.bat | 20 +------------------- ci/appveyor-prepare.bat | 29 ++--------------------------- 3 files changed, 3 insertions(+), 53 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 21ec93c86..ff829f801 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,7 +46,6 @@ environment: - TOOLCHAIN: 14.0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 TOOLCHAIN: 2017 - - TOOLCHAIN: cygwin - TOOLCHAIN: mingw APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -61,12 +60,6 @@ matrix: # VS Express installs don't have the 64 bit compiler - platform: x64 TOOLCHAIN: 10.0 - # Cygwin static-debug has compiler problems - - configuration: static-debug - TOOLCHAIN: cygwin - # Cygwin x86 install is currently (08/2019) broken (libncursesw-devel fails) - - platform: x86 - TOOLCHAIN: cygwin #---------------------------------# diff --git a/ci/appveyor-make.bat b/ci/appveyor-make.bat index 9cd8fe684..8d976d93d 100644 --- a/ci/appveyor-make.bat +++ b/ci/appveyor-make.bat @@ -1,6 +1,6 @@ :: Universal build script for AppVeyor (https://ci.appveyor.com/) :: Environment: -:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw] +:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/mingw] :: CONFIGURATION - determines EPICS build [dynamic/static] :: PLATFORM - architecture [x86/x64] :: @@ -20,24 +20,6 @@ echo [INFO] Platform: %OS% set "MAKEARGS=-j2 -Otarget" if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS= -if "%TOOLCHAIN%"=="cygwin" ( - set "MAKE=make" - if "%OS%"=="64BIT" ( - set "EPICS_HOST_ARCH=cygwin-x86_64" - set "INCLUDE=C:\cygwin64\include;%INCLUDE%" - set "PATH=C:\cygwin64\bin;%PATH%" - echo [INFO] Cygwin Toolchain 64bit - ) else ( - set "EPICS_HOST_ARCH=cygwin-x86" - set "INCLUDE=C:\cygwin\include;%INCLUDE%" - set "PATH=C:\cygwin\bin;%PATH%" - echo [INFO] Cygwin Toolchain 32bit - ) - echo [INFO] Compiler Version - gcc -v - goto Finish -) - if "%TOOLCHAIN%"=="mingw" ( set "MAKE=mingw32-make" if "%OS%"=="64BIT" ( diff --git a/ci/appveyor-prepare.bat b/ci/appveyor-prepare.bat index 9f105ee96..a685dbfb3 100644 --- a/ci/appveyor-prepare.bat +++ b/ci/appveyor-prepare.bat @@ -1,12 +1,12 @@ :: Build script for AppVeyor (https://ci.appveyor.com/) :: Environment: -:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw] +:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/mingw] :: CONFIGURATION - determines EPICS build [dynamic/static, -debug] :: PLATFORM - "x86" -> use 32bit architecture :: :: Prepares an Appveyor build by excuting the following steps :: - Set up configure\CONFIG_SITE for static vs. dynamic build -:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor +:: - Install Mingw (TOOLCHAIN setting) in the in the appropriate flavor :: - Download and install Make-4.1 from EPICS download page Setlocal EnableDelayedExpansion @@ -16,31 +16,6 @@ if "%PLATFORM%"=="x86" set OS=32BIT echo [INFO] Platform: %OS% -if "%TOOLCHAIN%"=="cygwin" ( - echo.%CONFIGURATION% | findstr /C:"static">nul && ( - echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE - echo STATIC_BUILD=YES>> configure\CONFIG_SITE - echo [INFO] EPICS set up for static build - ) || ( - echo [INFO] EPICS set up for dynamic build - ) - echo.%CONFIGURATION% | findstr /C:"debug">nul && ( - echo HOST_OPT=NO>> configure\CONFIG_SITE - echo [INFO] EPICS set up for debug build - ) || ( - echo [INFO] EPICS set up for optimized build - ) - if "%OS%"=="64BIT" ( - echo [INFO] Installing Cygwin 64bit and dependencies - @powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')" - C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel" - ) else ( - echo [INFO] Installing Cygwin 32bit and dependencies - @powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')" - C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel" - ) -) - if "%TOOLCHAIN%"=="mingw" ( echo.%CONFIGURATION% | findstr /C:"static">nul && ( echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE From 1c93726ee6996f22aedf7887c5ce0d0d2c2ed89e Mon Sep 17 00:00:00 2001 From: Niamh Dougan Date: Fri, 6 Sep 2019 13:00:00 +0200 Subject: [PATCH 27/47] renamed RELEASE_NOTES.html -> RELEASE_NOTES.md --- documentation/{RELEASE_NOTES.html => RELEASE_NOTES.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename documentation/{RELEASE_NOTES.html => RELEASE_NOTES.md} (100%) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.md similarity index 100% rename from documentation/RELEASE_NOTES.html rename to documentation/RELEASE_NOTES.md From 292dfe8e16d0d2f325541025fecc8497af5c2b7d Mon Sep 17 00:00:00 2001 From: Niamh Dougan Date: Fri, 6 Sep 2019 13:00:54 +0200 Subject: [PATCH 28/47] Convert RELEASE_NOTES from html to .md Reformat relocations table, escape words with underscores inside `back-ticks`. --- documentation/RELEASE_NOTES.md | 2014 ++++++++++++++------------------ 1 file changed, 889 insertions(+), 1125 deletions(-) diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 6f2019379..133c823a0 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -1,927 +1,865 @@ - - - - - EPICS Base R3.15.6 Release Notes - +# EPICS Base Release 3.15.7 - -

EPICS Base Release 3.15.7

+This version of EPICS Base has not been released yet. -

This version of EPICS Base has not been released yet.

- - -

Changes made on the 3.15 branch since 3.15.6

+## Changes made on the 3.15 branch since 3.15.6 -

Add option to avoid CALLBACK conflict

+### Add option to avoid CALLBACK conflict -

If a macro EPICS_NO_CALLBACK is defined, then callback.h will no longer (re)define CALLBACK. +If a macro `EPICS_NO_CALLBACK` is defined, then callback.h will no longer (re)define CALLBACK. The name 'CALLBACK' is used by the WIN32 API, and redefinition in callback.h cause errors if some windows headers are later included. -

-

Code which defines EPICS_NO_CALLBACK, but still wishes to use callbacks, should use +Code which defines `EPICS_NO_CALLBACK`, but still wishes to use callbacks, should use the alternate name 'epicsCallback' introduced in 3.15.6, 3.16.2, and 7.0.2. It is also possible, though not encouraged, to use 'struct callbackPvt' -which has been present since the callback API was introduced.

+which has been present since the callback API was introduced. -

Cleaning up with Multiple CA contexts in a Process

+### Cleaning up with Multiple CA contexts in a Process -

Bruno Martins reported a problem with the CA client library at shutdown in a +Bruno Martins reported a problem with the CA client library at shutdown in a process that uses multiple CA client contexts. The first context that triggers the CA client exit handler prevents any others from being able to clean up because it resets the ID of an internal epicsThreadPrivate variable which is shared by all clients. This action has been removed from the client library, -which makes cleanup of clients like this possible.

+which makes cleanup of clients like this possible. -

Perl CA bindings fixed for macOS Mojave

+### Perl CA bindings fixed for macOS Mojave -

Apple removed some Perl header files from macOS Mojave that were available +Apple removed some Perl header files from macOS Mojave that were available in their SDK, requiring a change to the include paths used when compiling the CA bindings. The new version should build on new and older macOS versions, and these changes may also help other targets that have an incomplete installation of Perl (the build will continue after printing a warning that the Perl CA -bindings could not be built).

+bindings could not be built). -

Routine epicsTempName() removed from libCom

+### Routine `epicsTempName()` removed from libCom -

This routine was a simple wrapper around the C89 function tmpnam() +This routine was a simple wrapper around the C89 function `tmpnam()` which is now seen as unsafe and causes warning messages to be generated by most modern compilers. The two internal uses of this function have been -modified to call epicsTempFile() instead. We were unable to find any +modified to call `epicsTempFile()` instead. We were unable to find any published code that used this function, so it was removed immediately instead -of being deprecated.

+of being deprecated. -

DBD Parsing of Record Types

+### DBD Parsing of Record Types -

The Perl DBD file parser has been made slightly more liberal; the order in +The Perl DBD file parser has been made slightly more liberal; the order in which DBD files must be parsed is now more flexible, so that a record type definition can now be parsed after a device support that referred to that record type. A warning message will be displayed when the device support is seen, but the subsequent loading of the record type will be accepted without triggering an error. See -Launchpad bug -#1801145.

+[Launchpad bug 1801145](https://bugs.launchpad.net/epics-base/+bug/1801145). -

menuScan and several record types documented with POD

+### menuScan and several record types documented with POD -

The EPICS Wiki pages describing a number of standard record types has been +The EPICS Wiki pages describing a number of standard record types has been converted into the Perl POD documentation format and added to the DBD files, so at build-time an HTML version of these documents is generated and installed -into the htmls directory. Thanks to Tony Pietryla.

+into the htmls directory. Thanks to Tony Pietryla. -

CA client tools learned -V option

+### CA client tools learned `-V` option -

This displays the version numbers of EPICS Base and the CA protocol.

+This displays the version numbers of EPICS Base and the CA protocol. +## Changes made between 3.15.5 and 3.15.6 -

Changes made between 3.15.5 and 3.15.6

+### Unsetting environment variables -

Unsetting environment variables

+The new command `epicsEnvUnset varname` can be used to +unset an environment variable. -

The new command epicsEnvUnset varname can be used to -unset an environment variable.

+### Warning indicators in msi (and macLib) output -

Warning indicators in msi (and macLib) output

- -

The libCom macro expansion library has been modified so that when the -SUPPRESS_WARNINGS flag is set it will no longer include any ,undefined -or ,recursive indicators in its output when undefined or recursive +The libCom macro expansion library has been modified so that when the +`SUPPRESS_WARNINGS` flag is set it will no longer include any `,undefined` +or `,recursive` indicators in its output when undefined or recursive macros are encountered. These indicators were harmless when the output was fed -into an IOC along with a definition for the macro, but when the msi +into an IOC along with a definition for the macro, but when the `msi` tool was used to generate other kinds of files they caused problems. If the -msi -V flag is used the markers will still be present in the output -whenever the appropriate condition is seen.

+`msi -V` flag is used the markers will still be present in the output +whenever the appropriate condition is seen. -

Improvements to msi

+### Improvements to msi -

In addition to fixing its response to discovering parsing errors in its +In addition to fixing its response to discovering parsing errors in its substitution input file (reported as Launchpad -bug #1503661) +[bug 1503661](https://bugs.launchpad.net/epics-base/+bug/1503661)) so it now deletes the incomplete output file, the msi program has been cleaned -up a little bit internally.

+up a little bit internally. -

All array records now post monitors on their array-length fields

+### All array records now post monitors on their array-length fields -

The waveform record has been posting monitors on its NORD field since Base +The waveform record has been posting monitors on its NORD field since Base 3.15.0.1; we finally got around to doing the equivalent in all the other built-in record types, which even required modifying device support in some -cases. This fixes -Launchpad bug #1730727.

+cases. This fixes +[Launchpad bug 1730727](https://bugs.launchpad.net/epics-base/+bug/1730727). -

HOWTO: Converting Wiki Record Reference to POD

+### HOWTO: Converting Wiki Record Reference to POD -

Some documentation has been added to the dbdToHtml.pl script +Some documentation has been added to the `dbdToHtml.pl` script explaining how Perl POD (Plain Old Documentation) markup can be added to -.dbd files to generate HTML documentation for the record types. To see -these instructions, run perl bin/<host>/dbdToHtml.pl -H -or perldoc bin/<host>/dbdToHtml.pl.

+`.dbd` files to generate HTML documentation for the record types. To see +these instructions, run `perl bin//dbdToHtml.pl -H` +or `perldoc bin//dbdToHtml.pl`. -

Fix problem with numeric soft events

+### Fix problem with numeric soft events -

Changing from numeric to named soft events introduced an incompatibility +Changing from numeric to named soft events introduced an incompatibility when a numeric event 1-255 is converted from a DOUBLE, e.g. from a calc record. -The post_event() API is not marked deprecated any more. +The `post_event()` API is not marked deprecated any more. -

Also scanpel has been modified to accept a glob pattern for -event name filtering and to show events with no connected records as well.

+Also `scanpel` has been modified to accept a glob pattern for +event name filtering and to show events with no connected records as well. -

Add osiSockOptMcastLoop_t and osiSockTest

+### Add `osiSockOptMcastLoop_t` and osiSockTest -

Added a new OS-independent typedef for multicast socket options, and a test -file to check their correct operation.

+Added a new OS-independent typedef for multicast socket options, and a test +file to check their correct operation. -

Support for CONFIG_SITE.local in Base

+### Support for `CONFIG_SITE.local` in Base -

This feature is mostly meant for use by developers; configuration -settings that would normally appear in Base/configure/CONFIG_SITE can now -be put in a locally created base/configure/CONFIG_SITE.local file instead -of having go modify or replace the original. A new .gitignore pattern -tells git to ignore all configure/*.local files.

+This feature is mostly meant for use by developers; configuration +settings that would normally appear in `base/configure/CONFIG_SITE` can now +be put in a locally created `base/configure/CONFIG_SITE.local` file instead +of having go modify or replace the original. A new `.gitignore` pattern +tells git to ignore all `configure/*.local` files. - +### Fix broken `EPICS_IOC_LOG_FILE_LIMIT=0` setting -

Fix broken EPICS_IOC_LOG_FILE_LIMIT=0 setting

- -

The Application Developers' Guide says this is allowed and disables the +The Application Developers' Guide says this is allowed and disables the limit on the log-file, but it hasn't actually worked for some time (if ever). Note that the iocLogServer will be removed from newer Base release sometime soon as its functionality can be implemented by other dedicated log servers -such as logstash or syslog-ng.

+such as logstash or syslog-ng. -

Fixes lp:1786858 -and part of lp:1786966. -

+Fixes [lp:1786858](https://bugs.launchpad.net/bugs/1786858) +and part of [lp:1786966](https://bugs.launchpad.net/bugs/1786966). -

Cleanup of startup directory

+### Cleanup of startup directory -

The files in the startup directory have not been maintained in recent years +The files in the startup directory have not been maintained in recent years and have grown crufty (technical term). This release includes the following -updates to these files:

+updates to these files: -
    + - The Perl `EpicsHostArch.pl` script has been rewritten, and support + for a few previously missing host architectures has been added to it. + - The `EpicsHostArch.pl` script has also been moved into the standard + `src/tools` directory, from where it will be installed into + `lib/perl`. In this new location it is no longer executable, so it must + be run by the `perl` executable. + - The build system has been adjusted to look for `EpicsHostArch.pl` in + both places if the `EPICS_HOST_ARCH` environment variable has not been + set at build-time. + - Sites that used the original Perl script to set `EPICS_HOST_ARCH` as + part of their standard environment will need to adjust their scripts when they + upgrade to this release. + - The `EpicsHostArch` shell script has been replaced with a wrapper + routine that calls the Perl `EpicsHostArch.pl` script. Sites that rely on + this script to set `EPICS_HOST_ARCH` should consider switching to the + Perl script instead. + - The `Site.cshrc` and `Site.profile` files have been renamed to + `unix.csh` and `unix.sh`, respectively. + - The existing `win32.bat` file has been cleaned up and a new + `windows.bat` file added for 64-bit targets. The contents of these files + should be seen as examples, don't uncomment or install parts for software that + you don't explicitly know that you need. -
  • The Perl EpicsHostArch.pl script has been rewritten, and support -for a few previously missing host architectures has been added to it.
  • +### Recent Apple XCode Build Issues -
  • The EpicsHostArch.pl script has also been moved into the standard -src/tools directory, from where it will be installed into -lib/perl. In this new location it is no longer executable, so it must -be run by the perl executable.
  • - -
  • The build system has been adjusted to look for EpicsHostArch.pl in -both places if the EPICS_HOST_ARCH environment variable has not been -set at build-time.
  • - -
  • Sites that used the original Perl script to set EPICS_HOST_ARCH as -part of their standard environment will need to adjust their scripts when they -upgrade to this release.
  • - -
  • The EpicsHostArch shell script has been replaced with a wrapper -routine that calls the Perl EpicsHostArch.pl script. Sites that rely on -this script to set EPICS_HOST_ARCH should consider switching to the -Perl script instead.
  • - -
  • The Site.cshrc and Site.profile files have been renamed to -unix.csh and unix.sh, respectively.
  • - -
  • The existing win32.bat file has been cleaned up and a new -windows.bat file added for 64-bit targets. The contents of these files -should be seen as examples, don't uncomment or install parts for software that -you don't explicitly know that you need.
  • - -
- -

Recent Apple XCode Build Issues

- -

The latest version of XCode will not compile calls to system() or -clock_settime() for iOS targets. There were several places in Base +The latest version of XCode will not compile calls to `system()` or +`clock_settime()` for iOS targets. There were several places in Base where these were being compiled, although there were probably never called. The -code has now been modified to permit iOS builds to complete again.

+code has now been modified to permit iOS builds to complete again. -

Prevent illegal alarm severities

+### Prevent illegal alarm severities -

A check has been added to recGblResetAlarms() that prevents records -from getting an alarm severity higher than INVALID_ALARM. It is still possible +A check has been added to `recGblResetAlarms()` that prevents records +from getting an alarm severity higher than `INVALID_ALARM`. It is still possible for a field like HSV to get set to a value that is not a legal alarm severity, but the core IOC code should never copy such a value into a record's SEVR or ACKS fields. With this fix the record's alarm severity will be limited to -INVALID_ALARM.

+`INVALID_ALARM`. -

Fixes for Launchpad bugs

+### Fixes for Launchpad bugs -

The following launchpad bugs have fixes included:

+The following launchpad bugs have fixes included: - + - [lp: 1786320](https://bugs.launchpad.net/epics-base/+bug/1786320), dbCa subscribes twice to ENUM + - [lp: 541221](https://bugs.launchpad.net/epics-base/+bug/541221), 'assert (pca-\>pgetNative)' failed in ../dbCa.c + - [lp: 1747091](https://bugs.launchpad.net/epics-base/+bug/1747091), epicsTimeGetEvent() / generalTime bug + - [lp: 1743076](https://bugs.launchpad.net/epics-base/+bug/1743076), Segfault in `ca_attach_context()` during exits + - [lp: 1751380](https://bugs.launchpad.net/epics-base/+bug/1751380), Deadlock in `ca_clear_subscription()` + - [lp: 1597809](https://bugs.launchpad.net/epics-base/+bug/1597809), Setting NAME field in DB file may break IOC + - [lp: 1770292](https://bugs.launchpad.net/epics-base/+bug/1770292), `get_alarm_double()` inconsistent across record types + - [lp: 1771298](https://bugs.launchpad.net/epics-base/+bug/1771298), Conversion of NaN to integer relies on undefined + behavior -

Updated VxWorks Timezone settings

+### Updated VxWorks Timezone settings -

Removed the settings for 2017; fixed the hour of the change for MET.

+Removed the settings for 2017; fixed the hour of the change for MET. -

Fixed camonitor server side relative timestamps bug

+### Fixed camonitor server side relative timestamps bug -

Initialize the first time-stamp from the first monitor, not the client-side -current time in this configuration.

+Initialize the first time-stamp from the first monitor, not the client-side +current time in this configuration. -

Build changes for MSVC

+### Build changes for MSVC -

Windows builds using Visual Studio 2015 and later now use the -FS -compiler option to allow parallel builds to work properly.

+Windows builds using Visual Studio 2015 and later now use the `-FS` +compiler option to allow parallel builds to work properly. -

We now give the -FC option to tell the compiler to print absolute -paths for source files in diagnostic messages.

+We now give the `-FC` option to tell the compiler to print absolute +paths for source files in diagnostic messages. -

Extend maximum Posix epicsEventWaitWithTimeout() delay

+### Extend maximum Posix epicsEventWaitWithTimeout() delay -

The Posix implementation of epicsEventWaitWithTimeout() was limiting the +The Posix implementation of epicsEventWaitWithTimeout() was limiting the timeout delay to at most 60 minutes (3600.0 seconds). This has been changed to 10 years; significantly longer maximum delays cause problems on systems where -time_t is still a signed 32-bit integer so cannot represent absolute +`time_t` is still a signed 32-bit integer so cannot represent absolute time-stamps after 2038-01-19. Our assumption is that such 32-bit systems will have been retired before the year 2028, but some additional tests have been added to the epicsTimeTest program to detect and fail if this assumption is -violated.

+violated. -

New test-related make targets

+### New test-related make targets -

This release adds several new make targets intended for use by developers +This release adds several new make targets intended for use by developers and Continuous Integration systems which simplify the task of running the built-in self-test programs and viewing the results. Since these targets are intended for limited use they can have requirements for the build host which -go beyond the standard minimum set needed to build and run Base.

+go beyond the standard minimum set needed to build and run Base. -
+#### `test-results` — Summarize test results -

test-results — Summarize test results

- -

The new make target test-results will run the self-tests if +The new make target `test-results` will run the self-tests if necessary to generate a TAP file for each test, then summarizes the TAP output files in each test directory in turn, displaying the details of any failures. -This step uses the program prove which comes with Perl, but also needs -cat to be provided in the default search path so will not work on most -Windows systems.

+This step uses the program “prove” which comes with Perl, but also needs +“cat” to be provided in the default search path so will not work on most +Windows systems. -

junitfiles — Convert test results to JUnit XML Format

+#### `junitfiles` — Convert test results to JUnit XML Format -

The new make target junitfiles will run the self-tests if necessary +The new make target `junitfiles` will run the self-tests if necessary and then convert the TAP output files into the more commonly-supported JUnit XML format. The program that performs this conversion needs the Perl module -XML::Generator to have been installed.

+“`XML::Generator`” to have been installed. -

clean-tests — Delete test result files

+#### `clean-tests` — Delete test result files -

The new make target clean-tests removes any test result files from -previous test runs. It cleans both TAP and JUnit XML files.

+The new make target `clean-tests` removes any test result files from +previous test runs. It cleans both TAP and JUnit XML files. -
+### Fix DNS related crash on exit -

Fix DNS related crash on exit

- -

The attempt to fix DNS related delays for short lived CLI programs (eg. caget) +The attempt to fix DNS related delays for short lived CLI programs (eg. caget) in lp:1527636 introduced a bug which cased these short lived clients to crash on exit. -This bug should now be fixed.

+This bug should now be fixed. -

Server bind issue on Windows

+### Server bind issue on Windows -

When a National Instruments network variables CA server is already running on +When a National Instruments network variables CA server is already running on a Windows system and an IOC or PCAS server is started, the IOC's attempt to bind a TCP socket to the CA server port number fails, but Windows returns a different error status value than the IOC is expecting in that circumstance (because the National Instruments code requests exclusive use of that port, unlike the EPICS code) so the IOC fails to start properly. The relevent EPICS bind() checks have now been updated so the IOC will request that a dynamic port -number be allocated for this TCP socket instead when this happens.

+number be allocated for this TCP socket instead when this happens. -

Checking Periodic Scan Rates

+### Checking Periodic Scan Rates -

Code has been added to the IOC startup to better protect it against bad -periodic scan rates, including against locales where . is not +Code has been added to the IOC startup to better protect it against bad +periodic scan rates, including against locales where `.` is not accepted as a decimal separator character. If the scan period in a menuScan choice string cannot be parsed, the associated periodic scan thread will no longer be started by the IOC and a warning message will be displayed at iocInit -time. The scanppl command will also flag the faulty menuScan value.

+time. The `scanppl` command will also flag the faulty menuScan value. +## Changes made between 3.15.4 and 3.15.5 -

Changes made between 3.15.4 and 3.15.5

+### dbStatic Library Speedup and Cleanup -

dbStatic Library Speedup and Cleanup

- -

Loading of database files has been optimized to avoid overproportionally +Loading of database files has been optimized to avoid over-proportionally long loading times for large databases. As a part of this, the alphabetical ordering of records instances (within a record type) has been dropped. In the unexpected case that applications were relying on the alphabetic order, setting -dbRecordsAbcSorted = 1 before loading the databases will retain the -old behavior.

+`dbRecordsAbcSorted = 1` before loading the databases will retain the +old behavior. -

The routine dbRenameRecord() has been removed, as it was intended +The routine `dbRenameRecord()` has been removed, as it was intended to be used by database configuration tools linked against a host side version -of the dbStatic library that is not being built anymore.

+of the dbStatic library that is not being built anymore. -

Launchpad Bug-fixes

+### Launchpad Bug-fixes -

In addition to the more detailed change descriptions below, the following -Launchpad bugs have also been fixed in this release:

+In addition to the more detailed change descriptions below, the following +Launchpad bugs have also been fixed in this release: -
    -
  • - #1440186 Crash due to a too small buffer being provided in - dbContextReadNotifyCache
  • -
  • - #1479316 Some data races found using Helgrind
  • -
  • - #1495833 biRecord prompt groups are nonsensical
  • -
  • - #1606848 WSAIoctl SIO_GET_INTERFACE_LIST failed in Windows
  • -
+ - [lp:1440186](https://bugs.launchpad.net/epics-base/+bug/1440186) Crash due to a too small buffer being provided in + dbContextReadNotifyCache + - [lp:1479316](https://bugs.launchpad.net/epics-base/+bug/1479316) Some data races found using Helgrind + - [lp:1495833](https://bugs.launchpad.net/epics-base/+bug/1495833) biRecord prompt groups are nonsensical + - [lp:1606848](https://bugs.launchpad.net/epics-base/+bug/1606848) WSAIoctl `SIO_GET_INTERFACE_LIST` failed in Windows -

Whole-Program Optimization for MS Visual Studio Targets

+### Whole-Program Optimization for MS Visual Studio Targets -

When using the Microsoft compilers a new build system variable is provided +When using the Microsoft compilers a new build system variable is provided that controls whether whole program optimization is used or not. For static builds using Visual Studio 2010 this optimization must be disabled. This is -controlled in the files configure/os/CONFIG_SITE.Common.windows-x64-static and -configure/os/CONFIG_SITE.Common.win32-x86-static by setting the variable -OPT_WHOLE_PROGRAM = NO to override the default value -YES that would otherwise be used.

+controlled in the files `configure/os/CONFIG_SITE.Common.windows-x64-static` and +`configure/os/CONFIG_SITE.Common.win32-x86-static` by setting the variable +`OPT_WHOLE_PROGRAM = NO` to override the default value +`YES` that would otherwise be used. -

Note that enabling this optimization slows down the build process. It is not +Note that enabling this optimization slows down the build process. It is not possible to selectively disable this optimization, when building a particular module say; Microsoft's linker will restart itself automatically with the --LTCG flag set and display a warning if it is asked to link any object -files that were compiled with the -GL flag.

+`-LTCG` flag set and display a warning if it is asked to link any object +files that were compiled with the `-GL` flag. -

Add dynamic (variable length) array support to PCAS

+### Add dynamic (variable length) array support to PCAS -

Dynamic array sizing support was added to the IOC server (RSRV) in the -Base-3.14.12 release, but has not until now been supported in the Portable -Channel Access Server (PCAS). Channel Access server applications using the +Dynamic array sizing support was added to the IOC server (RSRV) in the +Base-3.14.12 release, but has not until now been supported in the “Portable +Channel Access Server” (PCAS). Channel Access server applications using the PCAS may not need to be modified at all; if they already push monitors with different gdd array lengths, those variable sizes will be forwarded to any CA clients who have requested variable length updates. The example CAS server -application has been modified to demonstrate this feature.

+application has been modified to demonstrate this feature. -

In implementing the above, the gdd method gdd::put(const gdd *) now +In implementing the above, the gdd method `gdd::put(const gdd *)` now copies the full-sized array from the source gdd if the destination gdd is of -type array, has no allocated memory and a boundary size of 0.

+type array, has no allocated memory and a boundary size of 0. -

Additional epicsTime conversion

+### Additional epicsTime conversion -

The EPICS timestamp library (epicsTime) inside libCom's OSI layer has -been extended by routines that convert from struct tm to the EPICS -internal epicsTime type, assuming UTC - i.e. without going through +The EPICS timestamp library (epicsTime) inside libCom's OSI layer has +been extended by routines that convert from `struct tm` to the EPICS +internal `epicsTime` type, assuming UTC - i.e. without going through the timezone mechanism. This solves issues with converting from the structured type to the EPICS timestamp at driver level from multiple threads at a high -repetition rate, where the timezone mechanism was blocking on file access.

+repetition rate, where the timezone mechanism was blocking on file access. -

MinGW Cross-builds from Linux

+### MinGW Cross-builds from Linux -

The build configuration files that allow cross-building of the 32-bit +The build configuration files that allow cross-building of the 32-bit win32-x86-mingw cross-target have been adjusted to default to building shared libraries (DLLs) as this is now supported by recent MinGW compilers. The 64-bit windows-x64-mingw cross-target was already being built that way by default. The configuration options to tell the minGW cross-compiler to link programs with static versions of the compiler support libraries have now been moved into the -CONFIG_SITE.linux-x86.target files.

+`CONFIG_SITE.linux-x86.` files. -

General Time updates

+### General Time updates -

The iocInit code now performs a sanity check of the current time +The `iocInit` code now performs a sanity check of the current time returned by the generalTime subsystem and will print a warning if the wall-clock time returned has not been initialized yet. This is just a warning message; when a time provider does synchonize the IOC will subsequently pick up and use the correct time. This check code also primes the registered event system provider -if there is one so the epicsTimeGetEventInt() routine will work on IOCs -that ask for event time within an interrupt service routine.

+if there is one so the `epicsTimeGetEventInt()` routine will work on IOCs +that ask for event time within an interrupt service routine. -

The osiClockTime provider's synchronization thread (which is only used on +The osiClockTime provider's synchronization thread (which is only used on some embedded targets) will now poll the other time providers at 1Hz until the first time it manages to get a successful timestamp, after which it will poll -for updates every 60 seconds as before.

+for updates every 60 seconds as before. -

The routine generalTimeGetExceptPriority() was designed for use by +The routine `generalTimeGetExceptPriority()` was designed for use by backup (lower priority) time providers like the osiClockTime provider which do not have their own absolute time reference and rely on other providers for an absolute time source. This routine no longer implements the ratchet mechanism that prevented the time it returned from going backwards. If the backup clock's tick-timer runs fast the synchronization of the backup time provider would never allow it to be corrected backwards when the ratchet was in place. The regular -epicsTimeGetCurrent() API still uses the ratchet mechanism, so this -change will not cause the IOC to see time going backwards.

+`epicsTimeGetCurrent()` API still uses the ratchet mechanism, so this +change will not cause the IOC to see time going backwards. -

Microsoft Visual Studio builds

+### Microsoft Visual Studio builds -

The build configuration files for builds using the Microsoft compilers have +The build configuration files for builds using the Microsoft compilers have been updated, although there should be no noticable difference at most sites. -One extra compiler warning is now being suppressed for C++ code, C4344: -behavior change: use of explicit template arguments results in ... which is -gratuitous and was appearing frequently in builds of the EPICS V4 modules.

+One extra compiler warning is now being suppressed for C++ code, `C4344: behavior change: use of explicit template arguments results in ...` which is +gratuitous and was appearing frequently in builds of the EPICS V4 modules. -

Cross-builds of the windows-x64 target from a win32-x86 host have been -removed as they don't actually work within the context of a single make +Cross-builds of the windows-x64 target from a win32-x86 host have been +removed as they don't actually work within the context of a single `make` run. Significant changes to the build configuration files would be necessary for these kinds of cross-builds to work properly, which could be done if someone needs them (email Andrew Johnson before working on this, and see - -this stack-overflow answer for a starting point).

+[this stack-overflow answer](http://stackoverflow.com/questions/5807647/how-do-you-compile-32-bit-and-64-bit-applications-at-the-same-time-in-visual-stu) for a starting point). -

Bazaar keywords such as 'Revision-Id' removed

+### Bazaar keywords such as 'Revision-Id' removed -

In preparation for moving to git in place of the Bazaar revision control -system we have removed all the keywords from the Base source code.

+In preparation for moving to git in place of the Bazaar revision control +system we have removed all the keywords from the Base source code. -

Linux systemd service file for CA Repeater

+### Linux systemd service file for CA Repeater -

Building this version of Base on a Linux system creates a systemd service +Building this version of Base on a Linux system creates a systemd service file suitable for starting the Channel Access Repeater under systemd. The file will be installed into the target bin directory, from where it can be copied into the appropriate systemd location and modified as necessary. Installation -instructions are included as comments in the file.

+instructions are included as comments in the file. +## Changes made between 3.15.3 and 3.15.4 -

Changes made between 3.15.3 and 3.15.4

+### New string input device support "getenv" -

New string input device support "getenv"

- -

A new "getenv" device support for both the stringin and lsi (long string +A new "getenv" device support for both the stringin and lsi (long string input) record types can be used to read the value of an environment variable -from the IOC at runtime. See base/db/softIocExit.db for sample usage.

+from the IOC at runtime. See base/db/softIocExit.db for sample usage. -

Build rules and DELAY_INSTALL_LIBS

+### Build rules and `DELAY_INSTALL_LIBS` -

A new order-only prerequisite build rule has been added to ensure that +A new order-only prerequisite build rule has been added to ensure that library files (and DLL stubs on Windows) get installed before linking any executables, which resolves parallel build problems on high-powered CPUs. There are some (rare) cases though where a Makefile has to build an executable and run it to be able to compile code for a library built by the same Makefile. With this new build rule GNUmake will complain about a circular dependency and the build will probably fail in those cases. To avoid this problem the failing -Makefile should set DELAY_INSTALL_LIBS = YES before including the -$(TOP)/configure/RULES file, disabling the new build rule.

+Makefile should set `DELAY_INSTALL_LIBS = YES` before including the +`$(TOP)/configure/RULES` file, disabling the new build rule. -

IOC environment variables and build parameters

+### IOC environment variables and build parameters -

The IOC now sets a number of environment variables at startup that provide -the version of EPICS Base it was built against (EPICS_VERSION_...) and its build +The IOC now sets a number of environment variables at startup that provide +the version of EPICS Base it was built against (`EPICS_VERSION_...`) and its build architecture (ARCH). In some cases this allows a single iocBoot/ioc directory to be used to run the same IOC on several different architectures without any -changes.

+changes. -

There are also 3 new environment parameters (EPICS_BUILD_...) available that +There are also 3 new environment parameters (`EPICS_BUILD_...`) available that C/C++ code can use to find out the target architecture, OS class and compiler class it was built with. These may be useful when writing interfaces to other -languages.

+languages. -

New implementation of promptgroup/gui_group field property

+### New implementation of promptgroup/gui\_group field property -

The mechanism behind the "promptgroup()" field property inside a record type +The mechanism behind the `promptgroup()` field property inside a record type definition has been changed. Instead of using a fixed set of choices, the static database access library now collects the used gui group names while parsing DBD information. Group names should start with a two-digit number -plus space-dash-space to allow proper sorting of groups.

+plus space-dash-space to allow proper sorting of groups. -

The include file guigroup.h that defined the fixed set of choices +The include file `guigroup.h` that defined the fixed set of choices has been deprecated. Instead, use the conversion functions between index number -and group string that have been added to dbStaticLib.

+and group string that have been added to dbStaticLib. -

When a DBD file containing record-type descriptions is expanded, any -old-style GUI_xxx group names will be replaced by a new-style +When a DBD file containing record-type descriptions is expanded, any +old-style `GUI_xxx` group names will be replaced by a new-style string for use by the IOC. This permits an older record type to be used with the 3.15.4 release, although eventually record types should be converted by -hand with better group names used.

+hand with better group names used. -

CA server configuration changes

+### CA server configuration changes -

RSRV now honors EPICS_CAS_INTF_ADDR_LIST and binds only to the provided list +RSRV now honors `EPICS_CAS_INTF_ADDR_LIST` and binds only to the provided list of network interfaces. Name searches (UDP and TCP) on other network interfaces are ignored. For example on a computer with interfaces 10.5.1.1/24, 10.5.2.1/24, -and 10.5.3.1/24, setting "EPICS_CAS_INTF_ADDR_LIST='10.5.1.1 10.5.2.1'" will -accept traffic on the .1.1 and .2.1, but ignore from .3.1

+and 10.5.3.1/24, setting `EPICS_CAS_INTF_ADDR_LIST='10.5.1.1 10.5.2.1'` will +accept traffic on the .1.1 and .2.1, but ignore from .3.1 -

RSRV now honors EPICS_CAS_IGNORE_ADDR_LIST and ignores UDP messages received -from addresses in this list.

+RSRV now honors `EPICS_CAS_IGNORE_ADDR_LIST` and ignores UDP messages received +from addresses in this list. -

Previously, CA servers (RSRV and PCAS) would build the beacon address list -using EPICS_CA_ADDR_LIST if EPICS_CAS_BEACON_ADDR_LIST was no set. This is no -longer done. Sites depending on this should set both envronment variables to the -same value.

+Previously, CA servers (RSRV and PCAS) would build the beacon address list +using `EPICS_CA_ADDR_LIST` if `EPICS_CAS_BEACON_ADDR_LIST` was no set. This is no +longer done. Sites depending on this should set both environment variables to the +same value. -

IPv4 multicast for name search and beacons

+### IPv4 multicast for name search and beacons -

libca, RSRV, and PCAS may now use IPv4 multicasting for UDP traffic (name +libca, RSRV, and PCAS may now use IPv4 multicasting for UDP traffic (name search and beacons). This is disabled by default. To enable multicast address(s) -must be listed in EPICS_CA_ADDR_LIST for clients and EPICS_CAS_INTF_ADDR_LIST +must be listed in `EPICS_CA_ADDR_LIST` for clients and `EPICS_CAS_INTF_ADDR_LIST` for servers (IOCs should set both). For example: -"EPICS_CAS_INTF_ADDR_LIST='224.0.2.9' EPICS_CA_ADDR_LIST=224.0.2.9".

+`EPICS_CAS_INTF_ADDR_LIST='224.0.2.9' EPICS_CA_ADDR_LIST=224.0.2.9` -

Please note that no IPv4 multicast address is officially assigned for Channel -Access by IANA. The example 224.0.2.9 is taken from the AD-HOC Block I range.

+Please note that no IPv4 multicast address is officially assigned for Channel +Access by IANA. The example 224.0.2.9 is taken from the AD-HOC Block I range. -

Moved mlockall() into its own epicsThread routine

+### Moved `mlockall()` into its own epicsThread routine -

Since EPICS Base 3.15.0.2 on Posix OSs the initialization of the epicsThread -subsystem has called mlockall() when the OS supports it and thread +Since EPICS Base 3.15.0.2 on Posix OSs the initialization of the epicsThread +subsystem has called `mlockall()` when the OS supports it and thread priority scheduling is enabled. Doing so has caused problems in third-party applications that call the CA client library, so the functionality has been -moved to a separate routine epicsThreadRealtimeLock() which will be +moved to a separate routine `epicsThreadRealtimeLock()` which will be called by the IOC at iocInit (unless disabled by setting the global variable -dbThreadRealtimeLock to zero).

+`dbThreadRealtimeLock` to zero). -

Added dbQuietMacroWarnings control

+### Added dbQuietMacroWarnings control -

When loading database files, macros get expanded even on comment lines. If a +When loading database files, macros get expanded even on comment lines. If a comment contains an undefined macro, the load still continues but an error message gets printed. For this release the error message has been changed to a warning, but even this warning can be made less verbose by setting this new -variable to a non-zero value before loading the file, like this:

+variable to a non-zero value before loading the file, like this: -
-var dbQuietMacroWarnings 1      iocsh
-dbQuietMacroWarnings=1          VxWorks
-
+``` + var dbQuietMacroWarnings 1 iocsh + dbQuietMacroWarnings=1 VxWorks +``` -

This was Launchpad bug -541119.

+This was [Launchpad bug +541119](https://bugs.launchpad.net/bugs/541119). +## Changes from the 3.14 branch between 3.15.3 and 3.15.4 -

Changes from the 3.14 branch between 3.15.3 and 3.15.4

+### NTP Time Provider adjusts to OS tick rate changes -

NTP Time Provider adjusts to OS tick rate changes

- -

Dirk Zimoch provided code that allows the NTP Time provider (used on VxWorks +Dirk Zimoch provided code that allows the NTP Time provider (used on VxWorks and RTEMS only) to adapt to changes in the OS clock tick rate after the provider has been initialized. Note that changing the tick rate after iocInit() is not advisable, and that other software might still misbehave if initialized before -an OS tick rate change. This change was back-ported from the 3.15 branch.

+an OS tick rate change. This change was back-ported from the 3.15 branch. -

Making IOC ca_get operations atomic

+### Making IOC `ca_get` operations atomic -

When a CA client gets data from an IOC record using a compound data type such -as DBR_TIME_DOUBLE the value field is fetched from the database in a +When a CA client gets data from an IOC record using a compound data type such +as `DBR_TIME_DOUBLE` the value field is fetched from the database in a separate call than the other metadata, without keeping the record locked. This allows some other thread such as a periodic scan thread a chance to interrupt the get operation and process the record in between. CA monitors have always been atomic as long as the value data isn't a string or an array, but this race condition in the CA get path has now been fixed so the record will stay locked -between the two fetch operations.

+between the two fetch operations. -

This fixes -Launchpad bug #1581212, thanks to Till Strauman and Dehong Zhang.

+This fixes +[Launchpad bug 1581212](https://bugs.launchpad.net/epics-base/+bug/1581212), +thanks to Till Strauman and Dehong Zhang. -

New CONFIG_SITE variable for running self-tests

+### New `CONFIG_SITE` variable for running self-tests -

The 'make runtests' and 'make tapfiles' build targets normally only run the -self-tests for the main EPICS_HOST_ARCH architecture. If the host is +The 'make runtests' and 'make tapfiles' build targets normally only run the +self-tests for the main `EPICS_HOST_ARCH` architecture. If the host is able to execute self-test programs for other target architectures that are being -built by the host, such as when building a -debug version of the host +built by the host, such as when building a `-debug` version of the host architecture for example, the names of those other architectures can be added to -the new CROSS_COMPILER_RUNTEST_ARCHS variable in either the -configure/CONFIG_SITE file or in an appropriate -configure/os/CONFIG_SITE.<host>.Common file to have the test -programs for those targets be run as well.

+the new `CROSS_COMPILER_RUNTEST_ARCHS` variable in either the +`configure/CONFIG_SITE` file or in an appropriate +`configure/os/CONFIG_SITE..Common` file to have the test +programs for those targets be run as well. -

Additional RELEASE file checks

+### Additional RELEASE file checks -

An additional check has been added at build-time for the contents of the -configure/RELEASE file(s), which will mostly only affect users of the Debian +An additional check has been added at build-time for the contents of the +`configure/RELEASE` file(s), which will mostly only affect users of the Debian EPICS packages published by NSLS-2. Support modules may share an install path, -but all such modules must be listed adjacent to each other in any RELEASE files -that point to them. For example the following will fail the new checks:

+but all such modules must be listed adjacent to each other in any `RELEASE` files +that point to them. For example the following will fail the new checks: -
-AUTOSAVE = /usr/lib/epics
-ASYN = /home/mdavidsaver/asyn
-EPICS_BASE = /usr/lib/epics
-
+``` + AUTOSAVE = /usr/lib/epics + ASYN = /home/mdavidsaver/asyn + EPICS_BASE = /usr/lib/epics +``` -

giving the compile-time error

+giving the compile-time error -
-This application's RELEASE file(s) define
-	EPICS_BASE = /usr/lib/epics
-after but not adjacent to
-	AUTOSAVE = /usr/lib/epics
-Module definitions that share paths must be grouped together.
-Either remove a definition, or move it to a line immediately
-above or below the other(s).
-Any non-module definitions belong in configure/CONFIG_SITE.
-
+``` + This application's RELEASE file(s) define + EPICS_BASE = /usr/lib/epics + after but not adjacent to + AUTOSAVE = /usr/lib/epics + Module definitions that share paths must be grouped together. + Either remove a definition, or move it to a line immediately + above or below the other(s). + Any non-module definitions belong in configure/CONFIG_SITE. +``` - -

In many cases such as the one above the order of the AUTOSAVE and -ASYN lines can be swapped to let the checks pass, but if the -AUTOSAVE module depended on ASYN and hence had to appear -before it in the list this error indicates that AUTOSAVE should also be +In many cases such as the one above the order of the `AUTOSAVE` and +`ASYN` lines can be swapped to let the checks pass, but if the +`AUTOSAVE` module depended on `ASYN` and hence had to appear +before it in the list this error indicates that `AUTOSAVE` should also be built in its own private area; a shared copy would likely be incompatible with -the version of ASYN built in the home directory.

+the version of `ASYN` built in the home directory. -

String field buffer overflows

+### String field buffer overflows -

Two buffer overflow bugs that can crash the IOC have been fixed, caused by +Two buffer overflow bugs that can crash the IOC have been fixed, caused by initializing a string field with a value larger than the field size -(Launchpad bug -#1563191).

+([Launchpad bug 1563191](https://bugs.launchpad.net/bugs/1563191)). -

Fixed stack corruption bug in epicsThread C++ API

+### Fixed stack corruption bug in epicsThread C++ API -

The C++ interface to the epicsThread API could corrupt the stack on thread +The C++ interface to the epicsThread API could corrupt the stack on thread exit in some rare circumstances, usually at program exit. This bug has been -fixed (Launchpad bug -#1558206).

+fixed ([Launchpad bug 1558206](https://bugs.launchpad.net/bugs/1558206)). -

RTEMS NTP Support Issue

+### RTEMS NTP Support Issue -

On RTEMS the NTP Time Provider could in some circumstances get out of sync -with the server because the osdNTPGet() code wasn't clearing its input socket +On RTEMS the NTP Time Provider could in some circumstances get out of sync +with the server because the `osdNTPGet()` code wasn't clearing its input socket before sending out a new request. This -(Launchpad bug 1549908) -has now been fixed.

+([Launchpad bug 1549908](https://bugs.launchpad.net/bugs/1549908)) +has now been fixed. -

CALC engine bitwise operator fixes

+### CALC engine bitwise operator fixes -

The bitwise operators in the CALC engine have been modified to work properly +The bitwise operators in the CALC engine have been modified to work properly with values that have bit 31 (0x80000000) set. This modification involved back-porting some earlier changes from the 3.15 branch, and fixes -Launchpad bug -#1514520.

+[Launchpad bug 1514520](https://code.launchpad.net/bugs/1514520). -

Fix ipAddrToAsciiAsync(): Don't try to join the daemon thread

+### Fix `ipAddrToAsciiAsync()`: Don't try to join the daemon thread -

On process exit, don't try to stop the worker thread that makes DNS lookups +On process exit, don't try to stop the worker thread that makes DNS lookups asynchronous. Previously this would wait for any lookups still in progress, delaying the exit unnecessarily. This was most obvious with catools (eg. cainfo). -lp:1527636

+[lp:1527636](https://bugs.launchpad.net/bugs/1527636) -

Fix epicsTime_localtime() on Windows

+### Fix `epicsTime_localtime()` on Windows -

Simpler versions of the epicsTime_gmtime() and epicsTime_localtime() +Simpler versions of the `epicsTime_gmtime()` and `epicsTime_localtime()` routines have been included in the Windows implementations, and a new test program added. The original versions do not report DST status properly. Fixes -Launchpad bug 1528284.

+[Launchpad bug 1528284](https://bugs.launchpad.net/bugs/1528284). +## Changes made between 3.15.2 and 3.15.3 -

Changes made between 3.15.2 and 3.15.3

+### Make the NTP Time provider optional on VxWorks -

Make the NTP Time provider optional on VxWorks

- -

Recent versions of VxWorks (sometime after VxWorks 6) provide facilities for +Recent versions of VxWorks (sometime after VxWorks 6) provide facilities for automatically synchronizing the OS clock time with an NTP server. The EPICS time system used to assume that it had to provide time synchronization on VxWorks, but now it tests for the existance of either of the two OS synchronization threads before starting the NTP time provider. It is still possible to force the NTP provider to be started even if the OS synchronization is running by defining -the environment variable EPICS_TS_FORCE_NTPTIME in the startup script -before loading the IOC's .munch file. Forcing may be necessary if the VxWorks -image is not correctly configured with the IP address of a local NTP server.

+the environment variable `EPICS_TS_FORCE_NTPTIME` in the startup script +before loading the IOC's `.munch` file. Forcing may be necessary if the VxWorks +image is not correctly configured with the IP address of a local NTP server. -

Assembling files from numbered snippets

+### Assembling files from numbered snippets -

A tool has been added that assembles file snippets specified on the +A tool has been added that assembles file snippets specified on the command line into a single output file, with sorting and replacing/adding of snippets done based on their file names. The build system integration requires -the output file to be specified setting COMMON_ASSEMBLIES (arch independent) -or ASSEMBLIES (created by arch), then defining the snippets for each assembly -setting *_SNIPPETS (explicitly) or *_PATTERN (searched relative to all source +the output file to be specified setting `COMMON_ASSEMBLIES` (arch independent) +or `ASSEMBLIES` (created by arch), then defining the snippets for each assembly +setting `*_SNIPPETS` (explicitly) or `*_PATTERN` (searched relative to all source directories). -

-

Clean up after GNU readline()

+### Clean up after GNU readline() -

If EPICS Base is built with readline support, any IOC that calls epicsExit() +If EPICS Base is built with readline support, any IOC that calls epicsExit() from a thread other than the main thread is likely to leave the user's terminal in a weird state, requiring the user to run something like 'stty sane' to clean it up. This release patches the readline support code to clean up automatically -by registering an epicsAtExit() routine.

+by registering an epicsAtExit() routine. -

Removed the last vestiges of RSET::get_value()

+### Removed the last vestiges of `RSET::get_value()` -

The IOC has not called the get_value() routine in the RSET for a very long +The IOC has not called the `get_value()` routine in the RSET for a very long time, but there was still one implementation left in the event record support code, and a structure definition for one of the original arguments to that -routine was defined in recGbl.h. Both of these have now been removed.

+routine was defined in recGbl.h. Both of these have now been removed. +## Changes made between 3.15.1 and 3.15.2 -

Changes made between 3.15.1 and 3.15.2

+### Raised limit on link field length in database files -

Raised limit on link field length in database files

- -

The length of INP/OUT link fields in database files was limited to 79 chars +The length of INP/OUT link fields in database files was limited to 79 chars by an internal buffer size in the db file parser. This limitation will go away completely in 3.16, and has been statically raised to 255 chars for the 3.15 -series.

+series. -

aoRecord raw conversion overflows

+### aoRecord raw conversion overflows -

The ao record type now checks converted raw values and limits them to the +The ao record type now checks converted raw values and limits them to the 32-bit integer range before writing them to the RVAL field. Previously value overflows relied on Undefined Behaviour which could give different results on different platforms. The ROFF fields of the ao and ai record types are now -DBF_ULONG to allow an ROFF setting of 0x80000000 to work properly.

+`DBF_ULONG` to allow an ROFF setting of 0x80000000 to work properly. -

Changes to <top>/cfg/* files

+### Changes to `/cfg/*` files -

The order in which cfg/CONFIG* and cfg/RULES* files are included from support -applications listed in the configure/RELEASE* files has been changed. Previously +The order in which `cfg/CONFIG*` and `cfg/RULES*` files are included from support +applications listed in the `configure/RELEASE*` files has been changed. Previously these files were included in the order in which the top areas are listed in the RELEASE file, but it makes more sense to load them in reverse order since later entries override earlier ones in Makefiles but the release file order is supposed to allow earlier entries to take precedence over later ones. The same -change has been made to the inclusion of the <top>/configure/RULES_BUILD -files.

+change has been made to the inclusion of the `/configure/RULES_BUILD` +files. -

Two new file types can also be provided in a module's cfg directory. Files -named TOP_RULES* will be included by the top-level Makefile of other modules -that refer to this module; files name DIR_RULES* will be included by all -Makefiles that merely descend into lower-level directories. The cfg/RULES* files -are only included when make is building code inside the O.<arch> -directories.

+Two new file types can also be provided in a module's `cfg` directory. Files +named `TOP_RULES*` will be included by the top-level Makefile of other modules +that refer to this module; files name `DIR_RULES*` will be included by all +Makefiles that merely descend into lower-level directories. The `cfg/RULES*` files +are only included when make is building code inside the `O.` directories. -

The new cfg/DIR_RULES* file inclusion was designed to permit new recursive +The new `cfg/DIR_RULES*` file inclusion was designed to permit new recursive make actions to be implemented by appending the name of the new action to the -ACTIONS variable. There must be a matching rule in one of the cfg/RULES* files -when doing this. Similar rules may also be defined in the cfg/TOP_RULES* and/or -cfg/DIR_RULES* files, but these should only state prerequisites and not directly -provide commands to be executed.

+`ACTIONS` variable. There must be a matching rule in one of the `cfg/RULES*` files +when doing this. Similar rules may also be defined in the `cfg/TOP_RULES*` and/or +`cfg/DIR_RULES*` files, but these should only state prerequisites and not directly +provide commands to be executed. -

Build rules for RTEMS GESYS modules

+### Build rules for RTEMS GESYS modules -

RTEMS target builds can now be configured to make GESYS modules by changing -the USE_GESYS=NO setting in the file -configure/os/CONFIG_SITE.Common.RTEMS to YES.

+RTEMS target builds can now be configured to make GESYS modules by changing +the `USE_GESYS=NO` setting in the file +`configure/os/CONFIG_SITE.Common.RTEMS` to `YES`. -

Added Make variables for command-line use

+### Added Make variables for command-line use -

The following variables are now used during the build process, reserved for +The following variables are now used during the build process, reserved for setting on the command-line only (Makefiles should continue to use the -USR_ equivalents):

+`USR_` equivalents): -
    -
  • CMD_INCLUDES
  • -
  • CMD_CPPFLAGS
  • -
  • CMD_CFLAGS
  • -
  • CMD_CXXFLAGS
  • -
  • CMD_LDFLAGS
  • -
  • CMD_DBFLAGS
  • -
  • CMD_DBDFLAGS
  • -
  • CMD_REGRDDFLAGS
  • -
  • CMD_ARFLAGS
  • -
+ - `CMD_INCLUDES` + - `CMD_CPPFLAGS` + - `CMD_CFLAGS` + - `CMD_CXXFLAGS` + - `CMD_LDFLAGS` + - `CMD_DBFLAGS` + - `CMD_DBDFLAGS` + - `CMD_REGRDDFLAGS` + - `CMD_ARFLAGS` -

For example:

+For example: -
-make CMD_INCLUDES=/opt/local/include CMD_LDFLAGS=-L/opt/local/lib
-
+``` + make CMD_INCLUDES=/opt/local/include CMD_LDFLAGS=-L/opt/local/lib +``` -

Enhanced API for asTrapWrite listeners

+### Enhanced API for asTrapWrite listeners -

External software such as the CA Put Logging module that registers a listener +External software such as the CA Put Logging module that registers a listener with the asTrapWrite subsystem was not previously given access to the actual data being sent by the CA client. In most cases this was not a problem as the listener can look at the field being modified both before and after the operation, but if the put processes the record which immediately overwrites the -new value, the client's value cannot be observed.

+new value, the client's value cannot be observed. -

This release adds three fields to the asTrapWriteMessage structure that is +This release adds three fields to the asTrapWriteMessage structure that is passed to the listener routines. These new fields provide the CA data type, the number of array elements, and a pointer to the source data buffer. This change is completely backwards compatible with listener code written against the -original API. The new API can be detected at compile-time as follows:

+original API. The new API can be detected at compile-time as follows: -
-#include "asLib.h"
+```
+    #include "asLib.h"
 
-/* ... */
+    /* ... */
 
-#ifdef asTrapWriteWithData
-    /* Enhanced API */
-#endif
-
+ #ifdef asTrapWriteWithData + /* Enhanced API */ + #endif +``` -

Use of PATH_FILTER in Makefiles deprecated

+### Use of `PATH_FILTER` in Makefiles deprecated -

The PATH_FILTER variable was being called to convert forward shashes -/ in file paths into pairs of backward slashes -\\ on Windows architectures. This has never been strictly +The `PATH_FILTER` variable was being called to convert forward slashes +`/` in file paths into pairs of backward slashes +`\\` on Windows architectures. This has never been strictly necessary, and was added about 10 years ago to get around some short-comings in -Windows tools at the time. All uses of PATH_FILTER in Base have now been +Windows tools at the time. All uses of `PATH_FILTER` in Base have now been removed; the definition is still present, but will result in a warning being -printed if it is ever used.

+printed if it is ever used. -

Using msi for dependencies

+### Using msi for dependencies -

To reduce confusion the msi program has been modified to allow the generation -of dependency rules by adding support for a -D option, and changing the +To reduce confusion the msi program has been modified to allow the generation +of dependency rules by adding support for a `-D` option, and changing the commands in RULES.Db to use this option instead of the mkmf.pl script. The new build rules will not work with old versions of the msi program, so the command -variable name used in the rules has been changed from MSI to MSI3_15. Sites that -use a modified version of msi must provide support for both the -D and --o outfile options, and should then point the MSI3_15 variable in -their applications' CONFIG_SITE files to that updated executable.

+variable name used in the rules has been changed from `MSI` to `MSI3_15`. Sites that +use a modified version of msi must provide support for both the `-D` and +`-o outfile` options, and should then point the `MSI3_15` variable in +their applications' `CONFIG_SITE` files to that updated executable. +## Changes made between 3.15.0.2 and 3.15.1 -

Changes made between 3.15.0.2 and 3.15.1

+### `epicsStrnEscapedFromRaw()` and `epicsStrnRawFromEscaped()` -

epicsStrnEscapedFromRaw() and epicsStrnRawFromEscaped()

+These routines have been rewritten; the previous implementations did not +always behave exactly as specified. -

These routines have been rewritten; the previous implementations did not -always behave exactly as specified.

+### Shared Library Versions -

Shared Library Versions

- -

On architectures that can support it, the shared library version number for +On architectures that can support it, the shared library version number for libraries provided with Base has had the third component of the EPICS version number added to it, thus libCom.so.3.15.1 instead of libCom.so.3.15. Windows can only support two components to its internal product version number, and the Darwin bug that external shared libraries were being built using the EPICS -version number has been fixed.

+version number has been fixed. -

Hooking into dbLoadRecords

+### Hooking into dbLoadRecords -

A function pointer hook has been added to the dbLoadRecords() routine, to +A function pointer hook has been added to the dbLoadRecords() routine, to allow external modules such as autosave to be notified when new records have -been loaded during IOC initialization. The hook is called dbLoadRecordsHook and -follows the model of the recGblAlarmHook pointer in that modules that wish to +been loaded during IOC initialization. The hook is called `dbLoadRecordsHook` and +follows the model of the `recGblAlarmHook` pointer in that modules that wish to use it must save the current value of the pointer before installing their own function pointer, and must call the original function from their own -routine.

+routine. -

The hook is activiated from the dbLoadRecords() routine and gets called only +The hook is activiated from the `dbLoadRecords()` routine and gets called only after a database instance file has been read in without error. Note that the -dbLoadTemplates() routine directly calls dbLoadRecords() so this hook also +`dbLoadTemplates()` routine directly calls `dbLoadRecords()` so this hook also provides information about instantiated database templates. It is still possible -to load record instances using dbLoadDatabase() though, and doing this will not -result in the hook routines being called.

+to load record instances using `dbLoadDatabase()` though, and doing this will not +result in the hook routines being called. -

Code to use this hook should look something like this:

+Code to use this hook should look something like this: -
-#include "dbAccessDefs.h"
+```
+    #include "dbAccessDefs.h"
 
-static DB_LOAD_RECORDS_HOOK_ROUTINE previousHook;
+    static DB_LOAD_RECORDS_HOOK_ROUTINE previousHook;
 
-static void myRoutine(const char* file, const char* subs) {
-    if (previousHook)
-        previousHook(file, subs);
+    static void myRoutine(const char* file, const char* subs) {
+        if (previousHook)
+            previousHook(file, subs);
 
-    /* Do whatever ... */
-}
-
-void myInit(void) {
-    static int done = 0;
-
-    if (!done) {
-        previousHook = dbLoadRecordsHook;
-        dbLoadRecordsHook = myRoutine;
-        done = 1;
+        /* Do whatever ... */
     }
-}
-
-

As with many other parts of the static database access library there is no + void myInit(void) { + static int done = 0; + + if (!done) { + previousHook = dbLoadRecordsHook; + dbLoadRecordsHook = myRoutine; + done = 1; + } + } +``` + +As with many other parts of the static database access library there is no mutex to protect the function pointer. Initialization is expected to take place in the context of the IOC's main thread, from either a static C++ constructor or -an EPICS registrar routine.

+an EPICS registrar routine. +## Changes made between 3.15.0.1 and 3.15.0.2 -

Changes made between 3.15.0.1 and 3.15.0.2

+### New iocshLoad command -

New iocshLoad command

- -

A new command iocshLoad has been added to iocsh which executes a +A new command `iocshLoad` has been added to iocsh which executes a named iocsh script and can also set one or more shell macro variables at the same time, the values of which will be forgotten immediately after the named -script finishes executing. The following example shows the syntax:

+script finishes executing. The following example shows the syntax: -
-iocshLoad "serial.cmd", "DEV=/dev/ttyS0,PORT=com1,TYPE=RS485"
-iocshLoad "radmon.cmd", "PORT=com1,ADDR=0"
-
+``` + iocshLoad "serial.cmd", "DEV=/dev/ttyS0,PORT=com1,TYPE=RS485" + iocshLoad "radmon.cmd", "PORT=com1,ADDR=0" +``` -

Support routines for 64-bit integers

+### Support routines for 64-bit integers -

The libCom library now provides support for 64-bit integer types on all +The libCom library now provides support for 64-bit integer types on all supported architectures. The epicsTypes.h header file defines epicsInt64 and epicsUInt64 type definitions for both C and C++ code. The epicsStdlib.h header also declares the following for parsing strings into the relevent sized integer @@ -930,369 +868,365 @@ epicsScanLLong() and epicsScanULLong(), and the functions epicsParseInt64() and epicsParseUInt64(). Use the first two functions and the macros for long long and unsigned long long integer types, and the last two functions for the epicsInt64 and epicsUInt64 types. Note that the latter can map to the types long -and unsigned long on some 64-bit architectures such as linux-x86_64, not to the -two long long types.

+and unsigned long on some 64-bit architectures such as linux-x86\_64, not to the +two long long types. -

This version does not provide the ability to define 64-bit record fields, the +This version does not provide the ability to define 64-bit record fields, the use of the 64-bit types in the IOC database will come in a later release of -EPICS Base.

+EPICS Base. -

Full support for loadable support modules

+### Full support for loadable support modules -

Apparently later versions of Base 3.14 permitted support modules to be loaded +Apparently later versions of Base 3.14 permitted support modules to be loaded from a shared library at runtime without the IOC having been linked against that shared library; the registerRecordDeviceDriver.pl program would accept a partial DBD file containing just the entries needed for the library and generate the appropriate registration code. In 3.15 however the registerRecordDeviceDriver.pl program was replaced by one using the new DBD file parser, and in this a device support entry would only be accepted after first loading the record type that it -depended on.

+depended on. -

The parser has been modified to accept device entries without having seen the +The parser has been modified to accept device entries without having seen the record type first, although a warning is given when that happens. To remove the warning the DBD file can provide a record type declaration instead (no fields can be defined, so the braces must be empty), before the device() entry. The result will generate the correct registration code for the device entry without including anything for any merely declared record types. The generated code can be linked into a shared library and loaded by an IOC at runtime using dlload. -

-

Parallel callback threads

+### Parallel callback threads -

The general purpose callback facility can run multiple parallel callback +The general purpose callback facility can run multiple parallel callback threads per priority level. This makes better use of SMP architectures (e.g. processors with multiple cores), as callback work - which includes second stage processing of records with asynchronuous device support and I/O -scanned processing - can be distributed over the available CPUs.

+scanned processing - can be distributed over the available CPUs. -

Note that by using parallel callback threads the order of scan callback +Note that by using parallel callback threads the order of scan callback requests in the queue is not retained. If a device support needs to be informed when scanIoRequest processing has finished, it should use the new scanIoSetComplete() feature to add a user function that will be called after -the scanIoRequest record processing has finished.

+the scanIoRequest record processing has finished. -

Parallel callback threads have to be explicitly configured, by default -the IOC keeps the old behavior of running one callback thread per priority.

+Parallel callback threads have to be explicitly configured, by default +the IOC keeps the old behavior of running one callback thread per priority. -

Merge MMIO API from devLib2

+### Merge MMIO API from devLib2 -

Added calls to handle 8, 16, and 32 bit Memory Mapped I/O reads and writes. -The calls added include X_iowriteY() and -X_ioreadY() -where X is nat (native), be or le, -and Y is 16 or 32. -Also added are ioread8() and iowrite8().

+Added calls to handle 8, 16, and 32 bit Memory Mapped I/O reads and writes. +The calls added include `X_iowriteY()` and `X_ioreadY()` +where `X` is `nat` (native), `be` or `le`, and `Y` is `16` or `32`. +Also added are `ioread8()` and `iowrite8()`. -

Added optional dbServer API to database

+### Added optional dbServer API to database -

A server layer that sits on top of the IOC database may now register itself -as such by calling dbRegisterServer() and providing optional routines +A server layer that sits on top of the IOC database may now register itself +as such by calling `dbRegisterServer()` and providing optional routines that other components can use. The initial purpose of this API allows the Trace -Processing implementation in dbProcess() to identify a client that -causes a record to process when TPRO is set.

+Processing implementation in `dbProcess()` to identify a client that +causes a record to process when TPRO is set. -

To support the client idenfication, the server provides a routine that +To support the client identification, the server provides a routine that returns that identity string when called by one of its own processing -threads.

+threads. -

Concatenated database definition files

+### Concatenated database definition files -

A series of database definition (dbd) files can now be concatenated during +A series of database definition (dbd) files can now be concatenated during the build process into a newly-created dbd file with result being installed into -$(INSTALL_LOCATION)/dbd without expanding it.

+`$(INSTALL_LOCATION)/dbd` without expanding it. -

The following lines in an EPICS Makefile will create a file name.dbd in the +The following lines in an EPICS Makefile will create a file name.dbd in the O.Common build directory containing the contents of file1.dbd followed by file2.dbd then file3.dbd. The new file will then be installed into -$(INSTALL_LOCATION)/dbd without expanding any of its include statements.

+`$(INSTALL_LOCATION)/dbd` without expanding any of its include statements. -
-DBDCAT += name.dbd
-name_DBD += file1.dbd file2.dbd file3.dbd
-
+``` + DBDCAT += name.dbd + name_DBD += file1.dbd file2.dbd file3.dbd +``` -

The source files file1.dbd, file2.dbd and file3.dbd may be created by the +The source files file1.dbd, file2.dbd and file3.dbd may be created by the current Makefile, be located in the parent directory or any other directory in -the SRC_DIRS list, be specified by their full pathname, exist in the install dbd +the `SRC_DIRS` list, be specified by their full pathname, exist in the install dbd directory, or be found in any dbd directory linked from the application's -RELEASE files.

+RELEASE files. -

Posix: Drop SCHED_FIFO before exec() in child process

+### Posix: Drop `SCHED_FIFO` before exec() in child process -

If Base is compiled with USE_POSIX_THREAD_PRIORITY_SCHEDULING = YES -in configure/CONFIG_SITE or related files, the Posix implementation of the -libCom osiSpawnDetachedProcess() routine will switch the child process -to use the normal SCHED_OTHER (non real-time) scheduler before executing the +If Base is compiled with `USE_POSIX_THREAD_PRIORITY_SCHEDULING = YES` +in `configure/CONFIG_SITE` or related files, the Posix implementation of the +libCom `osiSpawnDetachedProcess()` routine will switch the child process +to use the normal `SCHED_OTHER` (non real-time) scheduler before executing the named executable program. If it needs to use the real-time scheduler the new -program can request that for itself.

+program can request that for itself. -

Posix: Lock all memory when running with FIFO scheduler

+### Posix: Lock all memory when running with FIFO scheduler -

On Posix systems, an IOC application's ability to meet timing deadlines is +On Posix systems, an IOC application's ability to meet timing deadlines is often dependent on its ability to lock part or all of the process's virtual address space into RAM, preventing that memory from being paged to the swap area. This change will attempt to lock the process's virtual address space into RAM if the process has the ability to run threads with different priorities. If -unsuccessful, it prints an message to stderr and continues.

+unsuccessful, it prints an message to stderr and continues. -

On Linux, one can grant a process the ability to run threads with different -priorities by using the command ulimit -r unlimited. To use the -FIFO scheduler for an IOC, use a command like this:

+On Linux, one can grant a process the ability to run threads with different +priorities by using the command `ulimit -r unlimited`. To use the +FIFO scheduler for an IOC, use a command like this: -
chrt -f 1 softIoc -d test.db
+``` + chrt -f 1 softIoc -d test.db +``` -

On Linux, one can grant a process the ability to lock itself into memory -using the command ulimit -l unlimited. These limits can also be -configured on a per user/per group basis by changing /etc/security/limits.conf -or its equivalent.

+On Linux, one can grant a process the ability to lock itself into memory +using the command `ulimit -l unlimited`. These limits can also be +configured on a per user/per group basis by changing `/etc/security/limits.conf` +or its equivalent. -

A child process created via fork() normally inherits its parent's resource +A child process created via `fork()` normally inherits its parent's resource limits, so a child of a real-time soft-IOC will get its parent's real-time priority and memlock limits. The memory locks themselves however are not -inherited by child processes.

+inherited by child processes. -

Implement EPICS_CAS_INTF_ADDR_LIST in rsrv

+### Implement `EPICS_CAS_INTF_ADDR_LIST` in rsrv -

The IOC server can now bind to a single IP address (and optional port number) -read from the standard environment parameter EPICS_CAS_INTF_ADDR_LIST. +The IOC server can now bind to a single IP address (and optional port number) +read from the standard environment parameter `EPICS_CAS_INTF_ADDR_LIST`. Additional addresses included in that parameter after the first will be ignored -and a warning message displayed at iocInit time.

+and a warning message displayed at iocInit time. -

alarmString.h deprecated again

+### alarmString.h deprecated again -

The string arrays that provide string versions of the alarm status and +The string arrays that provide string versions of the alarm status and severity values have been moved into libCom and the header file that used to instanciate them is no longer required, although a copy is still provided for backwards compatibility reasons. Only the alarm.h header needs to be included -now to declare the epicsAlarmSeverityStrings and epicsAlarmConditionStrings -arrays.

+now to declare the `epicsAlarmSeverityStrings` and `epicsAlarmConditionStrings` +arrays. -

General purpose thread pool

+### General purpose thread pool -

A general purpose threaded work queue API epicsThreadPool is added. -Multiple pools can be created with controlable priority and number -of worker threads. Lazy worker startup is supported.

+Multiple pools can be created with controllable priority and number +of worker threads. Lazy worker startup is supported. -

Database field setting updates

+### Database field setting updates -

A database (.db) file loaded by an IOC does not have to repeat the record +A database (.db) file loaded by an IOC does not have to repeat the record type of a record that has already been loaded. It may replace the first -parameter of the record(type, name) statement with an asterisk -character inside double-quotes, "*" instead. Thus the following is a -legal database file:

+parameter of the `record(type, name)` statement with an asterisk +character inside double-quotes, `"*"` instead. Thus the following is a +legal database file: -
record(ao, "ao1") {}
-record("*", "ao1") {
-    field(VAL, 10)
-}
+``` + record(ao, "ao1") {} + record("*", "ao1") { + field(VAL, 10) + } +``` -

Note that database configuration tools will not be expected to have to +Note that database configuration tools will not be expected to have to understand this syntax, which is provided for scripted and hand-coded database -and template instantiation only. Setting the IOC's dbRecordsOnceOnly +and template instantiation only. Setting the IOC's `dbRecordsOnceOnly` flag also makes this syntax illegal, since its purpose is to prevent -multiply-defined records from being collapsed into a single instance.

+multiply-defined records from being collapsed into a single instance. -

Added echo command to iocsh

+### Added echo command to iocsh -

The single argument string may contain escaped characters, which will be +The single argument string may contain escaped characters, which will be translated to their raw form before being printed (enclose the string in quotes to avoid double-translation). A newline is always appended to the output, and -output stream redirection is supported.

+output stream redirection is supported. -

Added macro EPICS_UNUSED to compilerDependencies.h

+### Added macro `EPICS_UNUSED` to compilerDependencies.h -

To prevent the compiler from warning about a known-unused variable, mark it -with the macro EPICS_UNUSED. On gcc and clang this will expand to -__attribute__((unused)) to prevent the warning.

+To prevent the compiler from warning about a known-unused variable, mark it +with the macro `EPICS_UNUSED`. On gcc and clang this will expand to +`__attribute__((unused))` to prevent the warning. -

User specified db substitution file suffix

+### User specified db substitution file suffix -

Per Dirk Zimoch's suggestion, a user specified db substitution file suffix is -now allowed by setting the variable SUBST_SUFFIX in a configuration directory -CONFIG_SITE file or in a Makefile before the include $(TOP)/configure/RULES -line. The default for SUBST_SUFFIX is .substitutions

+Per Dirk Zimoch's suggestion, a user specified db substitution file suffix is +now allowed by setting the variable `SUBST_SUFFIX` in a configuration directory +`CONFIG_SITE` file or in a Makefile before the include $(TOP)/configure/RULES +line. The default for `SUBST_SUFFIX` is `.substitutions` -

NTP Time Provider adjusts to OS tick rate changes

+### NTP Time Provider adjusts to OS tick rate changes -

Dirk Zimoch provided code that allows the NTP Time provider (used on VxWorks +Dirk Zimoch provided code that allows the NTP Time provider (used on VxWorks and RTEMS only) to adapt to changes in the OS clock tick rate after the provider -has been initialized. Note that changing the tick rate after iocInit() is not +has been initialized. Note that changing the tick rate after `iocInit()` is not advisable, and that other software might still misbehave if initialized before -an OS tick rate change.

+an OS tick rate change. -

Added newEpicsMutex macro

+### Added newEpicsMutex macro -

Internal C++ uses of new epicsMutex() have been replaced with a new +Internal C++ uses of `new epicsMutex()` have been replaced with a new macro which calls a new constructor, passing it the file name and line number of the mutex creation code. C code that creates mutexes has been using a similar macro for a long time, but there was no equivalent constructor for the C++ -wrapper class, so identifying a specific mutex was much harder to do.

+wrapper class, so identifying a specific mutex was much harder to do. -

Post DBE_PROPERTY events automatically

+### Post `DBE_PROPERTY` events automatically -

A new record field attribute "prop(YES)" has been added to identify fields +A new record field attribute `prop(YES)` has been added to identify fields holding meta-data. External changes to these fields will cause a CA monitor -event to be sent to all record subscribers who have asked for DBE_PROPERTY -updates. Meta-data fields have been marked for all Base record types.

+event to be sent to all record subscribers who have asked for `DBE_PROPERTY` +updates. Meta-data fields have been marked for all Base record types. -

errlogRemoveListener() routine changed

+### errlogRemoveListener() routine changed -

Code that calls errlogRemoveListener(myfunc) must be modified to use -the new, safer routine errlogRemoveListeners(myfunc, &pvt) instead. +Code that calls `errlogRemoveListener(myfunc)` must be modified to use +the new, safer routine `errlogRemoveListeners(myfunc, &pvt)` instead. The replacement routine takes a second argument which must be the same private -pointer that was passed to errlogAddListener() when adding that +pointer that was passed to `errlogAddListener()` when adding that listener. It also deletes all matching listeners (hence the new plural name) and returns how many were actually deleted, whereas the previous routine only -removed the first listener that matched.

+removed the first listener that matched. -

Simplified generation of .dbd files

+### Simplified generation of .dbd files -

The Perl script makeIncludeDbd.pl has been removed and the rules -that created an intermediate xxxInclude.dbd file from the -Makefile variable xxx_DBD have been modified to generate the target -xxx.dbd file directly. This should simplify applications that +The Perl script `makeIncludeDbd.pl` has been removed and the rules +that created an intermediate `xxxInclude.dbd` file from the +Makefile variable `xxx_DBD` have been modified to generate the target +`xxx.dbd` file directly. This should simplify applications that might have had to provide dependency rules for the intermediate files in 3.15. -Applications which provide their own xxxInclude.dbd source file -will continue to have it expanded as before.

+Applications which provide their own `xxxInclude.dbd` source file +will continue to have it expanded as before. -

New Undefined Severity field UDFS

+### New Undefined Severity field UDFS -

A new field has been added to dbCommon which configures the alarm severity +A new field has been added to dbCommon which configures the alarm severity associated with the record being undefined (when UDF=TRUE). The default value is INVALID so old databases will not be affected, but now individual records can be configured to have a lower severity or even no alarm when undefined. Be careful when changing this on applications where the IVOA field of output records is -used, IVOA still requires an INVALID severity to trigger value replacement.

+used, IVOA still requires an INVALID severity to trigger value replacement. -

New build target tapfiles

+### New build target “tapfiles” -

This new make target runs the same tests as the runtests target, but +This new make target runs the same tests as the “runtests” target, but instead of summarizing or displaying the output for each test script it creates -a .tap file inside the architecture build directory which contains the +a “.tap” file inside the architecture build directory which contains the detailed test output. The output file can be parsed by continuous integration -packages such as Jenkins to show the -test results.

+packages such as [Jenkins](http://www.jenkins-ci.org/) to show the +test results. -

Array field double-buffering

+### Array field double-buffering -

Array data can now be moved, without copying, into and out of the VAL field +Array data can now be moved, without copying, into and out of the VAL field of the waveform, aai, and aao record types by replacing the pointer in BPTR. -The basic rules which device support must follow are:

+The basic rules which device support must follow are: -
    -
  1. BPTR, and the memory it is currently pointing to, can only be accessed - while the record is locked.
  2. -
  3. NELM may not be changed; NORD should be updated whenever the number of - valid data elements changes.
  4. -
  5. When BPTR is replaced it must always point to a block of memory large - enough to hold the maximum number of elements, as given by the NELM and - FTVL fields.
  6. -
+1. BPTR, and the memory it is currently pointing to, can only be accessed + while the record is locked. +2. NELM may not be changed; NORD should be updated whenever the number of + valid data elements changes. +3. When BPTR is replaced it must always point to a block of memory large + enough to hold the maximum number of elements, as given by the NELM and + FTVL fields. -

Spin-locks API added

+### Spin-locks API added -

The new header file epicsSpin.h adds a portable spin-locks API which is +The new header file epicsSpin.h adds a portable spin-locks API which is intended for locking very short sections of code (typically one or two lines of C or C++) to provide a critical section that protects against race conditions. -On Posix platforms this uses the pthread_spinlock_t type if it's available and +On Posix platforms this uses the `pthread_spinlock_t` type if it's available and the build is not configured to use Posix thread priorities, but otherwise it -falls back to a pthread_mutex_t. On the UP VxWorks and RTEMS platforms the +falls back to a `pthread_mutex_t`. On the UP VxWorks and RTEMS platforms the implementations lock out CPU interrupts and disable task preemption while a spin-lock is held. The default implementation (used when no other implementation is provided) uses an epicsMutex. Spin-locks may not be taken recursively, and -the code inside the critical section should be short and deterministic.

+the code inside the critical section should be short and deterministic. -

Improvements to aToIPAddr()

+### Improvements to aToIPAddr() -

The libCom routine aToIPAddr() and the vxWorks implementation of the +The libCom routine aToIPAddr() and the vxWorks implementation of the associated hostToIPAddr() function have been modified to be able to look up hostnames that begin with one or more digits. The epicsSockResolveTest program -was added to check this functionality.

+was added to check this functionality. -

mbboDirect and mbbiDirect records

+### mbboDirect and mbbiDirect records -

These record types have undergone some significant rework, and will behave +These record types have undergone some significant rework, and will behave slightly differently than they did in their 3.14 versions. The externally -visible changes are as follows:

+visible changes are as follows: -
mbbiDirect
+##### mbbiDirect -
    -
  • If the MASK field is set in a database file, it will not be over-written + - If the MASK field is set in a database file, it will not be over-written when the record is initialized. This allows non-contiguous masks to be set, - although only the device support actually uses the MASK field.
  • -
  • If process() finds the UDF field to be set, the record will raise a - UDF/INVALID alarm.
  • -
+ although only the device support actually uses the MASK field. + - If process() finds the UDF field to be set, the record will raise a + UDF/INVALID alarm. -
mbboDirect
+##### mbboDirect -
    -
  • If the MASK field is set in a database file, it will not be over-written + - If the MASK field is set in a database file, it will not be over-written when the record is initialized. This allows non-contiguous masks to be set, - although only the device support actually uses the MASK field.
  • -
  • After the device support's init_record() routine returns during record - initialization, if OMSL is supervisory and UDF is clear the fields - B0-BF will be set from the current VAL field.
  • -
  • When a put to the OMSL field sets it to supervisory, the fields + although only the device support actually uses the MASK field. + - After the device support's `init_record()` routine returns during record + initialization, if OMSL is “supervisory” and UDF is clear the fields + B0-BF will be set from the current VAL field. + - When a put to the OMSL field sets it to “supervisory”, the fields B0-BF will be set from the current VAL field. This did not used to happen, the individual bit fields were previously never modified by the record. Note that this change may require some databases to be modified, if they - were designed to take advantage of the previous behavior.
  • -
+ were designed to take advantage of the previous behavior. -

Redirection of the errlog console stream

+### Redirection of the errlog console stream -

A new routine has been added to the errlog facility which allows the console +A new routine has been added to the errlog facility which allows the console error message stream to be redirected from stderr to some other already open -file stream:

+file stream: -
int errlogSetConsole(FILE *stream);
-
+``` + int errlogSetConsole(FILE *stream); +``` -

The stream argument must be a FILE* pointer as returned by fopen() that is -open for output. If NULL is passed in, the errlog thread's stderr output stream +The stream argument must be a `FILE*` pointer as returned by `fopen()` that is +open for output. If `NULL` is passed in, the errlog thread's stderr output stream will be used instead. Note that messages to the console can be disabled and -re-enabled using the eltc routine which is also an iocsh command, but there is -no iocsh command currently provided for calling errlogSetConsole.

+re-enabled using the `eltc` routine which is also an iocsh command, but there is +no iocsh command currently provided for calling `errlogSetConsole()`. -

Add cleanup subroutine to aSub record

+### Add cleanup subroutine to aSub record -

An aSub routine may set the CADR field with a function pointer which will be +An aSub routine may set the CADR field with a function pointer which will be run before a new routine in the event that a change to the SNAM field changes -the record's process subroutine.

+the record's process subroutine. -

This can be used to free any resources the routine needs to allocate. It can +This can be used to free any resources the routine needs to allocate. It can also be used to determine if this is the first time this routine has been called by this record instance. The CADR field is set to NULL immediately after the -routine it points to is called.

+routine it points to is called. -

Example:

+Example: -
void cleanup(aSubRecord* prec) {
-    free(prec->dpvt);
-    prec->dpvt = NULL;
-}
-
-long myAsubRoutine(aSubRecord* prec) {
-    if (!prec->cadr) {
-        /* check types of inputs and outputs */
-        if (prec->ftva != menuFtypeDOUBLE)
-            return 1; /* oops */
-
-        dpvt = malloc(42);
-        prec->cadr = &cleanup;
+```
+    void cleanup(aSubRecord* prec) {
+        free(prec->dpvt);
+        prec->dpvt = NULL;
     }
 
-    /* normal processing */
-}
-epicsRegisterFunction(myAsubRoutine);
-
+ long myAsubRoutine(aSubRecord* prec) { + if (!prec->cadr) { + /* check types of inputs and outputs */ + if (prec->ftva != menuFtypeDOUBLE) + return 1; /* oops */ -

Sequence record enhancements

+ dpvt = malloc(42); + prec->cadr = &cleanup; + } -

The sequence record type now has 16 link groups numbered 0 through 9 and A + /* normal processing */ + } + epicsRegisterFunction(myAsubRoutine); +``` + +### Sequence record enhancements + +The sequence record type now has 16 link groups numbered 0 through 9 and A through F, instead of the previous 10 groups numbered 1 through 9 and A. The changes to this record are directly equivalent to those described below for the fanout record. The fields OFFS and SHFT have been added and operate on the SELN @@ -1303,544 +1237,374 @@ when the selection number exceeded 10. The record also now posts monitors on the SELN field at the end of the sequence if its value changed when read through the SELL link. -

Fanout record enhancements

+### Fanout record enhancements -

The fanout record type now has 16 output links LNK0-LNK9 and LNKA-LNKF, plus +The fanout record type now has 16 output links LNK0-LNK9 and LNKA-LNKF, plus two additional fields which make the result backwards compatible with 3.14 databases, but also allow the link selection to be shifted without having to -process the SELN value through a calc or calcout record first.

+process the SELN value through a calc or calcout record first. -

Previously there was no LNK0 field, so when SELM is Mask bit 0 of SELN +Previously there was no LNK0 field, so when SELM is “Mask” bit 0 of SELN controls whether the LNK1 link field was activated; bit 1 controls LNK2 and so -on. When SELM is Specified and SELN is zero no output link would be +on. When SELM is “Specified” and SELN is zero no output link would be activated at all; LNK1 gets activated when SELN is 1 and so on. Only 6 links were provided, LNK1 through LNK6. The updated record type maintains the original behavior when the new fields are not configured, except that the SOFT/INVALID -alarm is not generated when SELN is 7 through 15.

+alarm is not generated when SELN is 7 through 15. -

The update involved adding a LNK0 field, as well as fields LNK7 through LNK9 +The update involved adding a LNK0 field, as well as fields LNK7 through LNK9 and LNKA through LNKF. To add flexibility and maintain backwards compatibility, -two additional fields have been added:

+two additional fields have been added: -
-
OFFS
+ - **OFFS** + This field holds a signed offset which is added to SELN to select which link + to activate when SELM is “Specified”. If the resulting value is outside the + range 0 .. 15 the record will go into a SOFT/INVALID alarm state. The default + value of OFFS is zero, so if it is not explicitly set and SELN is 1 the LNK1 + link will be activated. + - **SHFT** + When SELM is “Mask” the signed field SHFT is used to shift the SELN + value by SHFT bits (positive means right-wards, values outside the range -15 .. + 15 will result in a SOFT/INVALID alarm), before using the resulting bit-pattern + to control which links to activate. The default value is -1, so if SHFT is not + explicitly set bit 0 of SELN will be used to control whether LNK1 gets + activated. -
This field holds a signed offset which is added to SELN to select which link -to activate when SELM is Specified. If the resulting value is outside the -range 0 .. 15 the record will go into a SOFT/INVALID alarm state. The default -value of OFFS is zero, so if it is not explicitly set and SELN is 1 the LNK1 -link will be activated.
+The record also now posts monitors on the SELN field if it changes as a +result of record processing (i.e. when read through the SELL link). -
SHFT
+### Deleted Java build rules -
When SELM is Mask the signed field SHFT is used to shift the SELN -value by SHFT bits (positive means right-wards, values outside the range -15 .. -15 will result in a SOFT/INVALID alarm), before using the resulting bit-pattern -to control which links to activate. The default value is -1, so if SHFT is not -explicitly set bit 0 of SELN will be used to control whether LNK1 gets -activated.
- -
- -

The record also now posts monitors on the SELN field if it changes as a -result of record processing (i.e. when read through the SELL link).

- -

Deleted Java build rules

- -

Java has its own build systems now, so we've deleted the rules and associated +Java has its own build systems now, so we've deleted the rules and associated variables from Base, although they might get added to the Extensions build rules -for a while in case anyone still needs them.

+for a while in case anyone still needs them. -

Changes made between 3.14.x and 3.15.0.1

+## Changes made between 3.14.x and 3.15.0.1 -

Application clean rules

+### Application clean rules -

The clean Makefile target has changed between a single-colon rule +The `clean` Makefile target has changed between a single-colon rule and a double-colon rule more than once in the life of the EPICS build rules, and it just changed back to a single-colon rule, but now we recommend that applications that wish to provide a Makefile that is backwards compatible with -the 3.14 build rules use the construct shown below. The 3.15 rules now support -a variable called CLEANS to which a Makefile can add a list of files to -be deleted when the user does a make clean like this:

+the 3.14 build rules use the construct shown below. The 3.15 rules now support +a variable called `CLEANS` to which a Makefile can add a list of files to +be deleted when the user does a `make clean` like this: -
CLEANS += <list of files to be cleaned>
+```
+    CLEANS += 
 
-ifndef BASE_3_15
-clean::
-	$(RM) $(CLEANS)
-endif
+ ifndef BASE_3_15 + clean:: + $(RM) $(CLEANS) + endif +``` -

The conditional rule provides compatibility for use with the 3.14 build -system.

+The conditional rule provides compatibility for use with the 3.14 build +system. -

MSI included with Base

+### MSI included with Base -

An enhanced version of the Macro Substitution and Include program msi +An enhanced version of the Macro Substitution and Include program “msi” has been included with Base. Both this new version of msi and the IOC's -dbLoadTemplates command now support setting global macros in -substitution files, and dbLoadTemplates can now take a list of global +`dbLoadTemplates` command now support setting global macros in +substitution files, and `dbLoadTemplates` can now take a list of global macro settings as the second argument on its command line. The substitution file -syntax is documented in the Application Developers Guide.

+syntax is documented in the Application Developers Guide. -

Cross-builds targeting win32-x86-mingw

+### Cross-builds targeting win32-x86-mingw -

Some Linux distributions now package the MinGW cross-compiler which makes it +Some Linux distributions now package the MinGW cross-compiler which makes it possible to cross-build the win32-x86-mingw target from a linux-x86 host. Build configuration files for this combination are now included; adjust the settings -in configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw and add win32-x86-mingw to -the CROSS_COMPILER_TARGET_ARCHS variable in configure/CONFIG_SITE or in -configure/os/CONFIG_SITE.linux-x86.Common.

+in `configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw` and add win32-x86-mingw to +the `CROSS_COMPILER_TARGET_ARCHS` variable in `configure/CONFIG_SITE` or in +`configure/os/CONFIG_SITE.linux-x86.Common`. -

Architecture win32-x86-cygwin Removed

+### Architecture win32-x86-cygwin Removed -

The ability to compile non-cygwin binaries using the Cygwin build tools is no +The ability to compile non-cygwin binaries using the Cygwin build tools is no longer supported by current versions of Cygwin, so this architecture has been -removed. Use the MinWG tools and the win32-x86-mingw architecture instead.

+removed. Use the MinWG tools and the win32-x86-mingw architecture instead. -

RTEMS and VxWorks Test Harnesses

+### RTEMS and VxWorks Test Harnesses -

The original libCom test harness has been renamed libComTestHarness, -and two additional test harnesses have been created dbTestHarness and -filterTestHarness which are all built for RTEMS and vxWorks targets. -The new ones include tests in src/ioc/db/test and src/std/filters/test.

+The original libCom test harness has been renamed `libComTestHarness`, +and two additional test harnesses have been created `dbTestHarness` and +`filterTestHarness` which are all built for RTEMS and vxWorks targets. +The new ones include tests in src/ioc/db/test and src/std/filters/test. -

Running the new tests requires additional .db and .dbd files to be loaded at +Running the new tests requires additional .db and .dbd files to be loaded at runtime, which can be found in the relevant source directory or its O.Common subdirectory. If the target can access the Base source tree directly it may be simplest to cd to the relevant source directory before running the test. If not, the files needed are listed in the generated 'testspec' file found in the -associated build (O.arch) directory.

+associated build (O.*arch*) directory. -

For RTEMS users the current directory is determined in a BSP specific way. -See rtems_init.c and setBootConfigFromNVRAM.c in src/libCom/RTEMS.

+For RTEMS users the current directory is determined in a BSP specific way. +See `rtems_init.c` and `setBootConfigFromNVRAM.c` in `src/libCom/RTEMS`. -

New API to hook into thread creation

+### New API to hook into thread creation -

A hook API has been added allowing user-supplied functions to be called +A hook API has been added allowing user-supplied functions to be called whenever a thread starts. The calls are made from the thread's context, and can be used to control additional thread properties not handled inside EPICS base, e.g. setting the scheduling policy or CPU affinity (on SMP -systems).

+systems). -

The API also supports a mapping operation, calling a user-supplied function -for every thread that is currently running.

+The API also supports a mapping operation, calling a user-supplied function +for every thread that is currently running. -

New scan rate units

+### New scan rate units -

Scan rates defined in the menuScan.dbd file may now be specified in seconds, +Scan rates defined in the menuScan.dbd file may now be specified in seconds, minutes, hours or Hertz, and plural time units will also be accepted (seconds -are used if no unit is mentioned in the choice string). At iocInit each +are used if no unit is mentioned in the choice string). At `iocInit` each scan rate is compared with the OS's clock tick and a warning printed if the rate is too fast or likely to be more than 10% different to the requested rate. For example the rates given below are all valid, although non-standard (the -default menuScan choices that come with Base have not been changed):

+default menuScan choices that come with Base have not been changed): -
-
menu(menuScan) {
-    choice(menuScanPassive,     "Passive")
-    choice(menuScanEvent,       "Event")
-    choice(menuScanI_O_Intr,    "I/O Intr")
-    choice(menuScan1_hour,      "1 hour")
-    choice(menuScan0_5_hours, "0.5 hours")
-    choice(menuScan15_minutes, "15 minutes")
-    choice(menuScan5_minutes,   "5 minutes")
-    choice(menuScan1_minute,    "1 minute")
-    choice(menuScan10_seconds, "10 seconds")
-    choice(menuScan5_seconds,   "5 seconds")
-    choice(menuScan2_seconds,   "2 seconds")
-    choice(menuScan1_second,    "1 second")
-    choice(menuScan2_Hertz,     "2 Hertz")
-    choice(menuScan5_Hertz,     "5 Hertz")
-    choice(menuScan10_Hertz,   "10 Hz")
-}
+``` + menu(menuScan) { + choice(menuScanPassive, "Passive") + choice(menuScanEvent, "Event") + choice(menuScanI_O_Intr, "I/O Intr") + choice(menuScan1_hour, "1 hour") + choice(menuScan0_5_hours, "0.5 hours") + choice(menuScan15_minutes, "15 minutes") + choice(menuScan5_minutes, "5 minutes") + choice(menuScan1_minute, "1 minute") + choice(menuScan10_seconds, "10 seconds") + choice(menuScan5_seconds, "5 seconds") + choice(menuScan2_seconds, "2 seconds") + choice(menuScan1_second, "1 second") + choice(menuScan2_Hertz, "2 Hertz") + choice(menuScan5_Hertz, "5 Hertz") + choice(menuScan10_Hertz, "10 Hz") + } +``` -

Alarm filtering added to input record types

+### Alarm filtering added to input record types -

The record types ai, calc, longin and mbbi have a new alarm filter added to +The record types ai, calc, longin and mbbi have a new alarm filter added to them. This provides a low-pass filter that can be used to delay the reporting of alarms caused by the input level passing the HIGH, HIHI, LOW or LOLO values. The filter is controlled with a new AFTC field that sets the filter's time constant. The default value for this field is zero, which keeps the record's original -alarm behaviour.

+alarm behaviour. -

The record must be scanned often enough for the filtering action to work +The record must be scanned often enough for the filtering action to work effectively and the alarm severity can only change when the record is processed, but that processing does not have to be regular; the filter uses the time since the record last processed in its calculation. Setting AFTC to a positive number of seconds will delay the record going into or out of a minor alarm severity or from minor to major severity until the input signal has been in that range for -that number of seconds.

+that number of seconds. -

Post events on Waveform record's NORD field

+### Post events on Waveform record's NORD field -

When the record type or device support modify the NORD field of a waveform -record, the record support code now posts DBE_VALUE and DBE_LOG events for that -field, signalling the array length change to any client monitoring the NORD -field.

+When the record type or device support modify the NORD field of a waveform +record, the record support code now posts `DBE_VALUE` and `DBE_LOG` events for that +field, signaling the array length change to any client monitoring the NORD +field. -

Attributes of Non-VAL Fields

+### Attributes of Non-VAL Fields -

Non-VAL fields now report meaningful information for precision, units, +Non-VAL fields now report meaningful information for precision, units, graphic limits, control limits, and alarm limits instead of simply using PREC, EGU, HOPR, LOPR, DRVL, DRVH, HIHI, HIGH, LOW, and LOLO. All delay fields have a default precision of 2 digits, units "s" and control limits of 0 to 100,000 seconds (these precision and limit values can be changed for each record type as a whole at runtime by updating a registered global variable). Input fields like A-L of the calc record read their metadata -from the corresponding INPn link if possible.

-

epicsStdioRedirect.h merged into epicsStdio.h

+from the corresponding INPn link if possible. -

The definitions from the header file epicsStdioRedirect.h have been moved +#### epicsStdioRedirect.h merged into epicsStdio.h + +The definitions from the header file epicsStdioRedirect.h have been moved into epicsStdio.h so all calls to printf(), puts() and putchar() in files that -include that OSI header will now be subject to stdout redirection. In past +include that OSI header will now be subject to stdout redirection. In past releases (3.14.7 and later) it was necessary to request the redirection support -by including the epicsStdioRedirect.h header file. The header file is still -provided, but now it just includes epicsStdio.h.

+by including the epicsStdioRedirect.h header file. The header file is still +provided, but now it just includes epicsStdio.h. -

Named Soft Events

+#### Named Soft Events -

Soft events can now be given meaningful names instead of just using the -numbers 1-255. The EVNT field is now a DBF_STRING. The post_event() API +Soft events can now be given meaningful names instead of just using the +numbers 1-255. The EVNT field is now a `DBF_STRING`. The `post_event()` API is now deprecated but still works. It should be replaced by code that in advance -looks up the EVNTPVT event handle associated with the named event by -calling eventNameToHandle(char *), and when that event occurs passes -that handle to the new postEvent(EVNTPVT) routine (which may be called -from interrupt level). A new iocsh command postEvent name will +looks up the `EVNTPVT` event handle associated with the named event by +calling `eventNameToHandle(char *)`, and when that event occurs passes +that handle to the new `postEvent(EVNTPVT)` routine (which may be called +from interrupt level). A new iocsh command `postEvent name` will trigger a named event from the command-line or a startup script (on vxWorks the -expression postEvent(eventNameToHandle("name")) must be used -instead though).

+expression `postEvent(eventNameToHandle("name"))` must be used +instead though). -

Parallel Builds

+#### Parallel Builds -

As EPICS sites get computers with more CPUs they report additional bugs in our parallel build rules. Various issues have been fixed by separating out the build rules that generate dependency (.d) files, ensuring that they are constructed at -the appropriate time in the build.

+the appropriate time in the build. -

These rule changes can cause additional warning messages to appear when building support modules. Where an application provides its own Makefile rules it may now have to add rules to construct an associated dependency file. In many cases though the change needed is just to replace a dependency for a -target$(OBJ) with the target$(DEP) so this

+`target$(OBJ)` with the `target$(DEP)` so this -
-    myLib$(OBJ): myLib_lex.c
+``` + myLib$(OBJ): myLib_lex.c +``` -

-becomes

+becomes -
-    myLib$(DEP): myLib_lex.c
+``` + myLib$(DEP): myLib_lex.c +``` -

-To debug build issues assocated with dependency files, use the command make ---debug=m which tells GNUmake to display information about what it is doing -during the first pass when it updates its makefiles.

+To debug build issues associated with dependency files, use the command +`make --debug=m` which tells GNUmake to display information about what it is doing +during the first pass when it updates its makefiles. -

-Removed tsDefs.h

+### Removed tsDefs.h -

The deprecated tsDefs API was provided for 3.13 compatibility only, and has now -been removed. Convert any remaining code that used it to call the epicsTime API -instead.

+been removed. Convert any remaining code that used it to call the epicsTime API +instead. -

-Changes to epicsVersion.h

+### Changes to epicsVersion.h -

-The two macros EPICS_UPDATE_LEVEL and EPICS_CVS_SNAPSHOT have +The two macros `EPICS_UPDATE_LEVEL` and `EPICS_CVS_SNAPSHOT` have been deleted from the epicsVersion.h file; they were deprecated in R3.14 and can -be replaced with EPICS_PATCH_LEVEL and EPICS_DEV_SNAPSHOT -respectively.

+be replaced with `EPICS_PATCH_LEVEL` and `EPICS_DEV_SNAPSHOT` +respectively. -

A new pair of macros has been added to make version number comparisons easier. Code that will not work with a version of Base before 3.15.0 can now be -written like this to prevent it from compiling:

+written like this to prevent it from compiling: -
-#if defined(VERSION_INT) && EPICS_VERSION_INT < VERSION_INT(3,15,0,0)
-#  error EPICS Base R3.15.0 or later is required
-#endif
-
+``` + #if defined(VERSION_INT) && EPICS_VERSION_INT < VERSION_INT(3,15,0,0) + # error EPICS Base R3.15.0 or later is required + #endif + ``` -

-Added support for iocLogPrefix

+### Added support for iocLogPrefix -

-Added a iocLogPrefix command to iocsh. This adds a +Added a `iocLogPrefix` command to `iocsh`. This adds a prefix to all messages from this IOC (or other log client) as they get sent to the -iocLogServer. This lets sites use the "fac=<facility>" syntax for +iocLogServer. This lets sites use the `fac=` syntax for displaying the facility, process name etc. in log viewers like the -cmlogviewer.

+`cmlogviewer`. -

-Reworked the epicsEvent C & C++ APIs

+### Reworked the epicsEvent C & C++ APIs -
    -
  • Renamed the enum epicsEventWaitStatus to epicsEventStatus
  • -
  • Defined epicsEventWaitStatus as a macro for epicsEventStatus
  • -
  • Renamed epicsEventWaitOk to epicsEventOk
  • -
  • Renamed epicsEventWaitError to epicsEventError
  • -
  • Defined epicsEventWaitOK and epicsEventWaitError as macros
  • -
  • Added epicsEventTrigger(id) which triggers an event and returns OK or an - error status if the underlying OS primitives report an error
  • -
  • Added epicsEventMustTrigger(id) which halts on error
  • -
  • Defined epicsEventSignal(id) as a macro for epicsEventMustTrigger(id)
  • -
  • Added a new C++ method epicsEvent::trigger() which throws an - epicsEvent::invalidSemaphore in the event of an error
  • -
  • epicsEvent::signal() makes an inline call to epicsEvent::trigger()
  • -
  • epicsEventWait() and epicsEventWaitWithTimeout() now return an error - status if the underlying OS primitives report an error
  • -
  • All the epicsEventMust...() routines are now implemented in the common + - Renamed the enum epicsEventWaitStatus to epicsEventStatus + - Defined epicsEventWaitStatus as a macro for epicsEventStatus + - Renamed epicsEventWaitOk to epicsEventOk + - Renamed epicsEventWaitError to epicsEventError + - Defined epicsEventWaitOK and epicsEventWaitError as macros + - Added epicsEventTrigger(id) which triggers an event and returns OK or an + error status if the underlying OS primitives report an error + - Added epicsEventMustTrigger(id) which halts on error + - Defined epicsEventSignal(id) as a macro for epicsEventMustTrigger(id) + - Added a new C++ method epicsEvent::trigger() which throws an + epicsEvent::invalidSemaphore in the event of an error + - epicsEvent::signal() makes an inline call to epicsEvent::trigger() + - epicsEventWait() and epicsEventWaitWithTimeout() now return an error + status if the underlying OS primitives report an error + - All the epicsEventMust...() routines are now implemented in the common libCom/osi/epicsEvent.cpp source file, and call cantProceed() instead of - mis-using assert()
  • -
  • Implemented epicsEventShow() on Posix
  • -
  • Win32: Removed all epicsShareAPI decorations
  • -
+ mis-using assert() + - Implemented epicsEventShow() on Posix + - Win32: Removed all epicsShareAPI decorations -

-Enabled histogram record type

+### Enabled histogram record type -

The histogram record was not included in the base.dbd file in any 3.14 release, but has now been added along with its associated soft device support. The build system now generates the list of all the record.dbd files in base automatically -in src/std/rec/Makefile.

+in src/std/rec/Makefile. -

-Reorganization of src/

+### Reorganization of src/ -

Reorganization of subdirectories of src/ to better represent the relation -between different parts as described in the following table.

+Reorganization of subdirectories of src/ to better represent the relation +between different parts as described in the following table. -

This change also allows the number of libraries built to be reduced to: -libCap5.so, libca.so, libdbCore.so, libdbStaticHost.so, -libCom.so, libcas.so, libdbRecStd.so, and libgdd.so

+This change also allows the number of libraries built to be reduced to: +libCap5.so, libca.so, libdbCore.so, libdbStaticHost.so, +libCom.so, libcas.so, libdbRecStd.so, and libgdd.so - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ComponentDependencyLibrary nameDescription
src/toolsBuild system scripts
src/libComsrc/toolsComUtility routines and OS-independant API
src/templatesrc/toolsUser application templates (e.g. makeBaseApp)
src/ca/clientsrc/libComcaChannel Access client
src/ca/legacy/gddsrc/ca/clientgddGeneric data layer for PCAS
src/ca/legacy/pcassrc/ca/legacy/gddcasPortable Channel Access Server
src/iocsrc/cadbCoreCore database processing functions
src/stdsrc/iocdbRecStdStandard records, soft device support and the softIoc
+| Component | Dependency | Library name | Description | +| ------------------ | ----------------- | ------------ | ----------------------------------------------------- | +| src/tools | | | Build system scripts | +| src/libCom | src/tools | Com | Utility routines and OS-independant API | +| src/template | src/tools | | User application templates (e.g. makeBaseApp) | +| src/ca/client | src/libCom | ca | Channel Access client | +| src/ca/legacy/gdd | src/ca/client | gdd | Generic data layer for PCAS | +| src/ca/legacy/pcas | src/ca/legacy/gdd | cas | Portable Channel Access Server | +| src/ioc | src/ca | dbCore | Core database processing functions | +| src/std | src/ioc | dbRecStd | Standard records, soft device support and the softIoc | -

In order to better reflect these relations the following -directories and files were moved as described:

+directories and files were moved as described: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Relocations
PreviousNew
libCom
src/RTEMSsrc/libCom/RTEMS
src/toolsComm/flexsrc/libCom/flex
src/toolsComm/antelopesrc/libCom/yacc
src/dbStatic/alarm.h
.../alarmString.h
src/libCom/misc/
IOC Core Components
src/bptsrc/ioc/bpt
src/dbsrc/ioc/db
src/dbStaticsrc/ioc/dbStatic
src/dbtoolssrc/ioc/dbtemplate
src/miscsrc/ioc/misc
src/registrysrc/ioc/registry
src/rsrvsrc/ioc/rsrv 1
Standard Record Definitions
src/dev/softDevsrc/std/dev
src/recsrc/std/rec
src/softIocsrc/std/softIoc
Channel Access
src/casrc/ca/client
src/catoolssrc/ca/client/tools
src/cap5src/ca/client/perl
src/gddsrc/ca/legacy/gdd
src/cassrc/ca/legacy/pcas
src/excassrc/ca/legacy/pcas/ex
User Templates
src/makeBaseAppsrc/template/base
src/makeBaseExtsrc/template/ext
Dispersed
src/util 2src/ca/client
src/ca/client/test
src/libCom/log
src/as 3src/libCom/as
src/ioc/as
+#### Relocations -

1 +Category | Previous | New +:--- | :--- | :--- +libCom | srcRTEMS | src/libCom/RTEMS +| | src/toolsComm/flex | src/libCom/flex | +| | src/toolsComm/antelope | src/libCom/yacc +| | src/dbStatic/alarm.h | src/libCom/misc +| | .../alarmString.h | src/libCom/misc +IOC Core Components | src/bpt | src/ioc/bpt +| | src/db | src/ioc/db +| | src/dbStatic | src/ioc/dbStatic +| | src/dbtools | src/ioc/dbtemplate +| | src/misc | src/ioc/misc +| | src/registry | src/ioc/registry +| | src/rsrv | src/ioc/rsrv [1](#rsrv) +Standard Record Definitions | src/dev/softDev | src/std/dev +| | src/rec | src/std/rec +| | src/softIoc | src/std/softIoc +Channel Access | src/ca | src/ca/client +| | src/catools | src/ca/client/tools +| | src/cap5 | src/ca/client/perl +| | src/gdd | src/ca/legacy/gdd +| | src/cas | src/ca/legacy/pcas +| | src/excas | src/ca/legacy/pcas/ex +User Templates | src/makeBaseApp | src/template/base +| | src/makeBaseExt | src/template/ext +Dispersed | src/util [2](#util) | src/ca/client +| | | src/ca/client/test +| | | src/libCom/log +| | src/as [3](#as) | src/libCom/as +| | | src/ioc/as + +1 RSRV is built as part of dbCore due to its tight (bidirectional) coupling -with the other database code.

+with the other database code. -

2 -The contents for src/util/ moved to three locations. The caRepeater init script -was moved to src/ca/client/. ca_test is now in src/ca/client/test/. +2 +The contents for src/util/ moved to three locations. The caRepeater init script +was moved to src/ca/client/. `ca_test` is now in src/ca/client/test/. The iocLogServer was moved into the same directory (src/libCom/log) as -the log client code.

+the log client code. -

3 +3 The Access Security code has been divided, with the parts not related to the database (lexer/parser and trap registration) becoming part of libCom. -The remaining components are included in the dbCore library

+The remaining components are included in the dbCore library -

-Moved src/RTEMS/base directory

+### Moved src/RTEMS/base directory -

-These files are now found under src/RTEMS.

+These files are now found under src/RTEMS. -

-Removed 3.13 compatibility

+### Removed 3.13 compatibility -

-Removed the 3.13 <top>/config directory and build compatibility rules and -variables, and various conversion documents.

- - - +Removed the 3.13 `/config` directory and build compatibility rules and +variables, and various conversion documents. From 9efefad9554961d8eda8d01fb6107d5e824dc693 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 10 Oct 2019 00:57:45 -0400 Subject: [PATCH 29/47] Fix markdown formatting issue --- documentation/RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 133c823a0..7580b3a3b 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -1490,7 +1490,7 @@ written like this to prevent it from compiling: #if defined(VERSION_INT) && EPICS_VERSION_INT < VERSION_INT(3,15,0,0) # error EPICS Base R3.15.0 or later is required #endif - ``` +``` ### Added support for iocLogPrefix From 0a01c386984db607fb7f79bdde7482d64f9311a8 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 10 Oct 2019 12:12:41 -0400 Subject: [PATCH 30/47] File renames .dbd to .dbd.pod for stringout --- src/ioc/db/{menuIvoa.dbd => menuIvoa.dbd.pod} | 0 src/ioc/db/{menuOmsl.dbd => menuOmsl.dbd.pod} | 0 src/ioc/db/{menuYesNo.dbd => menuYesNo.dbd.pod} | 0 src/std/rec/{stringoutRecord.dbd => stringoutRecord.dbd.pod} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/ioc/db/{menuIvoa.dbd => menuIvoa.dbd.pod} (100%) rename src/ioc/db/{menuOmsl.dbd => menuOmsl.dbd.pod} (100%) rename src/ioc/db/{menuYesNo.dbd => menuYesNo.dbd.pod} (100%) rename src/std/rec/{stringoutRecord.dbd => stringoutRecord.dbd.pod} (100%) diff --git a/src/ioc/db/menuIvoa.dbd b/src/ioc/db/menuIvoa.dbd.pod similarity index 100% rename from src/ioc/db/menuIvoa.dbd rename to src/ioc/db/menuIvoa.dbd.pod diff --git a/src/ioc/db/menuOmsl.dbd b/src/ioc/db/menuOmsl.dbd.pod similarity index 100% rename from src/ioc/db/menuOmsl.dbd rename to src/ioc/db/menuOmsl.dbd.pod diff --git a/src/ioc/db/menuYesNo.dbd b/src/ioc/db/menuYesNo.dbd.pod similarity index 100% rename from src/ioc/db/menuYesNo.dbd rename to src/ioc/db/menuYesNo.dbd.pod diff --git a/src/std/rec/stringoutRecord.dbd b/src/std/rec/stringoutRecord.dbd.pod similarity index 100% rename from src/std/rec/stringoutRecord.dbd rename to src/std/rec/stringoutRecord.dbd.pod From ee38b99e0fe23280a08d35c84963868b598a35a5 Mon Sep 17 00:00:00 2001 From: Saeed Haghtalab Date: Fri, 6 Sep 2019 10:36:29 +0200 Subject: [PATCH 31/47] Adding POD to stringout record Also to menuYesNo, menuOmsl, menuIvoa menus --- src/ioc/db/menuIvoa.dbd.pod | 15 +- src/ioc/db/menuOmsl.dbd.pod | 18 +- src/ioc/db/menuYesNo.dbd.pod | 22 +- src/std/rec/stringoutRecord.dbd.pod | 368 ++++++++++++++++++++++++++-- 4 files changed, 395 insertions(+), 28 deletions(-) diff --git a/src/ioc/db/menuIvoa.dbd.pod b/src/ioc/db/menuIvoa.dbd.pod index b1b3ce51f..8ea2c7a7d 100644 --- a/src/ioc/db/menuIvoa.dbd.pod +++ b/src/ioc/db/menuIvoa.dbd.pod @@ -3,10 +3,19 @@ # National Laboratory. # Copyright (c) 2002 The Regents of the University of California, as # Operator of Los Alamos National Laboratory. -# EPICS BASE Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Menu menuIvoa + +This menu specifies the possibile actions to take when the INVALID alarm is +triggered. See individual record types for more information. + +=menu menuIvoa + +=cut + menu(menuIvoa) { choice(menuIvoaContinue_normally,"Continue normally") choice(menuIvoaDon_t_drive_outputs,"Don't drive outputs") diff --git a/src/ioc/db/menuOmsl.dbd.pod b/src/ioc/db/menuOmsl.dbd.pod index 3022437dc..833f44354 100644 --- a/src/ioc/db/menuOmsl.dbd.pod +++ b/src/ioc/db/menuOmsl.dbd.pod @@ -3,10 +3,22 @@ # National Laboratory. # Copyright (c) 2002 The Regents of the University of California, as # Operator of Los Alamos National Laboratory. -# EPICS BASE Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Menu menuOmsl + +This menu is used for the C field of many output record types. It controls +whether the record will fetch an input value from its C input link when +processed, which is useful when it is part of a closed loop control algorithm. +The C state means the input link will not be used, C +enables the input link. + +=menu menuOmsl + +=cut + menu(menuOmsl) { choice(menuOmslsupervisory,"supervisory") choice(menuOmslclosed_loop,"closed_loop") diff --git a/src/ioc/db/menuYesNo.dbd.pod b/src/ioc/db/menuYesNo.dbd.pod index 2d09dd65a..d4237e7b8 100644 --- a/src/ioc/db/menuYesNo.dbd.pod +++ b/src/ioc/db/menuYesNo.dbd.pod @@ -3,10 +3,26 @@ # National Laboratory. # Copyright (c) 2002 The Regents of the University of California, as # Operator of Los Alamos National Laboratory. -# EPICS BASE Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Menu menuYesNo + +This menu is used by many record types to specify simple C or C +options for record-specific purposes. + +Note that no other values for a field that uses menuYesNo are possible, e.g. +C or C would not be accepted as choices for the field. +Also, the choices C, C, and C are not valid choices since they +don't match the case of C or C. +The integer values C<0> and C<1> may often be used instead however, they are +used as an index into the choices so C<0> becomes C and C<1> becomes . + +=menu menuYesNo + +=cut + menu(menuYesNo) { choice(menuYesNoNO,"NO") choice(menuYesNoYES,"YES") diff --git a/src/std/rec/stringoutRecord.dbd.pod b/src/std/rec/stringoutRecord.dbd.pod index fe0bae5d0..5e6caf758 100644 --- a/src/std/rec/stringoutRecord.dbd.pod +++ b/src/std/rec/stringoutRecord.dbd.pod @@ -6,12 +6,80 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 String Output Record (stringout) + +The stringout record is used to write an arbitrary ASCII string of up to 40 +characters to other records or software variables. + +=head2 Contents + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=back + +=back + +=begin html + +
+
+
+ +=end html + +=recordtype stringout + +=cut + +include "menuIvoa.dbd" + menu(stringoutPOST) { choice(stringoutPOST_OnChange,"On Change") choice(stringoutPOST_Always,"Always") } recordtype(stringout) { - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_STRING) { prompt("Current Value") promptgroup("50 - Output") @@ -19,12 +87,41 @@ recordtype(stringout) { pp(TRUE) size(40) } - field(OVAL,DBF_STRING) { - prompt("Previous Value") - special(SPC_NOMOD) - interest(3) - size(40) - } + +=head2 Parameter Fields + +=head3 Scan Parameters + +The string output record has the standard fields for specifying under what +circumstances it will be processed. These fields are listed in +L. +In addition, L +explains how these fields are used. + +=head3 Desired Output Parameters + +The string output record must specify from where it gets its desired output +string. The first field that determines where the desired output originates is +the output mode select (OSML) field, which can have two possible value: C<<< +closed_loop >>> or C<<< supervisory >>>. If C<<< supervisory >>> is specified, +DOL is ignored, the current value of VAL is written, and the VAL can be changed +externally via dbPuts at run-time. If C<<< closed_loop >>> is specified, the VAL +field's value is obtained from the address specified in the desired output +location field (DOL) which can be either a database link or a channel access +link. + +DOL can also be a constant in addition to a link, in which case VAL is +initialized to the constant value. However, your string constant may be +interpreted as a CA link name, so if you want to initialize your string output +record, it's best to use the VAL field. Note that if DOL is a constant, OMSL +cannot be C<<< closed_loop. >>> See +L
+for information on specifying links. + +=fields VAL, DOL, OMSL + +=cut + field(DOL,DBF_INLINK) { prompt("Desired Output Loc") promptgroup("40 - Input") @@ -36,11 +133,42 @@ recordtype(stringout) { interest(1) menu(menuOmsl) } + +=head3 Write Parameters + +The output link specified in the OUT field specifies where the string output +record is to write its string. The link can be a database or channel access +link. If the OUT field is a constant, no output will be written. See L
for information on specifying links. + +In addition, the appropriate device support module must be entered into the DTYP +field. + +=fields OUT, DTYP + +=cut + field(OUT,DBF_OUTLINK) { prompt("Output Specification") promptgroup("50 - Output") interest(1) } + +=head3 Monitor Parameters + +These parameters are used to specify when the monitor post should be sent by +C routine. There are two possible choices: + +=head4 Menu stringoutPOST + +=menu stringoutPOST + +APST is used for archiver monitors and MPST is for all other type of monitors. + +=fields MPST, APST + +=cut + field(MPST,DBF_MENU) { prompt("Post Value Monitors") promptgroup("80 - Display") @@ -53,6 +181,78 @@ recordtype(stringout) { interest(1) menu(stringoutPOST) } + +=head3 Operator Display Parameters + +These parameters are used to present meaningful data to the operator. These +fields are used to display the value and other parameters of the string output +either textually or graphically. + +See L +for more on the record name (NAME) and description (DESC) fields. + +=fields NAME, DESC + +=head3 Alarm Parameters + +The possible alarm conditions for the string output record are the SCAN, READ, +and INVALID alarms. The severity of the first two is always MAJOR and not +configurable. + +The IVOA field specifies an action to take when the INVALID alarm is triggered. +There are three possible actions: + +=head4 Menu menuIvoa + +=menu menuIvoa + +When C<<< Set output to IVOV >>>, the value contained in the IVOV field is +written to the output link during an alarm condition. See +L +for more information on the IVOA and IVOV fields. +L +lists other fields related to a alarms that are common to all record types. + +=fields IVOA, IVOV + +=cut + + field(IVOA,DBF_MENU) { + prompt("INVALID output action") + promptgroup("50 - Output") + interest(2) + menu(menuIvoa) + } + field(IVOV,DBF_STRING) { + prompt("INVALID output value") + promptgroup("50 - Output") + interest(2) + size(40) + } + +=head3 Run-time and Simulation Mode Parameters + +The old value field (OVAL) of the string input is used to implement value change +monitors for VAL. If VAL is not equal to OVAL, then monitors are triggered. + +=fields OVAL + +The following fields are used to operate the string output in the simulation +mode. See +L +for more information on these fields. + +=fields SIOL, SIML, SIMM, SIMS + +=cut + + field(OVAL,DBF_STRING) { + prompt("Previous Value") + special(SPC_NOMOD) + interest(3) + size(40) + } + field(SIOL,DBF_OUTLINK) { prompt("Sim Output Specifctn") promptgroup("90 - Simulate") @@ -74,16 +274,146 @@ recordtype(stringout) { interest(2) menu(menuAlarmSevr) } - field(IVOA,DBF_MENU) { - prompt("INVALID output action") - promptgroup("50 - Output") - interest(2) - menu(menuIvoa) - } - field(IVOV,DBF_STRING) { - prompt("INVALID output value") - promptgroup("50 - Output") - interest(2) - size(40) - } + +=begin html + +
+
+
+ +=end html + +=head2 Record Support + +=head3 Record Support Routines (stringoutRecord.c) + +=head4 init_record + + long (*init_record)(struct dbCommon *precord, int pass) + +This routine initializes SIMM if SIML is a constant or creates a channel access +link if SIML is PV_LINK. If SIOL is PV_LINK a channel access link is created. + +This routine next checks to see that device support is available. The routine +next checks to see if the device support write routine is defined. If either +device support or the device support write routine does not exist, an error +message is issued and processing is terminated. + +If DOL is a constant, then the type double constant, if non-zero, is converted +to a string and stored into VAL and UDF is set to FALSE. If DOL type is a +PV_LINK then dbCaAddInlink is called to create a channel access link. + +If device support includes C, it is called. + +=head4 process + + long (*process)(struct dbCommon *precord) + +See L. + +=head3 Record Processing + +Routine process implements the following algorithm: + +=over + +=item 1. + +Check to see that the appropriate device support module exists. If it doesn't, +an error message is issued and processing is terminated with the PACT field +still set to TRUE. This ensures that processes will no longer be called for this +record. Thus error storms will not occur. + +=item 2. + +If PACT is FALSE and OMSL is CLOSED_LOOP, recGblGetLinkValue is called to read +the current value of VAL. See L. +If the return status of recGblGetLinkValue is zero then UDF is set to FALSE. + +=item 3. + +Check severity and write the new value. See +L +and L +for details on how the simulation mode and the INVALID alarm conditions affect output. + +=item 4. + +If PACT has been changed to TRUE, the device support write output routine has +started but has not completed writing the new value. In this case, the +processing routine merely returns, leaving PACT TRUE. + +=item 5. + +Check to see if monitors should be invoked. + +=over + +=item * + +Alarm monitors are invoked if the alarm status or severity has changed. + +=item * + +Archive and value change monitors are invoked if OVAL is not equal to VAL. + +=item * + +NSEV and NSTA are reset to 0. + +=back + +=item 6. + +Scan forward link if necessary, set PACT FALSE, and return. + +=back + +=begin html + +
+
+
+ +=end html + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each stringout output record must have an associated set of device support +routines. The primary responsibility of the device support routines is to write +a new value whenever write_stringout is called. The device support routines are +primarily interested in the following fields: + +=fields PACT, DPVT, NSEV, NSTA, VAL, OUT + +=head3 Device Support Routines (devSoSoft.c) + +=head4 write_stringout + + long write_stringout(stringoutRecord *prec) + +This routine must output a new value. It returns the following values: + +=over + +=item * 0: Success. + +=item * Other: Error. + +=back + +=head3 Device Support for Soft Records + +The C<<< Soft Channel >>> device support module writes the current value of VAL. + +If the OUT link type is PV_LINK, then dbCaAddInlink is called by +C. + +write_so calls recGblPutLinkValue to write the current value of VAL. See +L. + +=cut + } From 7ca26c515aec7897f1cb9298832be64a560d1be9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 10 Oct 2019 14:46:18 -0400 Subject: [PATCH 32/47] Clean up stringin POD links --- src/std/rec/stringinRecord.dbd.pod | 33 ++++++++++++------------------ 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/std/rec/stringinRecord.dbd.pod b/src/std/rec/stringinRecord.dbd.pod index 2dd305502..1de0cbe85 100644 --- a/src/std/rec/stringinRecord.dbd.pod +++ b/src/std/rec/stringinRecord.dbd.pod @@ -77,7 +77,7 @@ menu(stringinPOST) { choice(stringinPOST_Always,"Always") } recordtype(stringin) { - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_STRING) { prompt("Current Value") promptgroup("40 - Input") @@ -91,11 +91,8 @@ recordtype(stringin) { =head3 Scan Parameters The string input record has the standard fields for specifying under what -circumstances it will be processed. These fields are listed in -L. -In addition, -L -explains how these fields are used. +circumstances it will be processed. These fields are listed in L. +In addition, L explains how these fields are used. =head3 Read Parameters @@ -107,8 +104,7 @@ placed in the VAL field. The maximum number of characters that the string in VAL can be is 40. In addition, the appropriate device support module must be entered into the DTYP field. -See L
-for information on specifying links. +See L
for information on specifying links. =fields VAL, INP, DTYP @@ -122,7 +118,7 @@ for information on specifying links. =head3 Monitor Parameters -These parameters are used to specify when the monitor post should be sent by +These parameters are used to specify when the monitor post should be sent by C routine. There are two possible choices: =head4 Menu stringinPOST @@ -150,16 +146,16 @@ APST is used for archiver monitors and MPST is for all other type of monitors. =head3 Operator Display Parameters -See L -for more on the record name (NAME) and description (DESC) fields. +See L for more on the record name (NAME) and +description (DESC) fields. =fields NAME, DESC =head3 Alarm Parameters The string input record has the alarm parameters common to all record types. -L -lists other fields related to a alarms that are common to all record types. +L lists other fields related to a alarms that are common to all +record types. =head3 Run-time and Simulation Mode Parameters @@ -171,9 +167,7 @@ monitors for VAL. If VAL is not equal to OVAL, then monitors are triggered. The following fields are used to operate the string input in the simulation -mode. See -L -for more information on simulation mode fields. +mode. See L for more information on simulation mode fields. =fields SIOL, SVAL, SIML, SIMM, SIMS @@ -259,9 +253,8 @@ record. Thus error storms will not occur. =item 2. -readValue is called. See -L -for more information on simulation mode fields and how they affect input. +readValue is called. See L for more information on simulation +mode fields and how they affect input. =item 3. @@ -350,7 +343,7 @@ to a string and stored into VAL by C, and UDF is set to FALSE. If the INP link type is PV_LINK, then dbCaAddInlink is called by C. read_stringin calls recGblGetLinkValue to read the current value of VAL. See -L. +L. If the return status of recGblGetLinkValue is zero, then read_stringin sets UDF to FALSE. The status of recGblGetLinkValue is returned. From e0950643bbfe05895a807539bbb230d78d6edada Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 10 Oct 2019 14:53:10 -0400 Subject: [PATCH 33/47] Clean up state POD links --- src/std/rec/stateRecord.dbd.pod | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/std/rec/stateRecord.dbd.pod b/src/std/rec/stateRecord.dbd.pod index 8734f01bd..9dab4b53a 100644 --- a/src/std/rec/stateRecord.dbd.pod +++ b/src/std/rec/stateRecord.dbd.pod @@ -14,7 +14,7 @@ interface. Its only function is to provide a place in the database through which the state program can inform the operator interface of its state by storing an arbitrary ASCII string in its VAL field. -B +B =head2 Contents @@ -55,31 +55,28 @@ B. -In addition, -L -explains how these fields are used. +it will be processed. These fields are listed in L. In addition, +L explains how these fields are used. =head3 Operator Display Parameters -See L -for more on the record name (NAME) and description (DESC) fields. +See L for more on the record name (NAME) and +description (DESC) fields. =fields NAME, DESC =head3 Alarm Parameters -The state record has the alarm parameters common to all record types. -L -lists other fields related to a alarms that are common to all record types. +The state record has the alarm parameters common to all record types. +L lists other fields related to a alarms that are common to all +record types. =head3 Run-time Parameters @@ -87,7 +84,7 @@ These parameters are used by the application code to convey the state of the program to the operator interface. The VAL field holds the string retrieved from the state program. The OVAL is used to implement monitors for the VAL field. When the string in OVAL differs from the one in VAL, monitors are triggered. -They represent the current state of the sequence program. +They represent the current state of the sequence program. =fields VAL, OVAL @@ -115,8 +112,8 @@ They represent the current state of the sequence program. long (*process)(struct dbCommon *precord) -process triggers monitors on VAL when it changes and scans the forward link if -necessary. +C triggers monitors on VAL when it changes and scans the forward +link if necessary. =cut From 47f295fecb86773c7e6c5bc9c219a0a374224115 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 10 Oct 2019 15:02:06 -0400 Subject: [PATCH 34/47] Clean up permissive POD links --- src/std/rec/permissiveRecord.dbd.pod | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/std/rec/permissiveRecord.dbd.pod b/src/std/rec/permissiveRecord.dbd.pod index 8e0747fe9..bdcecb5e7 100644 --- a/src/std/rec/permissiveRecord.dbd.pod +++ b/src/std/rec/permissiveRecord.dbd.pod @@ -14,7 +14,7 @@ example would be a sequence program server and an operator interface client. By using multiple permissive records a sequence program can communicate its current state to the client. -B +B =head2 Contents @@ -59,19 +59,17 @@ B. -In addition, -L - explains how these fields are used. Since the permissive record supports - no direct interfaces to hardware, its SCAN field cannot be C<<< I/O Intr >>>. +circumstances the record will be processed. These fields are listed in +L. In addition, L explains how these +fields are used. Since the permissive record supports no direct interfaces to +hardware, its SCAN field cannot be C<<< I/O Intr >>>. =head3 Client-server Parameters @@ -106,9 +104,9 @@ Note that when WFLG is ON, the client program ''must not'' turn VAL to on. =head3 Operator Display Parameters The label field (LABL) contains a string given to it that should describe the -record in further detail. In addition to the DESC field. See -L -for more on the record name (NAME) and description (DESC) fields. +record in further detail. In addition to the DESC field. See +L for more on the record name (NAME) and +description (DESC) fields. =fields LABL, NAME, DESC @@ -124,9 +122,9 @@ for more on the record name (NAME) and description (DESC) fields. =head3 Alarm Parameters -The Permissive record has the alarm parameters common to all record types. -L -lists other fields related to a alarms that are common to all record types. +The Permissive record has the alarm parameters common to all record types. +L lists other fields related to a alarms that are common to all +record types. =head3 Run-time Parameters @@ -158,9 +156,9 @@ OLFG. long (*process)(struct dbCommon *precord) -process sets UDF to FALSE, triggers monitors on VAL and WFLG when they change, -and scans the forward link if necessary. +C<<< process() >>> sets UDF to FALSE, triggers monitors on VAL and WFLG when +they change, and scans the forward link if necessary. =cut -} \ No newline at end of file +} From 3128fdb930e0f7e6afb51c24f26f291aca17725b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 17 Oct 2019 16:14:59 -0500 Subject: [PATCH 35/47] Add and use epicsProve.pl script Some Windows Perl installations don't have a working prove.bat so 'make test-results' doesn't work properly on them. --- configure/CONFIG_BASE | 1 + configure/RULES_BUILD | 2 +- src/tools/Makefile | 1 + src/tools/epicsProve.pl | 10 ++++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/tools/epicsProve.pl diff --git a/configure/CONFIG_BASE b/configure/CONFIG_BASE index 2f099be96..c979d6d7c 100644 --- a/configure/CONFIG_BASE +++ b/configure/CONFIG_BASE @@ -69,6 +69,7 @@ REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl) FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl +PROVE = $(PERL) $(TOOLS)/epicsProve.pl #------------------------------------------------------- # tools for installing libraries and products diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 7061c5658..ca05f19c6 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -351,7 +351,7 @@ testspec: $(TESTSCRIPTS) test-results: tapfiles ifneq ($(TAPFILES),) ifdef RUNTESTS_ENABLED - prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES) + $(PROVE) --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES) endif CURRENT_TAPFILES := $(wildcard $(TAPFILES)) diff --git a/src/tools/Makefile b/src/tools/Makefile index c1606c8b3..636717d90 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -39,6 +39,7 @@ PERL_SCRIPTS += assembleSnippets.pl PERL_SCRIPTS += convertRelease.pl PERL_SCRIPTS += cvsclean.pl PERL_SCRIPTS += dos2unix.pl +PERL_SCRIPTS += epicsProve.pl PERL_SCRIPTS += expandVars.pl PERL_SCRIPTS += fullPathName.pl PERL_SCRIPTS += installEpics.pl diff --git a/src/tools/epicsProve.pl b/src/tools/epicsProve.pl new file mode 100644 index 000000000..a1b0c14d4 --- /dev/null +++ b/src/tools/epicsProve.pl @@ -0,0 +1,10 @@ +#!/usr/bin/env perl + +# Some Windows Perl installations provide a prove.bat file which +# doesn't work properly. + +use App::Prove; + +my $app = App::Prove->new; +$app->process_args(@ARGV); +exit( $app->run ? 0 : 1 ); From 953dd2b7f92647ed712714ab04f376a6d9b610eb Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 17 Oct 2019 17:17:05 -0500 Subject: [PATCH 36/47] Document use of epicsProve.pl Also replaced UTF-8 smart-quotes and m-dashes with ASCII/Markdown --- documentation/RELEASE_NOTES.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 7580b3a3b..451b2371d 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -6,6 +6,14 @@ This version of EPICS Base has not been released yet. +### `make test-results` for Windows + +The make target `test-results` should now work properly on Windows. Some Perl +installations used versions of `prove.bat` that would only display the results of +up to 3 tests or didn't return an error status in the event of tests failing. The +build system now calls its own perl script to summarize the results instead of +passing a list of TAP filenames to `prove`. + ### Add option to avoid CALLBACK conflict If a macro `EPICS_NO_CALLBACK` is defined, then callback.h will no longer (re)define CALLBACK. @@ -235,23 +243,23 @@ built-in self-test programs and viewing the results. Since these targets are intended for limited use they can have requirements for the build host which go beyond the standard minimum set needed to build and run Base. -#### `test-results` — Summarize test results +#### `test-results` - Summarize test results The new make target `test-results` will run the self-tests if necessary to generate a TAP file for each test, then summarizes the TAP output files in each test directory in turn, displaying the details of any failures. -This step uses the program “prove” which comes with Perl, but also needs -“cat” to be provided in the default search path so will not work on most +This step uses the program `prove` which comes with Perl, but also needs +`cat` to be provided in the default search path so will not work on most Windows systems. -#### `junitfiles` — Convert test results to JUnit XML Format +#### `junitfiles` - Convert test results to JUnit XML Format The new make target `junitfiles` will run the self-tests if necessary and then convert the TAP output files into the more commonly-supported JUnit XML format. The program that performs this conversion needs the Perl module -“`XML::Generator`” to have been installed. +`XML::Generator` to have been installed. -#### `clean-tests` — Delete test result files +#### `clean-tests` - Delete test result files The new make target `clean-tests` removes any test result files from previous test runs. It cleans both TAP and JUnit XML files. @@ -1103,11 +1111,11 @@ configured to have a lower severity or even no alarm when undefined. Be careful when changing this on applications where the IVOA field of output records is used, IVOA still requires an INVALID severity to trigger value replacement. -### New build target “tapfiles” +### New build target `tapfiles` -This new make target runs the same tests as the “runtests” target, but +This new make target runs the same tests as the `runtests` target, but instead of summarizing or displaying the output for each test script it creates -a “.tap” file inside the architecture build directory which contains the +a `.tap` file inside the architecture build directory which contains the detailed test output. The output file can be parsed by continuous integration packages such as [Jenkins](http://www.jenkins-ci.org/) to show the test results. From b34859fb86f22e24e52ef87aee6108a66e7ca749 Mon Sep 17 00:00:00 2001 From: Joao Paulo Martins Date: Thu, 5 Sep 2019 17:35:00 +0200 Subject: [PATCH 37/47] rename .dbd to .dpd.pod for mbbiDirect --- src/std/rec/{mbbiDirectRecord.dbd => mbbiDirectRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{mbbiDirectRecord.dbd => mbbiDirectRecord.dbd.pod} (100%) diff --git a/src/std/rec/mbbiDirectRecord.dbd b/src/std/rec/mbbiDirectRecord.dbd.pod similarity index 100% rename from src/std/rec/mbbiDirectRecord.dbd rename to src/std/rec/mbbiDirectRecord.dbd.pod From 3ff62f4ddb3dd4c1fc8146fca5f29e7d84731b1c Mon Sep 17 00:00:00 2001 From: Joao Paulo Martins Date: Thu, 5 Sep 2019 17:36:51 +0200 Subject: [PATCH 38/47] Add converted mbbiDirect POD --- src/std/rec/mbbiDirectRecord.dbd.pod | 406 ++++++++++++++++++++++++++- 1 file changed, 405 insertions(+), 1 deletion(-) diff --git a/src/std/rec/mbbiDirectRecord.dbd.pod b/src/std/rec/mbbiDirectRecord.dbd.pod index 3fa3d8823..724cbfb55 100644 --- a/src/std/rec/mbbiDirectRecord.dbd.pod +++ b/src/std/rec/mbbiDirectRecord.dbd.pod @@ -6,8 +6,158 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 B + +The mbbiDirect record retrieves a sixteen-bit hardware value and converts it to +an array of sixteen unsigned characters, each representing a bit of the word. +These fields (B0-B9, BA-BF) are set to 1 if a bit is set, and 0 if not. + +This record's operation is similar to that of the multi-bit binary input record, +and it has many fields in common with it. This record also has two available +soft device support modules: C and C. + +=head1 L + +=over + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=back + +=item * L + +=over + +=item * L + +=item * L + +=item * L + +=back + +=back + +=begin html + +


+ +=end html + +=recordtype mbbiDirect + +=cut + recordtype(mbbiDirect) { - include "dbCommon.dbd" + +=head2 Parameter Fields + +The fields fall into the following categories: + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=cut + +=head3 Scan Parameters + +The mbbiDirect record has the standard fields for specifying under what +circumstances the record will be processed. These fields are listed in L. In addition, L explains how these fields are +used. Note that I/O event scanning is only supported for those card types +that interrupt. + +=cut + +=head3 Read and Convert Parameters + +The device support routines obtain the record's input from the device or link +specified in the INP field. For records that obtain their input from devices, +the INP field must contain the address of the I/O card, and the DTYP field +must specify the proper device support module. Be aware that the address format +differs according to the I/O bus used. See L
for +information on the format of hardware addresses. + +Two soft device support modules can be specified in DTYP C and +C<<< Raw Soft Channel >>>. + +C<<< Raw Soft Channel >>> reads the value into RVAL, +upon which the normal conversion process is undergone. C<<< Soft Channel >>> +reads any unsigned integer directly into VAL. For a soft mbbiDirect record, the +INP field can be a constant, a database, or a channel access link. If INP is a +constant, then the VAL is initialized to the INP value but can be changed at +run-time via dbPutField or dbPutLink. See L
for +information on how to database links. + +For records that don't use C<<< Soft Channel >>> device support, RVAL is used to +determine VAL as follows: + +=over + +=item 1. RVAL is assigned to a temporary variable I = RVAL + +=item 2. I is shifted right SHFT number of bits. + +=item 3. VAL is set equal to I. + +=back + +Each of the fields, B0-BF, represents one bit of the word. + +=fields VAL, INP, RVAL, SHFT, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, BA, BB, BC, BD, BE, BF + +=cut + +=head3 Operator Display Parameters + +These parameters are used to present meaningful data to the operator. + +See L for more on the record name (NAME) and +description (DESC) fields. + +=fields NAME, DESC + +=cut + + include "dbCommon.dbd" field(VAL,DBF_USHORT) { prompt("Current Value") promptgroup("40 - Input") @@ -49,6 +199,27 @@ recordtype(mbbiDirect) { promptgroup("40 - Input") interest(1) } + +=head3 Run-time and Simulation Mode Parameters + +These parameters are used by the run-time code for processing the mbbi direct +record. They are not configurable prior to run-time. + +MASK is used by device support routine to read hardware register. Record support +sets low order NOBT bits in MASK. Device support can shift this value. + +MLST holds the value when the last monitor for value change was triggered. + +=fields NOBT, ORAW, MASK, MLST + +The following fields are used to operate the mbbiDirect record in the simulation +mode. See L for more information on these +fields. + +=fields SIOL, SVAL, SIML, SIMM, SIMS + +=cut + field(SIOL,DBF_INLINK) { prompt("Sim Input Specifctn") promptgroup("90 - Simulate") @@ -67,6 +238,20 @@ recordtype(mbbiDirect) { interest(1) menu(menuSimm) } + +=head3 Alarm Parameters + +The possible alarm conditions for multi-bit binary input direct records are the +SCAN and READ alarms. These alarms are not configurable by the user since they +are always of MAJOR severity. See L for a complete +explanation of Scan and Read alarms. No fields exist for the mbbi direct record +to have state alarms. + +L lists other fields related to a alarms that are common to all +record types. + +=cut + field(SIMS,DBF_MENU) { prompt("Sim mode Alarm Svrty") promptgroup("90 - Simulate") @@ -153,4 +338,223 @@ recordtype(mbbiDirect) { pp(TRUE) interest(1) } + +=begin html + +


+ +=end html + +=head2 Record Support + +=head3 Record Support Routines + +=head4 init_record + +This routine initializes SIMM with the value of SIML if SIML type is CONSTANT +link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise +initialized if SIOL is CONSTANT or PV_LINK. + +This routine next checks to see that device support is available and a device +support read routine is defined. If either does not exist, an error message is +issued and processing is terminated. + +Clears MASK and then sets the NOBT low order bits. + +If device support includes C, it is called. + +refresh_bits is then called to refresh all the bit fields based on a hardware +value. + +=head4 process + +See next section. + +=head3 Record Processing + +Routine process implements the following algorithm: + +=over + +=item 1. + +Check to see that the appropriate device support module exists. If it doesn't, +an error message is issued and processing is terminated with the PACT field +still set to TRUE. This ensures that processes will no longer be called for this +record. Thus error storms will not occur. + +=item 2. + +readValue is called. See L for information. + +=item 3. + +If PACT has been changed to TRUE, the device support read routine has started +but has not completed reading a new input value. In this case, the processing +routine merely returns, leaving PACT TRUE. + +=item 4. + +Convert. + +=over + +=item * status = read_mbbiDirect + +=item * PACT = TRUE + +=item * C is called. + +=item * If status is 0, then determine VAL + +=over + +=item * Set rval = RVAL + +=item * Shift rval right SHFT bits + +=item * Set VAL = RVAL + +=back + +=item * If status is 1, return 0 + +=item * If status is 2, set status = 0 + +=back + +=item 5. + +Check to see if monitors should be invoked. + +=over + +=item * Alarm monitors are invoked if the alarm status or severity has changed. + +=item * Archive and value change monitors are invoked if MLST is not equal to VAL. + +=item * Monitors for RVAL are checked whenever other monitors are invoked. + +=item * NSEV and NSTA are reset to 0. + +=back + +=item 6. + +Scan forward link if necessary, set PACT FALSE, and return. + +=back + +=begin html + +


+ +=end html + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each input record must have an associated set of device support routines. + +The primary responsibility of the device support routines is to obtain a new raw +input value whenever read_mbbiDirect is called. The device support routines are +primarily interested in the following fields: + +=fields PACT, DPVT, UDF, NSEV, NSTA, NOBT, VAL, INP, RVAL, MASK, SHFT + +=head3 Device Support Routines + +Device support consists of the following routines: + +=head4 long report(int level) + +This optional routine is called by the IOC command C and is passed the +report level that was requested by the user. +It should print a report on the state of the device support to stdout. +The C parameter may be used to output increasingly more detailed +information at higher levels, or to select different types of information with +different levels. +Level zero should print no more than a small summary. + +=head4 long init(int after) + +This optional routine is called twice at IOC initialization time. +The first call happens before any of the C calls are made, with +the integer parameter C set to 0. +The second call happens after all of the C calls have been made, +with C set to 1. + +=head4 init_record + + init_record(precord) + +This routine is optional. If provided, it is called by the record support +C routine. If it uses MASK, it should shift it as necessary and +also give SHFT a value. + +=head4 get_ioint_info + + get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt) + +This routine is called by the ioEventScan system each time the record is added +or deleted from an IEO event scan list. cmd has the value (0,1) if the +record is being (added to, deleted from) an IEO event list. It must be +provided for any device type that can use the ioEvent scanner. + +=head4 read_mbbiDirect + + read_mbbiDirect(precord) + +This routine must provide a new input value. It returns the following values: + +=over + +=item * + +0: Success. A new raw value is placed in RVAL. The record support module +determines VAL from RVAL and SHFT. + +=item * + +2: Success, but don't modify VAL. + +=item * + +Other: Error. + +=back + +=head3 Device Support For Soft Records + +Two soft device support modules, C<<< Soft Channel >>> and C<<< Raw Soft Channel +>>>, are provided for multi-bit binary input direct records not related to +actual hardware devices. The INP link type must be either CONSTANT, DB_LINK, or +CA_LINK. + +=head4 Soft Channel + +For this module, read_mbbiDirect always returns a value of 2, which means that +no conversion is performed. + +If the INP link type is constant, then the constant value is stored into VAL by +C, and UDF is set to FALSE. VAL can be changed via dbPut +requests. If the INP link type is PV_LINK, then dbCaAddInlink is called by +C. + +read_mbbiDirect calls recGblGetLinkValue to read the current value of VAL. + +See L for a further explanation. + +If the return status of recGblGetLinkValue is zero, then read_mbbi sets UDF to +FALSE. The status of recGblGetLinkValue is returned. + +=head4 Raw Soft Channel + +This module is like the previous except that values are read into RVAL, VAL is +computed from RVAL, and read_mbbiDirect returns a value of 0. Thus the record +processing routine will determine VAL in the normal way. + +=cut + } From c7db681e25bfc71a7407b1960ae2ad0d55e6b34b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 14 Oct 2019 15:19:41 -0400 Subject: [PATCH 39/47] rename .dbd to .dpd.pod for mbbo --- src/std/rec/{mbboRecord.dbd => mbboRecord.dbd.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/std/rec/{mbboRecord.dbd => mbboRecord.dbd.pod} (100%) diff --git a/src/std/rec/mbboRecord.dbd b/src/std/rec/mbboRecord.dbd.pod similarity index 100% rename from src/std/rec/mbboRecord.dbd rename to src/std/rec/mbboRecord.dbd.pod From 5b5fd8004c517fa4221d8492f23209a31a5776e9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 19 Oct 2019 23:17:18 -0500 Subject: [PATCH 40/47] Add converted mbbo POD --- src/std/rec/mbboRecord.dbd.pod | 445 ++++++++++++++++++++++++++++++++- 1 file changed, 444 insertions(+), 1 deletion(-) diff --git a/src/std/rec/mbboRecord.dbd.pod b/src/std/rec/mbboRecord.dbd.pod index f841ba018..a71829906 100644 --- a/src/std/rec/mbboRecord.dbd.pod +++ b/src/std/rec/mbboRecord.dbd.pod @@ -6,8 +6,173 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=title Multi-Bit Binary Output Record (mbbo) + +The normal use for the mbbo record type is to send a binary value (representing +one of up to 16 states) to a Digital Output module. It is used for any device +that uses more than one contiguous bit to control it. The mbbo record can also +be used to write discrete values to other records via database or channel access +links. + +=recordtype mbbo + +=cut + recordtype(mbbo) { - include "dbCommon.dbd" + +=head2 Parameter Fields + +The record-specific fields are described below, grouped by functionality. + +=head3 Scan Parameters + +The mbbo record has the standard fields for specifying under what circumstances +it will be processed. These fields are listed in L. In addition, +L explains how these fields are used. Note that I/O +event scanning is only supported for those card types that interrupt. + +=head3 Desired Output Parameters + +The multi-bit binary output record, like all output records, must specify where +its output originates. The output mode select (OMSL) field determines whether +the output originates from another record or from database access (i.e., the +operator). When set to C<<< closed_loop >>>, the desired output is retrieved +from the link specified in the desired output (DOL) field--which can specify +either a database or channel access link--and placed into the VAL field. When +set to C<<< supervisory >>>, the DOL field is ignored and the current value of +VAL is simply written. VAL can be changed via dpPuts at run-time when OMSL is +C<<< supervisory >>>. The DOL field can also be a constant, in which case the +VAL field is initialized to the constant value. If DOL is a constant, OMSL +cannot be set to C<<< closed_loop >>>. + +The VAL field itself usually consists of an index that specifies one of the +states. The actual output written is the value of RVAL, which is converted from +VAL following the routine explained in the next section. However, records that +use the C<<< Soft Channel >>> device support module write the VAL field's value +without any conversion. + +=fields OMSL, DOL, VAL + +=head3 Convert and Write Parameters + +The device support routines write the desired output to the location specified +in the OUT field. If the record uses soft device support, OUT can contain a +constant, a database link, or a channel access link; however, if OUT is a +constant, no value will be written. + +For records that write their values to hardware devices, the OUT output link +must specify the address of the I/O card, and the DTYP field must specify +the corresponding device support module. Be aware that the address format +differs according to the I/O bus used. See L
for +information on the format of hardware addresses. + +For mbbo records that write to hardware, the value written to the output +location is the value contained in RVAL, which is converted from VAL, VAL +containing an index of one of the 16 states (0-15). RVAL is then set to the +corresponding state value, the value in one of the fields ZRVL through FFVL. +Then this value is shifted left according to the number in the SHFT field so +that the value is in the correct position for the bits being used (the SHFT +value is set by device support and is not configurable by the user). + +The state value fields ZRVL through FFVL must be configured by the user before +run-time. When the state values are not defined, the states defined (SDEF) field +is set to FALSE at initialization time by the record routines. When SDEF is +FALSE, then the record processing routine does not try to find a match, RVAL is +set equal to VAL, the bits are shifted using the number in SHFT, and the value +is written thus. + +If the OUT output link specifies a database link, channel access link, or +constant, then the DTYP field must specify either one of the two soft device +support modules-- C<<< Soft Channel >>> or C<<< Raw Soft Channel >>>. C<<< Soft +>>> C<<< Channel >>> writes the value of VAL to the output link, without any +conversion, while C<<< Raw Soft Channel >>> writes the value from RVAL after it +has undergone the above conversion. See L
for information +on specifying links. + +Note also that when a string is retrieved as the desired output, a record +support routine is provided (C<<< put_enum_str() >>>) that will check to see +if the string matches one of the strings in the ZRST through FFST fields. If a +match is found, RVAL is set equal to the corresponding state value of that +string. + +=fields OUT, DTYP, RVAL, SHFT, SDEF, ZRVL, ONVL, TWVL, THVL, FRVL, FVVL, SXVL, SVVL, EIVL, NIVL, TEVL, ELVL, TVVL, TTVL, FTVL, FFVL + +=head3 Operator Display Parameters + +These parameters are used to present meaningful data to the operator. These +fields are used to display the value and other parameters of the mbbo record +either textually or graphically. The ZRST-FFST fields contain strings describing +each of the corresponding states. The C<<< get_enum_str() >>> and +C<<< get_enum_strs() >>> record routines retrieve these strings for the +operator. C<<< get_enum_str() >>> gets the string corresponding to the value in +VAL, and C<<< get_enum_strs() >>> retrieves all the strings. + +See L for more on the record name (NAME) and +description (DESC) fields. + +=fields NAME, DESC, ZRST, ONST, TWST, THST, FRST, FVST, SXST, SVST, EIST, NIST, TEST, ELST, TVST, TTST, FTST, FFST + +=head3 Alarm Parameters + +The possible alarm conditions for multi-bit binary outputs are the SCAN, READ, +INVALID, and state alarms. The SCAN and READ alarms are called by the support +modules and are not configurable by the user, as their severity is always MAJOR. + +The IVOA field specifies an action to take from a number of possible choices +when the INVALID alarm is triggered. The IVOV field contains a value to be +written once the INVALID alarm has been triggered if C<<< Set output to IVOV >>> +has been chosen in the IVOA field. The severity of the INVALID alarm is not +configurable by the user. + +The state alarms are configured in the below severity fields. These fields have +the usual possible values for severity fields: NO_ALARM, MINOR, and MAJOR. + +The unknown state severity field (UNSV), if set to MINOR or MAJOR, triggers an +alarm when the record support routine cannot find a matching value in the state +value fields for VAL or when VAL is out of range. + +The change of state severity field (COSV) triggers an alarm when the record's +state changes, if set to MAJOR or MINOR. + +The state severity (ZRSV-FFSV) fields, when set to MAJOR or MINOR, trigger an +alarm when VAL equals the corresponding field. + +See L for a complete explanation of discrete alarms and +these fields. See L for an explanation of the IVOA +and IVOV fields. L lists other fields related to a alarms that are +common to all record types. + +=fields UNSV, COSV, IVOA, IVOV, ZRSV, ONSV, TWSV, THSV, FRSV, FVSV, SXSV, SVSV, EISV, NISV, TESV, ELSV, TVSV, TTSV, FTSV, FFSV + +=head3 Run-Time and Simulation Mode Parameters + +These parameters are used by the run-time code for processing the multi-bit +binary output. + +MASK is used by device support routine to read the hardware register. Record +support sets low order of MASK the number of bits specified in NOBT. Device +support can shift this value. + +The LALM field implements the change of state alarm severity by holding the +value of VAL when the previous change of state alarm was issued. + +MLST holds the value when the last monitor for value change was triggered. + +SDEF is used by record support to save time if no states are defined; it is used +for converting VAL to RVAL. + +=fields NOBT, ORAW, MASK, LALM, MLST, SDEF + +The following fields are used to operate the mbbo record in the simulation mode. +See L for more information on the simulation +mode fields. + +=fields SIOL, SIML, SIMM, SIMS + +=cut + + include "dbCommon.dbd" field(VAL,DBF_ENUM) { prompt("Desired Value") promptgroup("50 - Output") @@ -497,3 +662,281 @@ recordtype(mbbo) { interest(2) } } + +=head2 Record Support + +=head3 Record Support Routines + +=head4 init_record + +This routine initializes SIMM if SIML is a constant or creates a channel access +link if SIML is PV_LINK. If SIOL is PV_LINK a channel access link is created. + +This routine next checks to see that device support is available. The routine +next checks to see if the device support write routine is defined. If either +device support or the device support write routine does not exist, an error +message is issued and processing is terminated. + +If DOL is a constant, then VAL is initialized to its value and UDF is set to +FALSE. + +MASK is cleared and then the NOBT low order bits are set. + +If device support includes C, it is called. + +init_common is then called to determine if any states are defined. If states are +defined, SDEF is set to TRUE. + +If device support returns success, VAL is then set from RVAL and UDF is set to +FALSE. + +=head4 process + +See next section. + +=head4 special + +Computes SDEF when any of the fields ZRVL,...FFVL change value. + +=head4 get_value + +Fills in the values of struct valueDes so that they refer to VAL. + +=head4 get_enum_str + +Retrieves ASCII string corresponding to VAL. + +=head4 get_enum_strs + +Retrieves ASCII strings for ZRST,...FFST. + +=head4 put_enum_str + +Checks if string matches ZRST,...FFST and if it does, sets VAL. + +=head3 Record Processing + +Routine process implements the following algorithm: + +=over + +=item 1. + +Check to see that the appropriate device support module exists. If it doesn't, +an error message is issued and processing is terminated with the PACT field +still set to TRUE. This ensures that processes will not longer be called for +this record. Thus error storms will not occur. + +=item 2. + +If PACT is FALSE + +=over + +=item * + +If DOL is DB_LINK and OMSL is CLOSED_LOOP + +=over + +=item * + +Get value from DOL + +=item * + +Set UDF to FALSE + +=item * + +Check for link alarm + +=back + +=item * + +If any state values are defined + +=over + +=item * + +If VAL E 15, then raise alarm and go to 4 + +=item * + +Else using VAL as index set RVAL = one of ZRVL,...FFVL + +=back + +=item * + +Else set RVAL = VAL + +=item * + +Shift RVAL left SHFT bits + +=back + +=item 3. + +Convert + +=over + +=item * + +If PACT is FALSE, compute RVAL + +=over + +=item * + +If VAL is 0,...,15, set RVAL from ZRVL,...,FFVL + +=item * + +If VAL out of range, set RVAL = undefined + +=back + +=item * + +Status = write_mbbo + +=back + +=item 4. + +Check alarms. This routine checks to see if the new VAL causes the alarm status +and severity to change. If so, NSEV, NSTA and LALM are set. + +=item 5. + +Check severity and write the new value. See L and L for more information. + +=item 6. + +If PACT has been changed to TRUE, the device support write output routine has +started but has not completed writing the new value. In this case, the +processing routine merely returns, leaving PACT TRUE. + +=item 7. + +Check to see if monitors should be invoked. + +=over + +=item * + +Alarm monitors are invoked if the alarm status or severity has changed. + +=item * + +Archive and value change monitors are invoked if MLST is not equal to VAL. + +=item * + +Monitors for RVAL and RBV are checked whenever other monitors are invoked. + +=item * + +NSEV and NSTA are reset to 0. + +=back + +=item 8. + +Scan forward link if necessary, set PACT FALSE, and return. + +=back + + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each mbbo record must have an associated set of device support routines. The +primary responsibility of the device support routines is to obtain a new raw +mbbo value whenever write_mbbo is called. The device support routines are +primarily interested in the following fields: + +=fields PACT, DPVT, NSEV, NSTA, NOBT, OUT, RVAL, RBV, MASK, SHFT + +=head3 Device Support Routines + +Device support consists of the following routines: + +=head4 long report(int level) + +This optional routine is called by the IOC command C and is passed the +report level that was requested by the user. +It should print a report on the state of the device support to stdout. +The C parameter may be used to output increasingly more detailed +information at higher levels, or to select different types of information with +different levels. +Level zero should print no more than a small summary. + +=head4 long init(int after) + +This optional routine is called twice at IOC initialization time. +The first call happens before any of the C calls are made, with +the integer parameter C set to 0. +The second call happens after all of the C calls have been made, +with C set to 1. + +=head4 init_record + + init_record(precord) + +This routine is optional. If provided, it is called by the record support's +C routine. If MASK is used, it should be shifted if necessary and SHFT +given a value. + +=head4 get_ioint_info + + get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt) + +This routine is called by the ioEventScan system each time the record is added +or deleted from an I/O event scan list. cmd has the value (0,1) if the +record is being (added to, deleted from) an I/O event list. It must be +provided for any device type that can use the ioEvent scanner. + +=head4 write_mbbo + + write_mbbo(precord) + +This routine must output a new value. It returns the following values: + +=over + +=item * + +0: Success. + +=item * + +Other: Error. + +=back + +=head3 Device Support For Soft Records + +=head4 Soft Channel + +The C<<< Soft Channel >>> module writes the current value of VAL. + +If the OUT link type is PV_LINK, then dbCaAddInlink is called by +C. + +write_mbbo calls recGblPutLinkValue to write the current value of VAL. See +L for more information. + +=head4 Raw Soft Channel + +This module writes RVAL to the location specified in the output link. It returns +a 0. + +=cut From 00334c981c60515dad5d1ea0025314ed01897114 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 20 Oct 2019 00:20:42 -0500 Subject: [PATCH 41/47] Perl-generated HTML is UTF-8; mark it so --- src/tools/dbdToHtml.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/dbdToHtml.pl b/src/tools/dbdToHtml.pl index 636292a52..adf2f004a 100644 --- a/src/tools/dbdToHtml.pl +++ b/src/tools/dbdToHtml.pl @@ -130,10 +130,11 @@ my $idify; if ($::XHTML) { $podHtml = Pod::Simple::XHTML->new(); $podHtml->html_doctype(<< '__END_DOCTYPE'); - + __END_DOCTYPE + $podHtml->html_charset('UTF-8'); $podHtml->html_header_tags($podHtml->html_header_tags . "\n"); @@ -142,6 +143,8 @@ __END_DOCTYPE return $podHtml->idify($title, 1); } } else { # Fall back to HTML + $Pod::Simple::HTML::Content_decl = + q{}; $podHtml = Pod::Simple::HTML->new(); $podHtml->html_css('style.css'); From 178d5779a201a3cd28a6ee3dadc98e604bd07313 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 20 Oct 2019 00:41:50 -0500 Subject: [PATCH 42/47] Cleanup of POD documentation, unifying some things Incomplete, still lots to do in these files. --- src/std/rec/aiRecord.dbd.pod | 16 ++--- src/std/rec/biRecord.dbd.pod | 34 +++++----- src/std/rec/compressRecord.dbd.pod | 97 +++++----------------------- src/std/rec/longinRecord.dbd.pod | 80 ++--------------------- src/std/rec/longoutRecord.dbd.pod | 64 ++---------------- src/std/rec/mbbiDirectRecord.dbd.pod | 84 +----------------------- src/std/rec/mbbiRecord.dbd.pod | 96 ++------------------------- src/std/rec/mbboDirectRecord.dbd.pod | 70 +------------------- src/std/rec/permissiveRecord.dbd.pod | 46 ++----------- src/std/rec/selRecord.dbd.pod | 63 ++---------------- src/std/rec/seqRecord.dbd.pod | 60 +---------------- src/std/rec/stateRecord.dbd.pod | 42 ++---------- src/std/rec/stringinRecord.dbd.pod | 68 ++----------------- src/std/rec/stringoutRecord.dbd.pod | 62 ++---------------- src/std/rec/subArrayRecord.dbd.pod | 70 ++------------------ src/std/rec/subRecord.dbd.pod | 73 ++++----------------- src/std/rec/waveformRecord.dbd.pod | 70 ++------------------ 17 files changed, 111 insertions(+), 984 deletions(-) diff --git a/src/std/rec/aiRecord.dbd.pod b/src/std/rec/aiRecord.dbd.pod index 2973ec831..0673447ff 100644 --- a/src/std/rec/aiRecord.dbd.pod +++ b/src/std/rec/aiRecord.dbd.pod @@ -4,7 +4,7 @@ # 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. +# in file LICENSE that is included with this distribution. #************************************************************************* =title Analog Input Record (ai) @@ -214,7 +214,7 @@ monitoring functionality. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_DOUBLE) { prompt("Current EGU Value") promptgroup("40 - Input") @@ -520,7 +520,7 @@ The individual routines are described below. =head3 Device Support Routines -=head4 long report(int level) + long report(int level) This optional routine is called by the IOC command C and is passed the report level that was requested by the user. @@ -530,7 +530,7 @@ information at higher levels, or to select different types of information with different levels. Level zero should print no more than a small summary. -=head4 long init(int after) + long init(int after) This optional routine is called twice at IOC initialization time. The first call happens before any of the C calls are made, with @@ -538,7 +538,7 @@ the integer parameter C set to 0. The second call happens after all of the C calls have been made, with C set to 1. -=head4 long init_record(aiRecord *prec) + long init_record(aiRecord *prec) This optional routine is called by the record initialization code for each ai record instance that has its DTYP field set to use this device support. @@ -555,7 +555,7 @@ C, but it is not necessary to check that condition first. This same calculation takes place in the C routine, so the implementation can usually just call that routine to perform the task. -=head4 long get_ioint_info(int cmd, aiRecord *prec, IOSCANPVT *piosl) + long get_ioint_info(int cmd, aiRecord *prec, IOSCANPVT *piosl) This optional routine is called whenever the record's SCAN field is being changed to or from the value C to find out which I/O Interrupt Scan @@ -584,7 +584,7 @@ thread. The C routine is safe to call from an interrupt service routine on embedded architectures (vxWorks and RTEMS). -=head4 long read_ai(aiRecord *prec) + long read_ai(aiRecord *prec) This essential routine is called when the record wants a new value from the addressed device. @@ -595,7 +595,7 @@ It is responsible for performing (or at least initiating) a read operation, and ... return value ... -=head4 long special_linconv(aiRecord *prec, int after) + long special_linconv(aiRecord *prec, int after) This optional routine should be provided if the record type's unit conversion features are used by the device support's C routine returning a diff --git a/src/std/rec/biRecord.dbd.pod b/src/std/rec/biRecord.dbd.pod index 2d4cc0c51..2ff7b1a93 100644 --- a/src/std/rec/biRecord.dbd.pod +++ b/src/std/rec/biRecord.dbd.pod @@ -162,7 +162,7 @@ these fields. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(INP,DBF_INLINK) { prompt("Input Specification") promptgroup("40 - Input") @@ -264,7 +264,7 @@ these fields. =head3 Record Support Routines -=head2 C + long init_record(struct dbCommon *precord, int pass); This routine initializes SIMM with the value of SIML if SIML type is a CONSTANT link or creates a channel access link if SIML type is PV_LINK. @@ -276,19 +276,19 @@ processing is terminated. If device support includes C, it is called. -=head2 C + long process(struct dbCommon *precord); -See next section. +See L below. -=head2 C + long get_enum_str(const struct dbAddr *paddr, char *pbuffer); Retrieves ASCII string corresponding to VAL. -=head2 C + long get_enum_strs(const struct dbAddr *paddr, struct dbr_enumStrs *p); Retrieves ASCII strings for ZNAM and ONAM. -=head2 C + long put_enum_str(const struct dbAddr *paddr, const char *pbuffer); Check if string matches ZNAM or ONAM, and if it does, sets VAL. @@ -296,7 +296,7 @@ Check if string matches ZNAM or ONAM, and if it does, sets VAL. Routine process implements the following algorithm: -=over 1 +=over =item 1. Check to see that the appropriate device support module exists. If it @@ -317,7 +317,7 @@ Convert. =back -=over 1 +=over =item * status = read_bi @@ -336,7 +336,7 @@ if status is 2, set status = 0 =back -=over 1 +=over =item 5. Check alarms: This routine checks to see if the new VAL causes the alarm @@ -348,7 +348,7 @@ Check if monitors should be invoked: =back -=over 1 +=over =item * Alarm monitors are invoked if the alarm status or severity has changed. @@ -364,7 +364,7 @@ NSEV and NSTA are reset to 0. =back -=over 1 +=over =item 7. Scan forward link if necessary, set PACT FALSE, and return. @@ -386,7 +386,7 @@ support routines are primarily interested in the following fields: Device support consists of the following routines: -=head4 long report(int level) + long report(int level); This optional routine is called by the IOC command C and is passed the report level that was requested by the user. @@ -396,7 +396,7 @@ information at higher levels, or to select different types of information with different levels. Level zero should print no more than a small summary. -=head4 long init(int after) + long init(int after); This optional routine is called twice at IOC initialization time. The first call happens before any of the C calls are made, with @@ -404,19 +404,19 @@ the integer parameter C set to 0. The second call happens after all of the C calls have been made, with C set to 1. -=head2 C + long init_record(struct dbCommon *precord); This routine is optional. If provided, it is called by the record support C routine. -=head2 C + long get_ioint_info(int cmd, struct dbCommon *precord, IOSCANPVT *ppvt); This routine is called by the ioEventScan system each time the record is added or deleted from an I/O event scan list. C has the value (0,1) if the record is being (added to, deleted from) and I/O event list. It must be provided for any device type that can use the ioEvent scanner. -=head2 C + long read_bi(struct dbCommon *precord); This routine must provide a new input value. It returns the following values: diff --git a/src/std/rec/compressRecord.dbd.pod b/src/std/rec/compressRecord.dbd.pod index 209e8d1f8..76a82abfe 100644 --- a/src/std/rec/compressRecord.dbd.pod +++ b/src/std/rec/compressRecord.dbd.pod @@ -4,7 +4,7 @@ # 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. +# in file LICENSE that is included with this distribution. #************************************************************************* =title Compression Record (compress) @@ -35,46 +35,10 @@ menu(compressALG) { } recordtype(compress) { -=head2 Contents - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=back - -=back - -=begin html - -
-
-
- -=end html - =head2 Parameter Fields +The record-specific fields are described below, grouped by functionality. + =head3 Scanning Parameters The compression record has the standard fields for specifying under what @@ -232,80 +196,52 @@ SPTR points to an array that is used for array averages. WPTR is used by the dbGetlinks routines. -=begin html - -
-
-
- -=end html - =head2 Record Support -=head3 Record Support Routines (compressRecord.c) +=head3 Record Support Routines -=head4 init_record - - long (*init_record)(struct dbCommon *precord, int pass) + long init_record(struct dbCommon *precord, int pass) Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record. -=head4 process + long process(struct dbCommon *precord) - long (*process)(struct dbCommon *precord) +See L below. -See L - -=head4 special - - long (*special)(struct dbAddr *paddr, int after) + long special(struct dbAddr *paddr, int after) This routine is called when RSET, ALG, or N are set. It performs a reset. -=head4 cvt_dbaddr - - long (*cvt_dbaddr)(struct dbAddr *paddr) + long cvt_dbaddr(struct dbAddr *paddr) This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result. -=head4 get_array_info - - long (*get_array_info)(struct dbAddr *paddr, long *no_elements, long *offset) + long get_array_info(struct dbAddr *paddr, long *no_elements, long *offset) Obtains values from the circular buffer referenced by VAL. -=head4 put_array_info - - long (*put_array_info)(struct dbAddr *paddr, long nNew); + long put_array_info(struct dbAddr *paddr, long nNew); Writes values into the circular buffer referenced by VAL. -=head4 get_units - - long (*get_units)(struct dbAddr *paddr, char *units); + long get_units(struct dbAddr *paddr, char *units); Retrieves EGU. -=head4 get_precision - - long (*get_precision)(const struct dbAddr *paddr, long *precision); + long get_precision(const struct dbAddr *paddr, long *precision); Retrieves PREC. -=head4 get_graphic_double - - long (*get_graphic_double)(struct dbAddr *paddr, struct dbr_grDouble *p); + long get_graphic_double(struct dbAddr *paddr, struct dbr_grDouble *p); Sets the upper display and lower display limits for a field. If the field is VAL, the limits are set to HOPR and LOPR, else if the field has upper and lower limits defined they will be used, else the upper and lower maximum values for the field type will be used. -=head4 get_control_double - - long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p); + long get_control_double(struct dbAddr *paddr, struct dbr_ctrlDouble *p); Sets the upper control and the lower control limits for a field. If the field is VAL, the limits are set to HOPR and LOPR, else if the field has upper and lower @@ -391,7 +327,7 @@ Scan forward link if necessary, set PACT FALSE, and return. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_NOACCESS) { prompt("Value") asl(ASL0) @@ -515,4 +451,3 @@ Scan forward link if necessary, set PACT FALSE, and return. interest(3) } } - diff --git a/src/std/rec/longinRecord.dbd.pod b/src/std/rec/longinRecord.dbd.pod index cbc5f5b54..4981a991f 100644 --- a/src/std/rec/longinRecord.dbd.pod +++ b/src/std/rec/longinRecord.dbd.pod @@ -7,7 +7,7 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=head1 Long Input Record (longin) +=title Long Input Record (longin) The normal use for the long input record or "longin" record is to retrieve a long integer value of up to 32 bits. Device support routines are provided to @@ -15,56 +15,6 @@ support direct interfaces to hardware. In addition, the C<<< Soft Channel >>> device module is provided to obtain input via database or channel access links or via dbPutField or dbPutLink requests. -=head1 Contents - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=back - -=back - -=begin html - -


- -=end html - =recordtype longin =cut @@ -73,21 +23,7 @@ recordtype(longin) { =head2 Parameter Fields -The fields in this record fall into the following categories: - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back +The record-specific fields are described below, grouped by functionality. =head3 Scan Parameters @@ -174,17 +110,11 @@ See L for more information on these fields. =fields SIOL, SVAL, SIML, SIMM, SIMS -=begin html - -


- -=end html - =head2 Record Support -=head3 Record Support Routines +=head3 Record Support Routines -=head4 init_record +=head4 init_record This routine initializes SIMM with the value of SIML if SIML type is CONSTANT link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise @@ -374,7 +304,7 @@ sets UDF to FALSE. read_longin returns the status of C. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_LONG) { prompt("Current value") promptgroup("40 - Input") diff --git a/src/std/rec/longoutRecord.dbd.pod b/src/std/rec/longoutRecord.dbd.pod index 5d8dd9320..d627b76ea 100644 --- a/src/std/rec/longoutRecord.dbd.pod +++ b/src/std/rec/longoutRecord.dbd.pod @@ -7,69 +7,15 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=head1 B +=title Long Output Record (longout) The normal use for the long output or "longout" record type is to store long -integer values of up to 32 bits and write them to hardware devices. The C<<< -Soft Channel >>> device support routine can also be used to write values to +integer values of up to 32 bits and write them to hardware devices. The C<<< +Soft Channel >>> device support layer can also be used to write values to other records via database or channel access links. The OUT field determines how the record is used. The record supports alarm limits and graphics and control limits. -=head1 L - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=back - -=back - -=begin html - -


- -=end html - =recordtype longout =cut @@ -149,7 +95,7 @@ and database links. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_LONG) { prompt("Desired Output") promptgroup("50 - Output") @@ -243,7 +189,7 @@ HYST field contains the alarm deadband around each limit alarm. See the See L for a complete explanation of alarms and these fields. For an explanation of the IVOA and IVOV fields, see L. L lists other fields related to a alarms that are common -to all record types. +to all record types. =fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, IVOA, IVOV diff --git a/src/std/rec/mbbiDirectRecord.dbd.pod b/src/std/rec/mbbiDirectRecord.dbd.pod index 724cbfb55..082f609cf 100644 --- a/src/std/rec/mbbiDirectRecord.dbd.pod +++ b/src/std/rec/mbbiDirectRecord.dbd.pod @@ -7,7 +7,7 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=head1 B +=title Multi-Bit Binary Input Direct Record (mbbiDirect) The mbbiDirect record retrieves a sixteen-bit hardware value and converts it to an array of sixteen unsigned characters, each representing a bit of the word. @@ -17,60 +17,6 @@ This record's operation is similar to that of the multi-bit binary input record, and it has many fields in common with it. This record also has two available soft device support modules: C and C. -=head1 L - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=back - -=back - -=begin html - -


- -=end html - =recordtype mbbiDirect =cut @@ -79,23 +25,7 @@ recordtype(mbbiDirect) { =head2 Parameter Fields -The fields fall into the following categories: - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=cut +The record-specific fields are described below, grouped by functionality. =head3 Scan Parameters @@ -105,8 +35,6 @@ Fields>. In addition, L explains how these fields are used. Note that I/O event scanning is only supported for those card types that interrupt. -=cut - =head3 Read and Convert Parameters The device support routines obtain the record's input from the device or link @@ -144,8 +72,6 @@ Each of the fields, B0-BF, represents one bit of the word. =fields VAL, INP, RVAL, SHFT, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, BA, BB, BC, BD, BE, BF -=cut - =head3 Operator Display Parameters These parameters are used to present meaningful data to the operator. @@ -339,12 +265,6 @@ record types. interest(1) } -=begin html - -


- -=end html - =head2 Record Support =head3 Record Support Routines diff --git a/src/std/rec/mbbiRecord.dbd.pod b/src/std/rec/mbbiRecord.dbd.pod index 2bbda6686..5fa977714 100644 --- a/src/std/rec/mbbiRecord.dbd.pod +++ b/src/std/rec/mbbiRecord.dbd.pod @@ -7,7 +7,7 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=head1 B +=title Multi-Bit Binary Input Record (mbbi) The normal use for the multi-bit binary input record is to read contiguous, multiple bit inputs from hardware. The binary value represents a state from a @@ -25,58 +25,6 @@ are provided: C<<< Soft Channel >>> allows VAL to be an arbitrary unsigned short integer. C<<< Raw Soft Channel >>> reads the value into RVAL just like normal device support modules. -=head1 L - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=back - -=back - -=begin html - -


- -=end html - =recordtype mbbi =cut @@ -85,23 +33,7 @@ recordtype(mbbi) { =head2 Parameter Fields -The multi-bit binary input fields fall into the following categories: - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back +The record-specific fields are described below, grouped by functionality. =head3 Scan Parameters @@ -121,7 +53,7 @@ differs according to the I/O bus used. See L
for information on the format of hardware addresses. Two soft device support modules can be specified in DTYP C and -C<<< Raw Soft Channel >>>. +C<<< Raw Soft Channel >>>. C<<< Raw Soft Channel >>> reads the value into RVAL, upon which the normal conversion process is undergone. C<<< Soft Channel >>> @@ -165,7 +97,7 @@ Each of the fields, ZRVL-FFVL, represents one of the possible sixteen states Alternatively, the input value can be read as a string, in which case, a match is sought with one of the strings specified in the ZRST-FFST fields. Then RVAL is set equal to the corresponding value for that string, and the conversion -process occurs. +process occurs. =fields VAL, INP, MASK, NOBT, RVAL, SHFT, ZRVL, ONVL, TWVL, THVL, FRVL, FVVL, SXVL, SVVL, EIVL, NIVL, TEVL, ELVL, TVVL, TTVL, FTVL, FFVL @@ -186,7 +118,7 @@ description (DESC) fields. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_ENUM) { prompt("Current Value") promptgroup("40 - Input") @@ -478,7 +410,7 @@ state occurs, if set to MAJOR or MINOR. The other fields, when set to MAJOR or MINOR, trigger an alarm when VAL equals the corresponding state. See the See L for a complete explanation of discrete alarms and these fields. L lists other -fields related to a alarms that are common to all record types. +fields related to a alarms that are common to all record types. =fields UNSV, COSV, ZRSV, ONSV, TWSV, THSV, FRSV, FVSV, SXSV, SVSV, EISV, NISV, TESV, ELSV, TVSV, TTSV, FTSV, FFSV @@ -709,14 +641,6 @@ See L for more information on these fields. menu(menuAlarmSevr) } -=pod - -=begin html - -


- -=end html - =head2 Record Support =head3 Record Support Routines @@ -869,7 +793,6 @@ Scan forward link if necessary, set PACT FALSE, and return. =back - =head2 Device Support =head3 Fields Of Interest To Device Support @@ -882,12 +805,6 @@ primarily interested in the following fields: =fields PACT, DPVT, UDF, NSEV, NSTA, NOBT, VAL, INP, RVAL, MASK, SHFT -=begin html - -


- -=end html - =head3 Device Support Routines Device support consists of the following routines: @@ -979,7 +896,6 @@ This module is like the previous except that values are read into RVAL, VAL is computed from RVAL, and read_mbbi returns a value of 0. Thus the record processing routine will determine VAL in the normal way. - =cut } diff --git a/src/std/rec/mbboDirectRecord.dbd.pod b/src/std/rec/mbboDirectRecord.dbd.pod index e730bc854..40a5532e9 100644 --- a/src/std/rec/mbboDirectRecord.dbd.pod +++ b/src/std/rec/mbboDirectRecord.dbd.pod @@ -7,7 +7,7 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=head1 B +=title Multi-Bit Binary Output Direct Record (mbboDirect) The mbboDirect record performs the opposite function to that of the mbbiDirect record. It accumulates bits (in the fields B0 - BF) as unsigned characters, and @@ -15,56 +15,6 @@ converts them to a word which is then written out to hardware. If a bit field is non-zero, it is interpreted as a binary 1. On the other hand, if it is zero, it is interpreted as a binary 0. -=head1 L - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=back - -=back - -=begin html - -


- -=end html - =recordtype mbboDirect =cut @@ -73,21 +23,7 @@ recordtype(mbboDirect) { =head2 Parameter Fields -The mbboDirect record's fields fall into the following categories: - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back +The record-specific fields are described below, grouped by functionality. =head3 Scan Parameters @@ -153,7 +89,7 @@ description (DESC) fields. =cut - include "dbCommon.dbd" + include "dbCommon.dbd" field(VAL,DBF_USHORT) { prompt("Word") promptgroup("50 - Output") diff --git a/src/std/rec/permissiveRecord.dbd.pod b/src/std/rec/permissiveRecord.dbd.pod index bdcecb5e7..5ad979f74 100644 --- a/src/std/rec/permissiveRecord.dbd.pod +++ b/src/std/rec/permissiveRecord.dbd.pod @@ -7,52 +7,14 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=head1 Permissive Record (permissive) +=title Permissive Record (permissive) The permissive record is for communication between a server and a client. An example would be a sequence program server and an operator interface client. By using multiple permissive records a sequence program can communicate its current state to the client. -B - -=head2 Contents - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L - -=item * L - -=item * L - -=back - -=item * L - -=over - -=item * L - -=back - -=back - -=begin html - -
-
-
- -=end html +B =recordtype permissive @@ -63,6 +25,8 @@ recordtype(permissive) { =head2 Parameter Fields +The record-specific fields are described below, grouped by functionality. + =head3 Scan Parameters The permissive record has the standard fields for specifying under what @@ -150,7 +114,7 @@ OLFG. =head2 Record Support -=head3 Record Support Routines (permissiveRecord.c) +=head3 Record Support Routines =head4 process diff --git a/src/std/rec/selRecord.dbd.pod b/src/std/rec/selRecord.dbd.pod index 9e49745cc..fe8301db6 100644 --- a/src/std/rec/selRecord.dbd.pod +++ b/src/std/rec/selRecord.dbd.pod @@ -7,59 +7,13 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -=pod - -=head1 Select Record (sel) +=title Select Record (sel) The select record computes a value based on input obtained from up to 12 locations. The selection algorithm can be one of the following: C<<< Specified >>>, C<<< High Signal >>>, C<<< Low Signal >>>, C<<< Median Signal >>>. Each input can be a constant, a database link, or a channel access link. -=head2 Contents - -=over - -=item * L - -=over - -=item * L - -=item * L - -=item * L