From 51e492fbb184fe92b9d8873cd541b6bc7138f819 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 9 Feb 2018 14:37:45 +0100 Subject: [PATCH 01/46] Fix numeric events: any number from 0 up to less than 256 is theated as an integer event. Event 0 is no event. --- src/ioc/db/dbScan.c | 84 +++++++++++++++++++++++++-------------------- src/ioc/db/dbScan.h | 2 +- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index e0c48d4c3..78c098281 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -111,8 +111,8 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = { typedef struct event_list { CALLBACK callback[NUM_CALLBACK_PRIORITIES]; scan_list scan_list[NUM_CALLBACK_PRIORITIES]; - struct event_list *next; - char event_name[MAX_STRING_SIZE]; + struct event_list *next; + char eventname[1]; /* actually arbitrary size */ } event_list; static event_list * volatile pevent_list[256]; static epicsMutexId event_lock; @@ -249,11 +249,6 @@ void scanAdd(struct dbCommon *precord) event_list *pel; eventname = precord->evnt; - if (strlen(eventname) >= MAX_STRING_SIZE) { - recGblRecordError(S_db_badField, (void *)precord, - "scanAdd: too long EVNT value"); - return; - } prio = precord->prio; if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { recGblRecordError(-1, (void *)precord, @@ -317,24 +312,17 @@ void scanDelete(struct dbCommon *precord) recGblRecordError(-1, (void *)precord, "scanDelete detected illegal SCAN value"); } else if (scan == menuScanEvent) { - char* eventname; int prio; event_list *pel; scan_list *psl = 0; - eventname = precord->evnt; prio = precord->prio; if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { recGblRecordError(-1, (void *)precord, "scanDelete detected illegal PRIO field"); return; } - do /* multithreading: make sure pel is consistent */ - pel = pevent_list[0]; - while (pel != pevent_list[0]); - for (; pel; pel=pel->next) { - if (strcmp(pel->event_name, eventname) == 0) break; - } + pel = eventNameToHandle(precord->evnt); if (pel && (psl = &pel->scan_list[prio])) deleteFromList(precord, psl); } else if (scan == menuScanI_O_Intr) { @@ -422,14 +410,12 @@ int scanpel(const char* eventname) /* print event list */ int prio; event_list *pel; - do /* multithreading: make sure pel is consistent */ - pel = pevent_list[0]; - while (pel != pevent_list[0]); - for (; pel; pel = pel->next) { - if (!eventname || strcmp(pel->event_name, eventname) == 0) { + for (pel = pevent_list[0]; pel; pel = pel->next) { + if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) { for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { if (ellCount(&pel->scan_list[prio].list) == 0) continue; - sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]); + sprintf(message, "Event \"%.*s\" Priority %s", + sizeof(message)-25, pel->eventname, priorityName[prio]); printList(&pel->scan_list[prio], message); } } @@ -480,18 +466,50 @@ event_list *eventNameToHandle(const char *eventname) int prio; event_list *pel; static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; + char* p; + double eventnumber; + size_t namelength; - if (!eventname || eventname[0] == 0) - return NULL; + if (!eventname) return NULL; + while (isblank(eventname[0])) eventname++; + if (!eventname[0]) return NULL; + namelength = strlen(eventname); + while (isblank(eventname[namelength-1])) namelength--; + + /* Backward compatibility with numeric events: + Treat any string that represents a double with an + integer part between 0 and 255 the same as the integer + because it is most probably a conversion from double + like from a calc record. + */ + if (epicsParseDouble(eventname, &eventnumber, &p) == 0 && + eventnumber >= 0 && eventnumber < 256 && *p == 0) + { + if (eventnumber < 1) + return NULL; /* 0 is no event */ + if ((pel = pevent_list[(int)eventnumber]) != NULL) + return pel; + } + else + eventnumber = 0; /* not a numeric event */ epicsThreadOnce(&onceId, eventOnce, NULL); epicsMutexMustLock(event_lock); for (pel = pevent_list[0]; pel; pel=pel->next) { - if (strcmp(pel->event_name, eventname) == 0) break; + if (strncmp(pel->eventname, eventname, namelength) == 0 + && pel->eventname[namelength] == 0) + break; } if (pel == NULL) { - pel = dbCalloc(1, sizeof(event_list)); - strcpy(pel->event_name, eventname); + pel = dbCalloc(1, sizeof(event_list) + namelength); + if (eventnumber > 0) + { + /* backward compatibility: make all numeric events look like integers */ + sprintf(pel->eventname, "%i", (int)eventnumber); + pevent_list[(int)eventnumber] = pel; + } + else + strncpy(pel->eventname, eventname, namelength); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]); callbackSetPriority(prio, &pel->callback[prio]); @@ -501,12 +519,6 @@ event_list *eventNameToHandle(const char *eventname) } pel->next=pevent_list[0]; pevent_list[0]=pel; - { /* backward compatibility */ - char* p; - long e = strtol(eventname, &p, 0); - if (*p == 0 && e > 0 && e <= 255) - pevent_list[e] = pel; - } } epicsMutexUnlock(event_lock); return pel; @@ -518,6 +530,7 @@ void postEvent(event_list *pel) if (scanCtl != ctlRun) return; if (!pel) return; + printf("postEvent %p \"%s\"\n", pel, pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { if (ellCount(&pel->scan_list[prio].list) >0) callbackRequest(&pel->callback[prio]); @@ -527,13 +540,8 @@ void postEvent(event_list *pel) /* backward compatibility */ void post_event(int event) { - event_list* pel; - if (event <= 0 || event > 255) return; - do { /* multithreading: make sure pel is consistent */ - pel = pevent_list[event]; - } while (pel != pevent_list[event]); - postEvent(pel); + postEvent(pevent_list[event]); } static void ioscanOnce(void *arg) diff --git a/src/ioc/db/dbScan.h b/src/ioc/db/dbScan.h index 28d2e133d..d3102712d 100644 --- a/src/ioc/db/dbScan.h +++ b/src/ioc/db/dbScan.h @@ -50,7 +50,7 @@ epicsShareFunc void scanCleanup(void); epicsShareFunc EVENTPVT eventNameToHandle(const char* event); epicsShareFunc void postEvent(EVENTPVT epvt); -epicsShareFunc void post_event(int event) EPICS_DEPRECATED; +epicsShareFunc void post_event(int event); epicsShareFunc void scanAdd(struct dbCommon *); epicsShareFunc void scanDelete(struct dbCommon *); epicsShareFunc double scanPeriod(int scan); From 7d836d9554fd728c3dc40915c503a7fa0cf79ab0 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 9 Feb 2018 16:58:36 +0100 Subject: [PATCH 02/46] some cleanup and scanpel improvement --- src/ioc/db/dbScan.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 78c098281..974cd847f 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -27,6 +27,7 @@ #include "epicsEvent.h" #include "epicsExit.h" #include "epicsInterrupt.h" +#include "epicsMath.h" #include "epicsMutex.h" #include "epicsPrint.h" #include "epicsRingPointer.h" @@ -412,10 +413,11 @@ int scanpel(const char* eventname) /* print event list */ for (pel = pevent_list[0]; pel; pel = pel->next) { if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) { + printf("Event \"%s\"\n", pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { - if (ellCount(&pel->scan_list[prio].list) == 0) continue; sprintf(message, "Event \"%.*s\" Priority %s", - sizeof(message)-25, pel->eventname, priorityName[prio]); + (int)(sizeof(message)-25), pel->eventname, priorityName[prio]); + sprintf(message, " Priority %s", priorityName[prio]); printList(&pel->scan_list[prio], message); } } @@ -466,15 +468,14 @@ event_list *eventNameToHandle(const char *eventname) int prio; event_list *pel; static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; - char* p; double eventnumber; size_t namelength; if (!eventname) return NULL; - while (isblank(eventname[0])) eventname++; + while (isspace((unsigned char)eventname[0])) eventname++; if (!eventname[0]) return NULL; namelength = strlen(eventname); - while (isblank(eventname[namelength-1])) namelength--; + while (isspace((unsigned char)eventname[namelength-1])) namelength--; /* Backward compatibility with numeric events: Treat any string that represents a double with an @@ -482,13 +483,17 @@ event_list *eventNameToHandle(const char *eventname) because it is most probably a conversion from double like from a calc record. */ - if (epicsParseDouble(eventname, &eventnumber, &p) == 0 && - eventnumber >= 0 && eventnumber < 256 && *p == 0) + if (epicsParseDouble(eventname, &eventnumber, NULL) == 0) { - if (eventnumber < 1) - return NULL; /* 0 is no event */ - if ((pel = pevent_list[(int)eventnumber]) != NULL) - return pel; + if (!finite(eventnumber)) + return NULL; /* Inf and NaN are no events */ + if (eventnumber >= 0 && eventnumber < 256) + { + if (eventnumber < 1) + return NULL; /* 0 is no event */ + if ((pel = pevent_list[(int)eventnumber]) != NULL) + return pel; + } } else eventnumber = 0; /* not a numeric event */ @@ -530,7 +535,6 @@ void postEvent(event_list *pel) if (scanCtl != ctlRun) return; if (!pel) return; - printf("postEvent %p \"%s\"\n", pel, pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { if (ellCount(&pel->scan_list[prio].list) >0) callbackRequest(&pel->callback[prio]); From adf53756162088892dece1303d604aae748a407c Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 12 Feb 2018 09:01:05 +0100 Subject: [PATCH 03/46] fix scanpel glob matching --- src/ioc/db/dbScan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 974cd847f..a77ec3a5a 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -412,7 +412,7 @@ int scanpel(const char* eventname) /* print event list */ event_list *pel; for (pel = pevent_list[0]; pel; pel = pel->next) { - if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) { + if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) { printf("Event \"%s\"\n", pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { sprintf(message, "Event \"%.*s\" Priority %s", From d19afc73afd01861c61462d60588595ba9d8673c Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 12 Feb 2018 12:06:12 +0100 Subject: [PATCH 04/46] Updated RELEASE_NOTES.html with soft event fix. --- documentation/RELEASE_NOTES.html | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 33f12c441..d8dd5d501 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -29,11 +29,28 @@ 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 problem with numeric soft events

+

Changing from numeric to named soft events introduced an incompatibility +when a numeric event is converted from a DOUBLE, e.g. from a calc record. +To make named events backward compatible to numeric events, the logic has +changed as follows:

+
  • Leading and trailing spaces are strippd from the event name +
  • Empty event names are no events +
  • If the event name can be converted to double: +
    • If the double is not finite (inf or nan) it is no event. +
    • If the double truncated to integer is between 1 and 255 + it is a numeric event. Its name is changed to the decimal + integer representation. +
    • If the double truncated to integer is 0 it is no event. +
    +
  • All other cases are named events +
+

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

Changes from the 3.14 branch since 3.15.5

-

Extend maximum Posix epicsEventWaitWithTimeout() delay

The Posix implementation of epicsEventWaitWithTimeout() was limiting the From 8a3080c16fd4ac4fdba504ef79d4d275d916aef6 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 13 Feb 2018 13:50:19 +0100 Subject: [PATCH 05/46] added test for named soft events --- src/ioc/db/test/Makefile | 13 ++++ src/ioc/db/test/epicsRunDbTests.c | 2 + src/ioc/db/test/scanEventTest.c | 117 ++++++++++++++++++++++++++++++ src/ioc/db/test/scanEventTest.db | 9 +++ 4 files changed, 141 insertions(+) create mode 100644 src/ioc/db/test/scanEventTest.c create mode 100644 src/ioc/db/test/scanEventTest.db diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 215545f4a..ec6b85673 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -138,6 +138,19 @@ testHarness_SRCS += dbPutGetTest.db TESTFILES += ../dbPutGetTest.db TESTS += testPutGetTest +TARGETS += $(COMMON_DIR)/scanEventTest.dbd +DBDDEPENDS_FILES += scanEventTest.dbd$(DEP) +scanEventTest_DBD += menuGlobal.dbd +scanEventTest_DBD += menuConvert.dbd +scanEventTest_DBD += menuScan.dbd +scanEventTest_DBD += eventRecord.dbd +scanEventTest_DBD += calcRecord.dbd +TESTPROD_HOST += scanEventTest +scanEventTest_SRCS += scanEventTest.c +scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp +scanEventTest_LIBS = dbRecStd +TESTS += scanEventTest + # This runs all the test programs in a known working order: testHarness_SRCS += epicsRunDbTests.c diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index 05fedeb51..ce41815fb 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -29,6 +29,7 @@ int testDbChannel(void); int chfPluginTest(void); int arrShorthandTest(void); int recGblCheckDeadbandTest(void); +int scanEventTest(void); void epicsRunDbTests(void) { @@ -47,6 +48,7 @@ void epicsRunDbTests(void) runTest(arrShorthandTest); runTest(recGblCheckDeadbandTest); runTest(chfPluginTest); + runTest(scanEventTest); dbmfFreeChunks(); diff --git a/src/ioc/db/test/scanEventTest.c b/src/ioc/db/test/scanEventTest.c new file mode 100644 index 000000000..e48110bcc --- /dev/null +++ b/src/ioc/db/test/scanEventTest.c @@ -0,0 +1,117 @@ +/*************************************************************************\ +* Copyright (c) 2018 Paul Scherrer Institut +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. + \*************************************************************************/ + +/* + * Author: Dirk Zimoch + */ + +#include +#include "dbStaticLib.h" +#include "dbAccessDefs.h" +#include "dbUnitTest.h" +#include "testMain.h" +#include "osiFileName.h" +#include "dbScan.h" + +void scanEventTest_registerRecordDeviceDriver(struct dbBase *); + +/* test name to event number: + num = 0 is no event, + num > 0 is numeric event + num < 0 is string event (use same unique number for aliases) +*/ +const struct {char* name; int num;} events[] = { + {"", 0}, + {" ", 0}, + {"0", 0}, + {"0.000000", 0}, + {"-0.00000", 0}, + {"0.9", 0}, + {"nan", 0}, + {"NaN", 0}, + {"-NAN", 0}, + {"-inf", 0}, + {"inf", 0}, + {"info 1", -1}, + {" info 1 ", -1}, + {"-0.9", -2}, + {"2", 2}, + {"2.000000", 2}, + {"2.5", 2}, + {" 2.5 ", 2}, + {"+0x02", 2}, + {"-2", -3}, + {"-2.000000", -4}, + {"-2.5", -5}, + {" -2.5 ", -5}, +}; + +MAIN(scanEventTest) +{ + unsigned int i; + int aliases[512] ; + int expected_count[512]; + #define INDX(i) 256-events[i].num + + testPlan(NELEMENTS(events)*2); + + memset(aliases, 0, sizeof(aliases)); + memset(expected_count, 0, sizeof(expected_count)); + + if (dbReadDatabase(&pdbbase, "scanEventTest.dbd", + "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR + "../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL)) + testAbort("Database description 'scanEventTest.dbd' not found"); + + scanEventTest_registerRecordDeviceDriver(pdbbase); + for (i = 0; i < NELEMENTS(events); i++) { + char substitutions[256]; + sprintf(substitutions, "N=%d,EVENT=%s", i, events[i].name); + if (dbReadDatabase(&pdbbase, "scanEventTest.db", + "." OSI_PATH_LIST_SEPARATOR "..", substitutions)) + testAbort("Error reading test database 'scanEventTest.db'"); + } + testIocInitOk(); + for (i = 0; i < NELEMENTS(events); i++) { + EVENTPVT pev = eventNameToHandle(events[i].name); + /* test that some names are not events (num=0) */ + if (events[i].num == 0) + testOk(pev == NULL, "\"%s\" -> no event", events[i].name); + else + { + expected_count[INDX(i)]++; /* +1 for postEvent */ + if (events[i].num > 0) + { + testOk(pev != NULL, "\"%s\" -> numeric event %d", events[i].name, events[i].num); + expected_count[INDX(i)]++; /* +1 for post_event */ + } + else + { + /* test that some strings resolve the same event (num!=0) */ + if (!aliases[INDX(i)]) + { + aliases[INDX(i)] = i; + testOk(pev != NULL, "\"%s\" -> new named event", events[i].name); + } + else + { + testOk(pev == eventNameToHandle(events[aliases[INDX(i)]].name), + "\"%s\" alias for \"%s\"", events[i].name, events[aliases[INDX(i)]].name); + } + } + } + post_event(events[i].num); + postEvent(pev); + } + for (i = 0; i < NELEMENTS(events); i++) { + char pvname[100]; + sprintf(pvname, "c%d", i); + testDiag("Check if %s (event \"%s\") has processed %d times", pvname, events[i].name, expected_count[INDX(i)]); + testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]); + } + + return testDone(); +} diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db new file mode 100644 index 000000000..439d30da8 --- /dev/null +++ b/src/ioc/db/test/scanEventTest.db @@ -0,0 +1,9 @@ +record(calc, "c$(N)") { + field(SCAN, "Event") + field(EVNT, "$(EVENT)") + field(CALC, "VAL+1") +} +record(event, "e$(N)") { + field(SCAN, "Event") + field(VAL, "$(EVENT)") +} From 0691fc5f57fb9c6cf79669e3a0d3260c0a1a2f42 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 13 Feb 2018 14:10:29 +0100 Subject: [PATCH 06/46] fix scanEvent test --- src/ioc/db/test/scanEventTest.db | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db index 439d30da8..dbdb61f77 100644 --- a/src/ioc/db/test/scanEventTest.db +++ b/src/ioc/db/test/scanEventTest.db @@ -3,7 +3,3 @@ record(calc, "c$(N)") { field(EVNT, "$(EVENT)") field(CALC, "VAL+1") } -record(event, "e$(N)") { - field(SCAN, "Event") - field(VAL, "$(EVENT)") -} From 1e9826d1878a2a3cbbed38eea0fd1a1183213917 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 13 Feb 2018 15:36:21 +0100 Subject: [PATCH 07/46] add tests for calculated numeric soft events --- src/ioc/db/test/Makefile | 2 ++ src/ioc/db/test/devEventSoft.dbd | 1 + src/ioc/db/test/scanEventTest.c | 34 +++++++++++++++++++++++++------- src/ioc/db/test/scanEventTest.db | 11 +++++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 src/ioc/db/test/devEventSoft.dbd diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index ec6b85673..77e485aec 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -144,7 +144,9 @@ scanEventTest_DBD += menuGlobal.dbd scanEventTest_DBD += menuConvert.dbd scanEventTest_DBD += menuScan.dbd scanEventTest_DBD += eventRecord.dbd +scanEventTest_DBD += devEventSoft.dbd scanEventTest_DBD += calcRecord.dbd +scanEventTest_DBD += dfanoutRecord.dbd TESTPROD_HOST += scanEventTest scanEventTest_SRCS += scanEventTest.c scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp diff --git a/src/ioc/db/test/devEventSoft.dbd b/src/ioc/db/test/devEventSoft.dbd new file mode 100644 index 000000000..ec3bc2d07 --- /dev/null +++ b/src/ioc/db/test/devEventSoft.dbd @@ -0,0 +1 @@ +device(event,CONSTANT,devEventSoft,"Soft Channel") diff --git a/src/ioc/db/test/scanEventTest.c b/src/ioc/db/test/scanEventTest.c index e48110bcc..9835b7bf8 100644 --- a/src/ioc/db/test/scanEventTest.c +++ b/src/ioc/db/test/scanEventTest.c @@ -35,14 +35,15 @@ const struct {char* name; int num;} events[] = { {"-NAN", 0}, {"-inf", 0}, {"inf", 0}, - {"info 1", -1}, - {" info 1 ", -1}, - {"-0.9", -2}, {"2", 2}, {"2.000000", 2}, {"2.5", 2}, {" 2.5 ", 2}, {"+0x02", 2}, + {"3", 3}, + {"info 1", -1}, + {" info 1 ", -1}, + {"-0.9", -2}, {"-2", -3}, {"-2.000000", -4}, {"-2.5", -5}, @@ -51,12 +52,13 @@ const struct {char* name; int num;} events[] = { MAIN(scanEventTest) { - unsigned int i; + int i, e; int aliases[512] ; int expected_count[512]; #define INDX(i) 256-events[i].num + #define MAXEV 5 - testPlan(NELEMENTS(events)*2); + testPlan(NELEMENTS(events)*2+(MAXEV+1)*5); memset(aliases, 0, sizeof(aliases)); memset(expected_count, 0, sizeof(expected_count)); @@ -75,6 +77,7 @@ MAIN(scanEventTest) testAbort("Error reading test database 'scanEventTest.db'"); } testIocInitOk(); + testDiag("Test if eventNameToHandle() strips spaces and handles numeric events"); for (i = 0; i < NELEMENTS(events); i++) { EVENTPVT pev = eventNameToHandle(events[i].name); /* test that some names are not events (num=0) */ @@ -103,13 +106,30 @@ MAIN(scanEventTest) } } } - post_event(events[i].num); + post_event(events[i].num); /* triggers numeric events only */ postEvent(pev); } + + testDiag("Check calculated numeric events (backward compatibility)"); + for (e = 0; e <= MAXEV; e++) { + testdbPutFieldOk("eventnum", DBR_LONG, e); + testdbGetFieldEqual("e1", DBR_LONG, e); + testdbGetFieldEqual("e2", DBR_LONG, e); + testdbPutFieldOk("e3", DBR_LONG, e); + testdbPutFieldOk("e3.PROC", DBR_LONG, 1); + if (e != 0) + for (i = 0; i < NELEMENTS(events); i++) + if (events[i].num == e) { + expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */ + break; + } + } + + testDiag("Check if events have been processed the expected number of times"); for (i = 0; i < NELEMENTS(events); i++) { char pvname[100]; sprintf(pvname, "c%d", i); - testDiag("Check if %s (event \"%s\") has processed %d times", pvname, events[i].name, expected_count[INDX(i)]); + testDiag("Event \"%s\" expected %d times", events[i].name, expected_count[INDX(i)]); testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]); } diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db index dbdb61f77..9118823d8 100644 --- a/src/ioc/db/test/scanEventTest.db +++ b/src/ioc/db/test/scanEventTest.db @@ -3,3 +3,14 @@ record(calc, "c$(N)") { field(EVNT, "$(EVENT)") field(CALC, "VAL+1") } +record(dfanout, "eventnum") { + field(OUTA, "e1 PP") + field(FLNK, "e2") +} +record(event, "e1") { +} +record(event, "e2") { + field(INP, "eventnum") +} +record(event, "e3") { +} From b2d6b67b06bd40acd31bfdbee78d353b98deacfa Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 16 Feb 2018 11:03:12 +0100 Subject: [PATCH 08/46] removed obsolete code in scanpel --- src/ioc/db/dbScan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index a77ec3a5a..cabd73679 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -415,8 +415,7 @@ int scanpel(const char* eventname) /* print event list */ if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) { printf("Event \"%s\"\n", pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { - sprintf(message, "Event \"%.*s\" Priority %s", - (int)(sizeof(message)-25), pel->eventname, priorityName[prio]); + if (ellCount(&pel->scan_list[prio].list) == 0) continue; sprintf(message, " Priority %s", priorityName[prio]); printList(&pel->scan_list[prio], message); } From 29795656e6be467d541f2292b750129a64f782cf Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 20 Feb 2018 09:53:06 +0100 Subject: [PATCH 09/46] bugfix for soft events >= 256 --- src/ioc/db/dbScan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index cabd73679..28c3dda5e 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -467,7 +467,7 @@ event_list *eventNameToHandle(const char *eventname) int prio; event_list *pel; static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; - double eventnumber; + double eventnumber = 0; size_t namelength; if (!eventname) return NULL; @@ -493,9 +493,9 @@ event_list *eventNameToHandle(const char *eventname) if ((pel = pevent_list[(int)eventnumber]) != NULL) return pel; } + else + eventnumber = 0; /* not a numeric event between 1 and 255 */ } - else - eventnumber = 0; /* not a numeric event */ epicsThreadOnce(&onceId, eventOnce, NULL); epicsMutexMustLock(event_lock); From 428a8f57e9a5caf8949702daf401cdd0832e5dd1 Mon Sep 17 00:00:00 2001 From: "J. Lewis Muir" Date: Tue, 20 Feb 2018 10:20:37 -0600 Subject: [PATCH 10/46] Fix typos in Channel Filters doc --- src/std/filters/filters.dbd.pod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/std/filters/filters.dbd.pod b/src/std/filters/filters.dbd.pod index db97907a5..f1a848469 100644 --- a/src/std/filters/filters.dbd.pod +++ b/src/std/filters/filters.dbd.pod @@ -146,9 +146,9 @@ Note: Negative index numbers address from the end of the array, with C<-1> being =item Square bracket notation C<[start:increment:end]> (shorthand) -The common square bracket notation with can be used in place of JSON. +The common square bracket notation which can be used in place of JSON. Any parameter may be omitted (keeping the colons) to use the default value. -If only one colon is included, this means C<[start:end]> with a increment of 1. +If only one colon is included, this means C<[start:end]> with an increment of 1. If only a single parameter is used C<[index]> the filter returns one element. =item Start index C<"s"> From e50c46851274f4f4cf791428a5c2bab9f1f4c677 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 26 Feb 2018 11:41:20 +0100 Subject: [PATCH 11/46] moved scanEventTest from src/ioc/db/test to src/std/rec/test --- src/ioc/db/test/Makefile | 15 --------------- src/ioc/db/test/devEventSoft.dbd | 1 - src/ioc/db/test/epicsRunDbTests.c | 2 -- src/std/rec/test/Makefile | 9 +++++++++ src/std/rec/test/epicsRunRecordTests.c | 2 ++ src/{ioc/db => std/rec}/test/scanEventTest.c | 0 src/{ioc/db => std/rec}/test/scanEventTest.db | 0 7 files changed, 11 insertions(+), 18 deletions(-) delete mode 100644 src/ioc/db/test/devEventSoft.dbd rename src/{ioc/db => std/rec}/test/scanEventTest.c (100%) rename src/{ioc/db => std/rec}/test/scanEventTest.db (100%) diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 77e485aec..215545f4a 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -138,21 +138,6 @@ testHarness_SRCS += dbPutGetTest.db TESTFILES += ../dbPutGetTest.db TESTS += testPutGetTest -TARGETS += $(COMMON_DIR)/scanEventTest.dbd -DBDDEPENDS_FILES += scanEventTest.dbd$(DEP) -scanEventTest_DBD += menuGlobal.dbd -scanEventTest_DBD += menuConvert.dbd -scanEventTest_DBD += menuScan.dbd -scanEventTest_DBD += eventRecord.dbd -scanEventTest_DBD += devEventSoft.dbd -scanEventTest_DBD += calcRecord.dbd -scanEventTest_DBD += dfanoutRecord.dbd -TESTPROD_HOST += scanEventTest -scanEventTest_SRCS += scanEventTest.c -scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp -scanEventTest_LIBS = dbRecStd -TESTS += scanEventTest - # This runs all the test programs in a known working order: testHarness_SRCS += epicsRunDbTests.c diff --git a/src/ioc/db/test/devEventSoft.dbd b/src/ioc/db/test/devEventSoft.dbd deleted file mode 100644 index ec3bc2d07..000000000 --- a/src/ioc/db/test/devEventSoft.dbd +++ /dev/null @@ -1 +0,0 @@ -device(event,CONSTANT,devEventSoft,"Soft Channel") diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index ce41815fb..05fedeb51 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -29,7 +29,6 @@ int testDbChannel(void); int chfPluginTest(void); int arrShorthandTest(void); int recGblCheckDeadbandTest(void); -int scanEventTest(void); void epicsRunDbTests(void) { @@ -48,7 +47,6 @@ void epicsRunDbTests(void) runTest(arrShorthandTest); runTest(recGblCheckDeadbandTest); runTest(chfPluginTest); - runTest(scanEventTest); dbmfFreeChunks(); diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index 5322c8e92..70b6e173e 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -37,6 +37,15 @@ testHarness_SRCS += analogMonitorTest_registerRecordDeviceDriver.cpp TESTFILES += $(COMMON_DIR)/analogMonitorTest.dbd ../analogMonitorTest.db TESTS += analogMonitorTest +TARGETS += $(COMMON_DIR)/scanEventTest.dbd +DBDDEPENDS_FILES += scanEventTest.dbd$(DEP) +scanEventTest_DBD += base.dbd +TESTPROD_HOST += scanEventTest +scanEventTest_SRCS += scanEventTest.c +scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp +TESTFILES += $(COMMON_DIR)/scanEventTest.dbd ../scanEventTest.db +TESTS += scanEventTest + TARGETS += $(COMMON_DIR)/regressTest.dbd DBDDEPENDS_FILES += regressTest.dbd$(DEP) regressTest_DBD += base.dbd diff --git a/src/std/rec/test/epicsRunRecordTests.c b/src/std/rec/test/epicsRunRecordTests.c index 092c0a6ce..1a7133c19 100644 --- a/src/std/rec/test/epicsRunRecordTests.c +++ b/src/std/rec/test/epicsRunRecordTests.c @@ -14,6 +14,7 @@ int analogMonitorTest(void); int arrayOpTest(void); +int scanEventTest(void); void epicsRunRecordTests(void) { @@ -22,6 +23,7 @@ void epicsRunRecordTests(void) runTest(analogMonitorTest); runTest(arrayOpTest); + runTest(scanEventTest); epicsExit(0); /* Trigger test harness */ } diff --git a/src/ioc/db/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c similarity index 100% rename from src/ioc/db/test/scanEventTest.c rename to src/std/rec/test/scanEventTest.c diff --git a/src/ioc/db/test/scanEventTest.db b/src/std/rec/test/scanEventTest.db similarity index 100% rename from src/ioc/db/test/scanEventTest.db rename to src/std/rec/test/scanEventTest.db From 396cf4ee3f7194b6e4939fba7708d2b87e0740aa Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 7 Mar 2018 14:49:12 +0100 Subject: [PATCH 12/46] remove special handling for inf and nan events --- src/ioc/db/dbScan.c | 5 +---- src/std/rec/test/scanEventTest.c | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 28c3dda5e..e9dc178a2 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -27,7 +27,6 @@ #include "epicsEvent.h" #include "epicsExit.h" #include "epicsInterrupt.h" -#include "epicsMath.h" #include "epicsMutex.h" #include "epicsPrint.h" #include "epicsRingPointer.h" @@ -484,8 +483,6 @@ event_list *eventNameToHandle(const char *eventname) */ if (epicsParseDouble(eventname, &eventnumber, NULL) == 0) { - if (!finite(eventnumber)) - return NULL; /* Inf and NaN are no events */ if (eventnumber >= 0 && eventnumber < 256) { if (eventnumber < 1) @@ -493,7 +490,7 @@ event_list *eventNameToHandle(const char *eventname) if ((pel = pevent_list[(int)eventnumber]) != NULL) return pel; } - else + else eventnumber = 0; /* not a numeric event between 1 and 255 */ } diff --git a/src/std/rec/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c index 9835b7bf8..595264a8f 100644 --- a/src/std/rec/test/scanEventTest.c +++ b/src/std/rec/test/scanEventTest.c @@ -14,6 +14,7 @@ #include "dbUnitTest.h" #include "testMain.h" #include "osiFileName.h" +#include "epicsThread.h" #include "dbScan.h" void scanEventTest_registerRecordDeviceDriver(struct dbBase *); @@ -24,23 +25,22 @@ void scanEventTest_registerRecordDeviceDriver(struct dbBase *); num < 0 is string event (use same unique number for aliases) */ const struct {char* name; int num;} events[] = { +/* No events */ + {NULL, 0}, {"", 0}, {" ", 0}, {"0", 0}, {"0.000000", 0}, {"-0.00000", 0}, {"0.9", 0}, - {"nan", 0}, - {"NaN", 0}, - {"-NAN", 0}, - {"-inf", 0}, - {"inf", 0}, +/* Numeric events */ {"2", 2}, {"2.000000", 2}, {"2.5", 2}, {" 2.5 ", 2}, {"+0x02", 2}, {"3", 3}, +/* Named events */ {"info 1", -1}, {" info 1 ", -1}, {"-0.9", -2}, @@ -48,6 +48,11 @@ const struct {char* name; int num;} events[] = { {"-2.000000", -4}, {"-2.5", -5}, {" -2.5 ", -5}, + {"nan", -6}, + {"NaN", -7}, + {"-NAN", -8}, + {"-inf", -9}, + {"inf", -10}, }; MAIN(scanEventTest) @@ -117,14 +122,14 @@ MAIN(scanEventTest) testdbGetFieldEqual("e2", DBR_LONG, e); testdbPutFieldOk("e3", DBR_LONG, e); testdbPutFieldOk("e3.PROC", DBR_LONG, 1); - if (e != 0) - for (i = 0; i < NELEMENTS(events); i++) - if (events[i].num == e) { - expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */ - break; - } + for (i = 0; i < NELEMENTS(events); i++) + if (e > 0 && e < 256 && events[i].num == e) { /* numeric events */ + expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */ + break; + } } - + /* Allow records to finish processing */ + epicsThreadSleep(0.1); testDiag("Check if events have been processed the expected number of times"); for (i = 0; i < NELEMENTS(events); i++) { char pvname[100]; From 2b4a9632b7e21a60b80e1454e44db41d8128ad06 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 7 Mar 2018 14:51:38 +0100 Subject: [PATCH 13/46] update RELEASE_NOTES for named event fix --- documentation/RELEASE_NOTES.html | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index d8dd5d501..d19664ea1 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -16,6 +16,14 @@ +

Fix problem with numeric soft events

+

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. + +

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

Added a new OS-independent typedef for multicast socket options, and a test @@ -29,28 +37,11 @@ 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 problem with numeric soft events

-

Changing from numeric to named soft events introduced an incompatibility -when a numeric event is converted from a DOUBLE, e.g. from a calc record. -To make named events backward compatible to numeric events, the logic has -changed as follows:

-
  • Leading and trailing spaces are strippd from the event name -
  • Empty event names are no events -
  • If the event name can be converted to double: -
    • If the double is not finite (inf or nan) it is no event. -
    • If the double truncated to integer is between 1 and 255 - it is a numeric event. Its name is changed to the decimal - integer representation. -
    • If the double truncated to integer is 0 it is no event. -
    -
  • All other cases are named events -
-

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

Changes from the 3.14 branch since 3.15.5

+

Extend maximum Posix epicsEventWaitWithTimeout() delay

The Posix implementation of epicsEventWaitWithTimeout() was limiting the From 05a3699b49642d43655022f365b7bb8c7ed4460b Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 18 Feb 2017 03:27:49 -0800 Subject: [PATCH 14/46] Update pcas CA error msgs to include the pv name for easier debugging. --- src/ca/legacy/pcas/generic/casPVI.cc | 32 ++++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/ca/legacy/pcas/generic/casPVI.cc b/src/ca/legacy/pcas/generic/casPVI.cc index 50e5d27a7..48692b99b 100644 --- a/src/ca/legacy/pcas/generic/casPVI.cc +++ b/src/ca/legacy/pcas/generic/casPVI.cc @@ -26,6 +26,11 @@ #include "casAsyncIOI.h" #include "casMonitor.h" + +// Use casErrMessage instead of errMessage to show PV name +#define casErrMessage(S, PM) \ + errPrintf(S, __FILE__, __LINE__, ", %s, %s", getName(), PM) + casPVI::casPVI ( casPV & intf ) : pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ), nIOAttached ( 0u ), deletePending ( false ) {} @@ -146,7 +151,7 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn ) // gddArray(int app, aitEnum prim, int dimen, ...); gdd * pTmp = new gddScalar ( gddAppType_enums ); if ( pTmp == NULL ) { - errMessage ( S_cas_noMemory, + casErrMessage ( S_cas_noMemory, "unable to create gdd for read of application type \"enums\" string" " conversion table for enumerated PV" ); return S_cas_noMemory; @@ -156,8 +161,8 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn ) gddAppType_enums, MAX_ENUM_STATES ); if ( status != S_cas_success ) { pTmp->unreference (); - errMessage ( status, - "unable to to config gdd for read of application type \"enums\" string" + casErrMessage ( status, + "unable to config gdd for read of application type \"enums\" string" " conversion table for enumerated PV"); return status; } @@ -187,9 +192,9 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) epicsGuard < epicsMutex > guard ( this->mutex ); if ( resp.isContainer() ) { - errMessage ( S_cas_badType, - "application type \"enums\" string conversion table for" - " enumerated PV was a container (expected vector of strings)" ); + casErrMessage ( S_cas_badType, + "Invalid \"enums\" string conversion table for" + " enumerated PV (container instead of vector of strings)" ); return; } @@ -197,14 +202,14 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) if ( resp.primitiveType() == aitEnumString ) { aitString *pStr = (aitString *) resp.dataVoid (); if ( ! this->enumStrTbl.setString ( 0, pStr->string() ) ) { - errMessage ( S_cas_noMemory, + casErrMessage ( S_cas_noMemory, "no memory to set enumerated PV string cache" ); } } else if ( resp.primitiveType() == aitEnumFixedString ) { aitFixedString *pStr = (aitFixedString *) resp.dataVoid (); if ( ! this->enumStrTbl.setString ( 0, pStr->fixed_string ) ) { - errMessage ( S_cas_noMemory, + casErrMessage ( S_cas_noMemory, "no memory to set enumerated PV string cache" ); } } @@ -232,7 +237,7 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) aitString *pStr = (aitString *) resp.dataVoid (); for ( index = 0; indexenumStrTbl.setString ( index, pStr[index].string() ) ) { - errMessage ( S_cas_noMemory, + casErrMessage ( S_cas_noMemory, "no memory to set enumerated PV string cache" ); } } @@ -241,19 +246,18 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) aitFixedString *pStr = (aitFixedString *) resp.dataVoid (); for ( index = 0; index < count; index++ ) { if ( ! this->enumStrTbl.setString ( index, pStr[index].fixed_string ) ) { - errMessage ( S_cas_noMemory, + casErrMessage ( S_cas_noMemory, "no memory to set enumerated PV string cache" ); } } } else { - errMessage ( S_cas_badType, - "application type \"enums\" string conversion" - " table for enumerated PV isnt a string type?" ); + casErrMessage( S_cas_badType, + "bad \"enums\" string conversion table for enumerated PV" ); } } else { - errMessage ( S_cas_badType, + casErrMessage ( S_cas_badType, "application type \"enums\" string conversion table" " for enumerated PV was multi-dimensional" " (expected vector of strings)" ); From b9443f8813e29a764b517e1f5f329ae952c9cd07 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 23 Mar 2018 11:39:53 -0500 Subject: [PATCH 15/46] Tell MSVC to use absolute filenames in diagnostics (-FC flag) --- configure/os/CONFIG.win32-x86.win32-x86 | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86 index f5b21cc2e..54a0ec954 100644 --- a/configure/os/CONFIG.win32-x86.win32-x86 +++ b/configure/os/CONFIG.win32-x86.win32-x86 @@ -85,16 +85,20 @@ CPP = cl -nologo -C -E # Configure OS vendor C++ compiler # -# __STDC__=0 gives us both: -# 1) define STDC for code (pretend ANSI conformance) -# 2) set it to 0 to use MS C "extensions" (open for _open etc.) -# because MS uses: if __STDC__ ... disable many nice things -# # -EHsc - generate code for exceptions # -GR - generate code for run time type identification # CCC = cl -EHsc -GR -CODE_CPPFLAGS += -nologo -D__STDC__=0 + +# Other compiler flags, used for CPP, C and C++ +# +# -FC - Show absolute path of source file in diagnostics +# -D__STDC__=0 gives us both: +# 1) define STDC for code (pretend ANSI conformance) +# 2) set it to 0 to use MS C "extensions" (open for _open etc.) +# because MS uses: if __STDC__ ... disable many nice things +# +CODE_CPPFLAGS += -nologo -FC -D__STDC__=0 CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE From 91ce807e8beedc3d6449cee4209ae1b14d4d0be1 Mon Sep 17 00:00:00 2001 From: Benjamin Franksen Date: Wed, 11 Apr 2018 12:58:28 +0200 Subject: [PATCH 16/46] Fix for lp: #1751380 Add warnings about possible deadlock to the docs for ca_clear_channel, ca_clear_subscription, and ca_context_destroy. --- src/ca/CAref.html | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/ca/CAref.html b/src/ca/CAref.html index 13bcd795f..0651b2c26 100644 --- a/src/ca/CAref.html +++ b/src/ca/CAref.html @@ -2674,6 +2674,14 @@ automatically released by the system when the process exits and vxWorks or RTEMS no cleanup occurs unless the application calls ca_context_destroy().

+

Note: This operation blocks until any user callbacks for any channel +created in the current context have run to completion. If callbacks take a +lock (mutex) then it is the user's responsibility to ensure that this lock +is not held when ca_clear_context() is called, otherwise a +deadlock may ensue. (See also ca_clear_channel() and ca_clear_subscription().)

+

Returns

ECA_NORMAL - Normal successful completion

@@ -2819,6 +2827,12 @@ efficiently sent over the network in one message.

clearing a channel does shutdown and reclaim any channel state change event subscriptions (monitors) registered with the channel.

+

Note: This operation blocks until any user callbacks for this channel +have run to completion. If callbacks take a lock (mutex) then it is the +user's responsibility to ensure that this lock is not held when +ca_clear_channel() is called, otherwise a deadlock may ensue. +(See also ca_clear_subscription().)

+

Arguments

CHID
@@ -3200,6 +3214,13 @@ and not forwarded to the server until one of ca_flush_io(), c ca_pend_event(), or ca_sg_block() are called. This allows several requests to be efficiently sent together in one message.

+

Note: This operation blocks until any user callbacks for this channel +have run to completion. If callbacks take a lock (mutex) then it is the +user's responsibility to ensure that this lock is not held when +ca_clear_subscription() is called, otherwise a deadlock may +ensue. (See also ca_clear_channel().)

+

Arguments

EVID
From b8a0792fae7acbd31d6c93d0c79849e310b44bcc Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 13 Apr 2018 10:47:59 -0500 Subject: [PATCH 17/46] Update documentation/README files --- documentation/README.1st | 28 +++++++++++++--------------- documentation/README.html | 30 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/documentation/README.1st b/documentation/README.1st index 4886bea7c..8166b1434 100644 --- a/documentation/README.1st +++ b/documentation/README.1st @@ -67,8 +67,9 @@ Software requirements GNU make - You must use GNU make, gnumake, for any EPICS builds. Set your path so - that a gnumake version 3.81 or later is available. + You must use the GNU version of make for EPICS builds, and we now + recommend version 4.1 or later (version 3.82 may work on Linux, but + doesn't on Windows). Perl You must have Perl version 5.8.1 or later installed. The EPICS @@ -99,20 +100,17 @@ RTEMS For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or - later. + 4.10. The newer 4.11 or 5.x releases are not supported yet. - GNU readline or Tecla library - GNU readline and Tecla libraries can be used by the IOC shell to provide - command line editing and command line history recall and edit. GNU - readline (or Tecla library) must be installed on your target system when - COMMANDLINE_LIBRARY is set to READLINE (or TECLA) for that target. EPICS - (EPICS shell) is the default specified in CONFIG_COMMON. A READLINE - override is defined for linux-x86 in the EPICS distribution. Comment out - COMMANDLINE_LIBRARY=READLINE in - configure/os/CONFIG_SITE.Common.linux-x86 if readline is not installed - on linux-x86. Command-line editing and history will then be those - supplied by the os. On vxWorks the ledLib command-line input library is - used instead. + Command-line editing libraries + GNU readline or other OS-specific libraries can be used by the IOC shell + to provide command line editing and history recall. The default setting + is different for each OS. On Linux the default is to use READLINE since + most distributions include it. On MacOS the default is also READLINE + since Apple provides a compatible library, although it isn't GNU. On + RTEMS we support GNU readline and Tecla, although the default is to use + neither since these have to be added to the RTEMS installation + separately. On vxWorks we support the built-in ledLib library. Host system storage requirements diff --git a/documentation/README.html b/documentation/README.html index 868043718..d1e2be299 100644 --- a/documentation/README.html +++ b/documentation/README.html @@ -72,8 +72,8 @@

Software requirements

GNU make
- You must use GNU make, gnumake, for any EPICS builds. Set your path - so that a gnumake version 3.81 or later is available. + You must use the GNU version of make for EPICS builds, and we now recommend + version 4.1 or later (version 3.82 may work on Linux, but doesn't on Windows).

Perl
You must have Perl version 5.8.1 or later installed. The EPICS configuration @@ -103,20 +103,20 @@ about configuring your vxWorks operating system for use with EPICS.

RTEMS
- For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or later.

+ For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or 4.10. The + newer 4.11 or 5.x releases are not supported yet.

+ +

Command-line editing libraries
+ + GNU readline or other OS-specific libraries can be used by the IOC shell to + provide command line editing and history recall. The default setting is + different for each OS. On Linux the default is to use READLINE since most + distributions include it. On MacOS the default is also READLINE since Apple + provides a compatible library, although it isn't GNU. On RTEMS we support GNU + readline and Tecla, although the default is to use neither since these have to + be added to the RTEMS installation separately. On vxWorks we support the + built-in ledLib library.

-

GNU readline or Tecla library
- GNU readline and Tecla libraries can be used by the IOC shell to - provide command line editing and command line history recall and edit. - GNU readline (or Tecla library) must be installed on your target system - when COMMANDLINE_LIBRARY is set to READLINE (or TECLA) for that target. - EPICS (EPICS shell) is the default specified in CONFIG_COMMON. A - READLINE override is defined for linux-x86 in the EPICS distribution. - Comment out COMMANDLINE_LIBRARY=READLINE in - configure/os/CONFIG_SITE.Common.linux-x86 if readline is not installed - on linux-x86. Command-line editing and history will then be those - supplied by the os. On vxWorks the ledLib command-line input library is - used instead.

Host system storage requirements

From 92f0f65d2c9cb7f344b383327be5aa3c6964a256 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 30 Apr 2018 13:37:57 -0500 Subject: [PATCH 18/46] Adjust old INT64 Release Notes entry for db_access users --- documentation/RELEASE_NOTES.html | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index f5936bcc2..d3a03bf4c 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -107,6 +107,27 @@ preprocessor macro):

#endif +

If the code uses the old db_access.h types (probably because it's calling +Channel Access APIs) then it will have to test against the EPICS version number +instead, like this:

+ +
+#include <epicsVersion.h>
+
+#ifndef VERSION_INT
+#  define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
+#endif
+#ifndef EPICS_VERSION_INT
+#  define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
+#endif
+
+#if EPICS_VERSION_INT >= VERSION_INT(3,16,1,0)
+    /* Code where Base has INT64 support */
+#else
+    /* Code for older versions */
+#endif
+
+

Channel Access does not (and probably never will) directly support 64-bit integer types, so the new field types are presented to the CA server as DBF_DOUBLE values. This means that field values larger than 2^52 From 57eea6a153bb3501d35e636496afafd32fac9979 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 2 May 2018 01:09:46 -0500 Subject: [PATCH 19/46] Add INT64 support to the printf record type Use the 'll' modifier to fetch and print 64-bit integer data. Also now rejects mixing of the 'l' and 'h' modifiers. --- src/std/rec/printfRecord.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/std/rec/printfRecord.c b/src/std/rec/printfRecord.c index 7011453d4..576b9632a 100644 --- a/src/std/rec/printfRecord.c +++ b/src/std/rec/printfRecord.c @@ -34,12 +34,13 @@ /* Flag bits */ -#define F_CHAR 1 -#define F_SHORT 2 -#define F_LONG 4 -#define F_LEFT 8 -#define F_BADFMT 0x10 -#define F_BADLNK 0x20 +#define F_CHAR 1 +#define F_SHORT 2 +#define F_LONG 4 +#define F_LONGLONG 8 +#define F_LEFT 0x10 +#define F_BADFMT 0x40 +#define F_BADLNK 0x80 #define F_BAD (F_BADFMT | F_BADLNK) #define GET_PRINT(VALTYPE, DBRTYPE) \ @@ -129,13 +130,20 @@ static void doPrintf(printfRecord *prec) flags |= F_BADLNK; break; case 'h': - if (flags & F_SHORT) + if (flags & (F_LONGLONG | F_LONG | F_CHAR)) + flags |= F_BADFMT; + else if (flags & F_SHORT) flags = (flags & ~F_SHORT) | F_CHAR; else flags |= F_SHORT; break; case 'l': - flags |= F_LONG; + if (flags & (F_LONGLONG | F_SHORT | F_CHAR)) + flags |= F_BADFMT; + else if (flags & F_LONG) + flags = (flags & ~F_LONG) | F_LONGLONG; + else + flags |= F_LONG; break; default: if (strchr("diouxXeEfFgGcs%", ch) == NULL) @@ -175,6 +183,9 @@ static void doPrintf(printfRecord *prec) else if (flags & F_SHORT) { GET_PRINT(epicsInt16, DBR_SHORT); } + else if (flags & F_LONGLONG) { + GET_PRINT(epicsInt64, DBR_INT64); + } else { /* F_LONG has no real effect */ GET_PRINT(epicsInt32, DBR_LONG); } @@ -187,6 +198,9 @@ static void doPrintf(printfRecord *prec) else if (flags & F_SHORT) { GET_PRINT(epicsUInt16, DBR_USHORT); } + else if (flags & F_LONGLONG) { + GET_PRINT(epicsUInt64, DBR_UINT64); + } else { /* F_LONG has no real effect */ GET_PRINT(epicsUInt32, DBR_ULONG); } From 3f3696fb91e31ca654b1b472190297a8451364ae Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 3 May 2018 14:28:44 -0500 Subject: [PATCH 20/46] dbStatic: Prevent modifying a NAME field using a DB file Fixes LP: #1597809 --- src/dbStatic/dbLexRoutines.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c index db95cc61f..87bb7295f 100644 --- a/src/dbStatic/dbLexRoutines.c +++ b/src/dbStatic/dbLexRoutines.c @@ -974,6 +974,12 @@ static void dbRecordField(char *name,char *value) yyerror(NULL); return; } + if (pdbentry->indfield == 0) { + epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n", + dbGetRecordName(pdbentry)); + yyerror(NULL); + return; + } dbTranslateEscape(value, value); /* yuck: in-place, but safe */ status = dbPutString(pdbentry,value); if(status) { From 116c90c2ea1e3e542ee5d0d42349a64b1f4097b1 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 3 May 2018 14:40:12 -0500 Subject: [PATCH 21/46] Reformatting, no code changes --- src/dbStatic/dbLexRoutines.c | 67 ++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c index 87bb7295f..91437b342 100644 --- a/src/dbStatic/dbLexRoutines.c +++ b/src/dbStatic/dbLexRoutines.c @@ -960,29 +960,29 @@ static void dbRecordHead(char *recordType, char *name, int visible) static void dbRecordField(char *name,char *value) { - DBENTRY *pdbentry; - tempListNode *ptempListNode; - long status; + DBENTRY *pdbentry; + tempListNode *ptempListNode; + long status; - if(duplicate) return; + if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbFindField(pdbentry,name); - if(status) { - epicsPrintf("Record \"%s\" does not have a field \"%s\"\n", - dbGetRecordName(pdbentry), name); - yyerror(NULL); - return; + if (status) { + epicsPrintf("Record \"%s\" does not have a field \"%s\"\n", + dbGetRecordName(pdbentry), name); + yyerror(NULL); + return; } if (pdbentry->indfield == 0) { epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n", - dbGetRecordName(pdbentry)); + dbGetRecordName(pdbentry)); yyerror(NULL); return; } dbTranslateEscape(value, value); /* yuck: in-place, but safe */ status = dbPutString(pdbentry,value); - if(status) { + if (status) { epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n", dbGetRecordName(pdbentry), name, value); yyerror(NULL); @@ -992,33 +992,33 @@ static void dbRecordField(char *name,char *value) static void dbRecordInfo(char *name, char *value) { - DBENTRY *pdbentry; - tempListNode *ptempListNode; - long status; + DBENTRY *pdbentry; + tempListNode *ptempListNode; + long status; - if(duplicate) return; + if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbPutInfo(pdbentry,name,value); - if(status) { - epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n", + if (status) { + epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n", dbGetRecordName(pdbentry), name, value); - yyerror(NULL); - return; + yyerror(NULL); + return; } } static void dbRecordAlias(char *name) { - DBENTRY *pdbentry; - tempListNode *ptempListNode; - long status; + DBENTRY *pdbentry; + tempListNode *ptempListNode; + long status; - if(duplicate) return; + if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbCreateAlias(pdbentry, name); - if(status) { + if (status) { epicsPrintf("Can't create alias \"%s\" for \"%s\"\n", name, dbGetRecordName(pdbentry)); yyerror(NULL); @@ -1028,15 +1028,16 @@ static void dbRecordAlias(char *name) static void dbAlias(char *name, char *alias) { - DBENTRY dbEntry; - DBENTRY *pdbEntry = &dbEntry; + DBENTRY dbEntry; + DBENTRY *pdbEntry = &dbEntry; dbInitEntry(pdbbase, pdbEntry); if (dbFindRecord(pdbEntry, name)) { epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n", alias, name); yyerror(NULL); - } else if (dbCreateAlias(pdbEntry, alias)) { + } + else if (dbCreateAlias(pdbEntry, alias)) { epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n", alias, name); yyerror(NULL); @@ -1046,14 +1047,14 @@ static void dbAlias(char *name, char *alias) static void dbRecordBody(void) { - DBENTRY *pdbentry; + DBENTRY *pdbentry; - if(duplicate) { - duplicate = FALSE; - return; + if (duplicate) { + duplicate = FALSE; + return; } pdbentry = (DBENTRY *)popFirstTemp(); - if(ellCount(&tempList)) - yyerrorAbort("dbRecordBody: tempList not empty"); + if (ellCount(&tempList)) + yyerrorAbort("dbRecordBody: tempList not empty"); dbFreeEntry(pdbentry); } From 49371cfe006b71bf43bc44c0c4a5289c1b0770ef Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 12 May 2018 22:25:15 -0500 Subject: [PATCH 22/46] Fix RTEMS build in src/std/rec/test Also back-ported Michael's change from commit b9b8cde5f6a to avoid using callocMustSucceed() in eventNameToHandle() --- src/ioc/db/dbScan.c | 10 ++++++---- src/std/rec/test/Makefile | 4 +++- src/std/rec/test/epicsRunRecordTests.c | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index e9dc178a2..311297441 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -6,7 +6,7 @@ * Copyright (c) 2013 Helmholtz-Zentrum Berlin * für Materialien und Energie GmbH. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* dbScan.c */ /* tasks and subroutines to scan the database */ @@ -502,9 +502,10 @@ event_list *eventNameToHandle(const char *eventname) break; } if (pel == NULL) { - pel = dbCalloc(1, sizeof(event_list) + namelength); - if (eventnumber > 0) - { + pel = calloc(1, sizeof(event_list) + namelength); + if (!pel) + goto done; + if (eventnumber > 0) { /* backward compatibility: make all numeric events look like integers */ sprintf(pel->eventname, "%i", (int)eventnumber); pevent_list[(int)eventnumber] = pel; @@ -521,6 +522,7 @@ event_list *eventNameToHandle(const char *eventname) pel->next=pevent_list[0]; pevent_list[0]=pel; } +done: epicsMutexUnlock(event_lock); return pel; } diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index 70b6e173e..9a7e58320 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -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 the file LICENSE that is included with this distribution. +# in the file LICENSE that is included with this distribution. #************************************************************************* TOP=../../../.. @@ -43,6 +43,8 @@ scanEventTest_DBD += base.dbd TESTPROD_HOST += scanEventTest scanEventTest_SRCS += scanEventTest.c scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp +testHarness_SRCS += scanEventTest.c +testHarness_SRCS += scanEventTest_registerRecordDeviceDriver.cpp TESTFILES += $(COMMON_DIR)/scanEventTest.dbd ../scanEventTest.db TESTS += scanEventTest diff --git a/src/std/rec/test/epicsRunRecordTests.c b/src/std/rec/test/epicsRunRecordTests.c index 1a7133c19..b3ee4dd85 100644 --- a/src/std/rec/test/epicsRunRecordTests.c +++ b/src/std/rec/test/epicsRunRecordTests.c @@ -23,6 +23,7 @@ void epicsRunRecordTests(void) runTest(analogMonitorTest); runTest(arrayOpTest); + runTest(scanEventTest); epicsExit(0); /* Trigger test harness */ From 490c50473690b2b8004d00e3c3ad774cc776ad29 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 10 May 2018 09:26:01 -0400 Subject: [PATCH 23/46] scanEventTest: use dbUnitTest.h for IOC lifecycle --- src/std/rec/test/scanEventTest.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/std/rec/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c index 77acbbeca..971820850 100644 --- a/src/std/rec/test/scanEventTest.c +++ b/src/std/rec/test/scanEventTest.c @@ -65,21 +65,18 @@ MAIN(scanEventTest) testPlan(NELEMENTS(events)*2+(MAXEV+1)*5); + testdbPrepare(); + memset(aliases, 0, sizeof(aliases)); memset(expected_count, 0, sizeof(expected_count)); - if (dbReadDatabase(&pdbbase, "scanEventTest.dbd", - "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR - "../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL)) - testAbort("Database description 'scanEventTest.dbd' not found"); + testdbReadDatabase("scanEventTest.dbd", NULL, NULL); scanEventTest_registerRecordDeviceDriver(pdbbase); for (i = 0; i < NELEMENTS(events); i++) { char substitutions[256]; sprintf(substitutions, "N=%d,EVENT=%s", i, events[i].name); - if (dbReadDatabase(&pdbbase, "scanEventTest.db", - "." OSI_PATH_LIST_SEPARATOR "..", substitutions)) - testAbort("Error reading test database 'scanEventTest.db'"); + testdbReadDatabase("scanEventTest.db", NULL, substitutions); } testIocInitOk(); testDiag("Test if eventNameToHandle() strips spaces and handles numeric events"); @@ -138,5 +135,9 @@ MAIN(scanEventTest) testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]); } + testIocShutdownOk(); + + testdbCleanup(); + return testDone(); } From 00a974ce528277de9a95987cfda538ff18e38d8c Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 14 May 2018 09:56:26 -0700 Subject: [PATCH 24/46] callback.h: add epicsCallback alternative to CALLBACK Add epicsCallback as an IDE friendly alternative to CALLBACK. IDEs like qtcreator have long been confused by the use of CALLBACK, a name which has long been used by other libraries, which prevents code using it from being parsed correctly. --- src/ioc/db/callback.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ioc/db/callback.h b/src/ioc/db/callback.h index 34224f475..9011446dc 100644 --- a/src/ioc/db/callback.h +++ b/src/ioc/db/callback.h @@ -42,7 +42,9 @@ typedef struct callbackPvt { int priority; void *user; /*for use by callback user*/ void *timer; /*for use by callback itself*/ -}CALLBACK; +}epicsCallback; + +typedef epicsCallback CALLBACK; typedef void (*CALLBACKFUNC)(struct callbackPvt*); From 3b7e348a8c7f01d8a7a17a2f604819c65f89cc3c Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 14 May 2018 10:35:16 -0700 Subject: [PATCH 25/46] dbUnitTest.h add callback sync. and global mutex Add testSyncCallback() to wait for in queued and in-progress callbacks to complete. Also add testGlobalLock() to help tests avoid use after free when destroying sync. primitives. --- src/ioc/db/callback.c | 84 +++++++++++++++++++++++++++++++++++++++++ src/ioc/db/dbUnitTest.c | 24 ++++++++++++ src/ioc/db/dbUnitTest.h | 59 +++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) diff --git a/src/ioc/db/callback.c b/src/ioc/db/callback.c index 903ca3f43..b805c1c16 100644 --- a/src/ioc/db/callback.c +++ b/src/ioc/db/callback.c @@ -46,6 +46,7 @@ #include "epicsExport.h" #include "link.h" #include "recSup.h" +#include "dbUnitTest.h" /* for testSyncCallback() */ static int callbackQueueSize = 2000; @@ -353,3 +354,86 @@ void callbackRequestProcessCallbackDelayed(CALLBACK *pcallback, callbackSetProcess(pcallback, Priority, pRec); callbackRequestDelayed(pcallback, seconds); } + +/* Sync. process of testSyncCallback() + * + * 1. For each priority, make a call to callbackRequest() for each worker. + * 2. Wait until all callbacks are concurrently being executed + * 3. Last worker to begin executing signals success and begins waking up other workers + * 4. Last worker to wake signals testSyncCallback() to complete + */ +typedef struct { + epicsEventId wait_phase2, wait_phase4; + int nphase2, nphase3; + epicsCallback cb; +} sync_helper; + +static void sync_callback(epicsCallback *cb) +{ + sync_helper *helper; + callbackGetUser(helper, cb); + + testGlobalLock(); + + assert(helper->nphase2 > 0); + if(--helper->nphase2!=0) { + /* we are _not_ the last to start. */ + testGlobalUnlock(); + epicsEventMustWait(helper->wait_phase2); + testGlobalLock(); + } + + /* we are either the last to start, or have been + * woken by the same and must pass the wakeup along + */ + epicsEventMustTrigger(helper->wait_phase2); + + assert(helper->nphase2 == 0); + assert(helper->nphase3 > 0); + + if(--helper->nphase3==0) { + /* we are the last to wake up. wake up testSyncCallback() */ + epicsEventMustTrigger(helper->wait_phase4); + } + + testGlobalUnlock(); +} + +void testSyncCallback(void) +{ + sync_helper helper[NUM_CALLBACK_PRIORITIES]; + unsigned i; + + testDiag("Begin testSyncCallback()"); + + for(i=0; i Date: Mon, 14 May 2018 10:40:01 -0700 Subject: [PATCH 26/46] scanEventTest: use testSyncCallback() --- src/std/rec/test/scanEventTest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/std/rec/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c index 971820850..6b90a413b 100644 --- a/src/std/rec/test/scanEventTest.c +++ b/src/std/rec/test/scanEventTest.c @@ -126,7 +126,7 @@ MAIN(scanEventTest) } } /* Allow records to finish processing */ - epicsThreadSleep(0.1); + testSyncCallback(); testDiag("Check if events have been processed the expected number of times"); for (i = 0; i < NELEMENTS(events); i++) { char pvname[100]; From ca22d508312b823b3d686206ea8d16cdda2c1c11 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 10 May 2018 10:39:11 -0400 Subject: [PATCH 27/46] rec: consistent get_alarm_double() for longin/longout (fixes lp #1770292) --- src/rec/longinRecord.c | 8 ++++---- src/rec/longoutRecord.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rec/longinRecord.c b/src/rec/longinRecord.c index 58d9ccfbf..12da09c60 100644 --- a/src/rec/longinRecord.c +++ b/src/rec/longinRecord.c @@ -201,10 +201,10 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad) longinRecord *prec=(longinRecord *)paddr->precord; if(paddr->pfield==(void *)&prec->val){ - pad->upper_alarm_limit = prec->hihi; - pad->upper_warning_limit = prec->high; - pad->lower_warning_limit = prec->low; - pad->lower_alarm_limit = prec->lolo; + pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN; + pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN; + pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN; + pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN; } else recGblGetAlarmDouble(paddr,pad); return(0); } diff --git a/src/rec/longoutRecord.c b/src/rec/longoutRecord.c index a57d52829..c6ba45a4c 100644 --- a/src/rec/longoutRecord.c +++ b/src/rec/longoutRecord.c @@ -242,10 +242,10 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad) int fieldIndex = dbGetFieldIndex(paddr); if(fieldIndex == longoutRecordVAL) { - pad->upper_alarm_limit = prec->hihi; - pad->upper_warning_limit = prec->high; - pad->lower_warning_limit = prec->low; - pad->lower_alarm_limit = prec->lolo; + pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN; + pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN; + pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN; + pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN; } else recGblGetAlarmDouble(paddr,pad); return(0); } From 2d9c5e99a191f15ca7d20a8546be922057eb9598 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 15 May 2018 11:17:49 +0200 Subject: [PATCH 28/46] db: correctly convert NaN alarm levels to integers (fixes lp #1771298) --- src/db/dbAccess.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c index ef27afafb..b60594fed 100644 --- a/src/db/dbAccess.c +++ b/src/db/dbAccess.c @@ -297,10 +297,10 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer, if (*options & DBR_AL_LONG) { struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer; - pal->upper_alarm_limit = (epicsInt32) ald.upper_alarm_limit; - pal->upper_warning_limit = (epicsInt32) ald.upper_warning_limit; - pal->lower_warning_limit = (epicsInt32) ald.lower_warning_limit; - pal->lower_alarm_limit = (epicsInt32) ald.lower_alarm_limit; + pal->upper_alarm_limit = isfinite(ald.upper_alarm_limit) ? (epicsInt32) ald.upper_alarm_limit : 0; + pal->upper_warning_limit = isfinite(ald.upper_warning_limit) ? (epicsInt32) ald.upper_warning_limit : 0; + pal->lower_warning_limit = isfinite(ald.lower_warning_limit) ? (epicsInt32) ald.lower_warning_limit : 0; + pal->lower_alarm_limit = isfinite(ald.lower_alarm_limit) ? (epicsInt32) ald.lower_alarm_limit : 0; if (no_data) *options ^= DBR_AL_LONG; /*Turn off option*/ From 6ff271527bdd9887dc01741ca1735d660093550c Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 7 Sep 2017 10:30:32 +0200 Subject: [PATCH 29/46] std/rec: fix typo in mbboDirect promptgroup --- src/std/rec/mbboDirectRecord.dbd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/std/rec/mbboDirectRecord.dbd b/src/std/rec/mbboDirectRecord.dbd index 0b4285e32..0c816ad6b 100644 --- a/src/std/rec/mbboDirectRecord.dbd +++ b/src/std/rec/mbboDirectRecord.dbd @@ -96,56 +96,56 @@ recordtype(mbboDirect) { } field(B8,DBF_UCHAR) { prompt("Bit 8") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(B9,DBF_UCHAR) { prompt("Bit 9") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(BA,DBF_UCHAR) { prompt("Bit 10") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(BB,DBF_UCHAR) { prompt("Bit 11") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(BC,DBF_UCHAR) { prompt("Bit 12") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(BD,DBF_UCHAR) { prompt("Bit 13") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(BE,DBF_UCHAR) { prompt("Bit 14") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) } field(BF,DBF_UCHAR) { prompt("Bit 15") - promptgroup("52 - Output 9-F") + promptgroup("52 - Output 8-F") special(SPC_MOD) pp(TRUE) interest(1) From 4df39bb425454247f0eef1f62e7642a6a00a42da Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 7 Sep 2017 10:33:11 +0200 Subject: [PATCH 30/46] std/rec: make mbbiDirect prompts consistent with mbboDirect --- src/std/rec/mbbiDirectRecord.dbd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/std/rec/mbbiDirectRecord.dbd b/src/std/rec/mbbiDirectRecord.dbd index 3fa3d8823..c4edcfd4e 100644 --- a/src/std/rec/mbbiDirectRecord.dbd +++ b/src/std/rec/mbbiDirectRecord.dbd @@ -124,32 +124,32 @@ recordtype(mbbiDirect) { interest(1) } field(BA,DBF_UCHAR) { - prompt("Bit A") + prompt("Bit 10") pp(TRUE) interest(1) } field(BB,DBF_UCHAR) { - prompt("Bit B") + prompt("Bit 11") pp(TRUE) interest(1) } field(BC,DBF_UCHAR) { - prompt("Bit C") + prompt("Bit 12") pp(TRUE) interest(1) } field(BD,DBF_UCHAR) { - prompt("Bit D") + prompt("Bit 13") pp(TRUE) interest(1) } field(BE,DBF_UCHAR) { - prompt("Bit E") + prompt("Bit 14") pp(TRUE) interest(1) } field(BF,DBF_UCHAR) { - prompt("Bit F") + prompt("Bit 15") pp(TRUE) interest(1) } From ab517a9392e088c1b2b8db38cafad7f65e938030 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 7 Sep 2017 10:34:12 +0200 Subject: [PATCH 31/46] std/rec: move mbboDirect bits to end (as mbbiDirect) --- src/std/rec/mbboDirectRecord.dbd | 132 +++++++++++++++---------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/std/rec/mbboDirectRecord.dbd b/src/std/rec/mbboDirectRecord.dbd index 0c816ad6b..db6cc95f3 100644 --- a/src/std/rec/mbboDirectRecord.dbd +++ b/src/std/rec/mbboDirectRecord.dbd @@ -38,6 +38,72 @@ recordtype(mbboDirect) { promptgroup("50 - Output") interest(1) } + field(RVAL,DBF_ULONG) { + prompt("Raw Value") + special(SPC_NOMOD) + pp(TRUE) + } + field(ORAW,DBF_ULONG) { + prompt("Prev Raw Value") + special(SPC_NOMOD) + interest(3) + } + field(RBV,DBF_ULONG) { + prompt("Readback Value") + special(SPC_NOMOD) + } + field(ORBV,DBF_ULONG) { + prompt("Prev Readback Value") + special(SPC_NOMOD) + interest(3) + } + field(MASK,DBF_ULONG) { + prompt("Hardware Mask") + special(SPC_NOMOD) + interest(1) + } + field(MLST,DBF_ULONG) { + prompt("Last Value Monitored") + special(SPC_NOMOD) + interest(3) + } + field(SHFT,DBF_ULONG) { + prompt("Shift") + promptgroup("50 - Output") + interest(1) + } + field(SIOL,DBF_OUTLINK) { + prompt("Sim Output Specifctn") + promptgroup("90 - Simulate") + interest(1) + } + field(SIML,DBF_INLINK) { + prompt("Sim Mode Location") + promptgroup("90 - Simulate") + interest(1) + } + field(SIMM,DBF_MENU) { + prompt("Simulation Mode") + interest(1) + menu(menuYesNo) + } + field(SIMS,DBF_MENU) { + prompt("Sim mode Alarm Svrty") + promptgroup("90 - Simulate") + interest(2) + menu(menuAlarmSevr) + } + field(IVOA,DBF_MENU) { + prompt("INVALID outpt action") + promptgroup("50 - Output") + interest(2) + menu(menuIvoa) + } + field(IVOV,DBF_USHORT) { + prompt("INVALID output value") + promptgroup("50 - Output") + interest(2) + } field(B0,DBF_UCHAR) { prompt("Bit 0") promptgroup("51 - Output 0-7") @@ -150,70 +216,4 @@ recordtype(mbboDirect) { pp(TRUE) interest(1) } - field(RVAL,DBF_ULONG) { - prompt("Raw Value") - special(SPC_NOMOD) - pp(TRUE) - } - field(ORAW,DBF_ULONG) { - prompt("Prev Raw Value") - special(SPC_NOMOD) - interest(3) - } - field(RBV,DBF_ULONG) { - prompt("Readback Value") - special(SPC_NOMOD) - } - field(ORBV,DBF_ULONG) { - prompt("Prev Readback Value") - special(SPC_NOMOD) - interest(3) - } - field(MASK,DBF_ULONG) { - prompt("Hardware Mask") - special(SPC_NOMOD) - interest(1) - } - field(MLST,DBF_ULONG) { - prompt("Last Value Monitored") - special(SPC_NOMOD) - interest(3) - } - field(SHFT,DBF_ULONG) { - prompt("Shift") - promptgroup("50 - Output") - interest(1) - } - field(SIOL,DBF_OUTLINK) { - prompt("Sim Output Specifctn") - promptgroup("90 - Simulate") - interest(1) - } - field(SIML,DBF_INLINK) { - prompt("Sim Mode Location") - promptgroup("90 - Simulate") - interest(1) - } - field(SIMM,DBF_MENU) { - prompt("Simulation Mode") - interest(1) - menu(menuYesNo) - } - field(SIMS,DBF_MENU) { - prompt("Sim mode Alarm Svrty") - promptgroup("90 - Simulate") - interest(2) - menu(menuAlarmSevr) - } - field(IVOA,DBF_MENU) { - prompt("INVALID outpt action") - promptgroup("50 - Output") - interest(2) - menu(menuIvoa) - } - field(IVOV,DBF_USHORT) { - prompt("INVALID output value") - promptgroup("50 - Output") - interest(2) - } } From 7aa2ae20941b36fd6828a2d9da98e04ae3c85eb8 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 7 Sep 2017 10:35:09 +0200 Subject: [PATCH 32/46] std/rec: make SHFT field of mbboDirect USHRT (as mbbiDirect) --- src/std/rec/mbboDirectRecord.dbd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/std/rec/mbboDirectRecord.dbd b/src/std/rec/mbboDirectRecord.dbd index db6cc95f3..ad57dc02c 100644 --- a/src/std/rec/mbboDirectRecord.dbd +++ b/src/std/rec/mbboDirectRecord.dbd @@ -67,7 +67,7 @@ recordtype(mbboDirect) { special(SPC_NOMOD) interest(3) } - field(SHFT,DBF_ULONG) { + field(SHFT,DBF_USHORT) { prompt("Shift") promptgroup("50 - Output") interest(1) From d9742d52409f14b3e8cca243efcaa58fb82a9790 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 7 Sep 2017 10:44:53 +0200 Subject: [PATCH 33/46] std/rec: make VAL (etc.) of mbbiDirect/mbboDirect LONG (not ULONG because of CA) --- src/std/rec/mbbiDirectRecord.c | 12 ++-- src/std/rec/mbbiDirectRecord.dbd | 86 +++++++++++++++++++++- src/std/rec/mbboDirectRecord.c | 28 ++++---- src/std/rec/mbboDirectRecord.dbd | 118 ++++++++++++++++++++++++++++++- 4 files changed, 218 insertions(+), 26 deletions(-) diff --git a/src/std/rec/mbbiDirectRecord.c b/src/std/rec/mbbiDirectRecord.c index 112272925..7e0c41828 100644 --- a/src/std/rec/mbbiDirectRecord.c +++ b/src/std/rec/mbbiDirectRecord.c @@ -9,7 +9,7 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* mbbiDirectRecord.c - Record Support routines for mbboDirect records */ +/* mbbiDirectRecord.c - Record Support routines for mbbiDirect records */ /* * Original Authors: Bob Dalesio and Matthew Needes * Date: 10-07-93 @@ -92,7 +92,7 @@ struct mbbidset { /* multi bit binary input dset */ static void monitor(mbbiDirectRecord *); static long readValue(mbbiDirectRecord *); -#define NUM_BITS 16 +#define NUM_BITS 32 static long init_record(struct dbCommon *pcommon, int pass) { @@ -114,7 +114,7 @@ static long init_record(struct dbCommon *pcommon, int pass) } recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm); - recGblInitConstantLink(&prec->siol, DBF_USHORT, &prec->sval); + recGblInitConstantLink(&prec->siol, DBF_ULONG, &prec->sval); /* Initialize MASK if the user set NOBT instead */ if (prec->mask == 0 && prec->nobt <= 32) @@ -123,11 +123,11 @@ static long init_record(struct dbCommon *pcommon, int pass) if (pdset->init_record) { status = pdset->init_record(prec); if (status == 0) { - epicsUInt16 val = prec->val; + epicsUInt32 val = prec->val; epicsUInt8 *pBn = &prec->b0; int i; - /* Initialize B0 - BF from VAL */ + /* Initialize B0 - B1F from VAL */ for (i = 0; i < NUM_BITS; i++, pBn++, val >>= 1) *pBn = !! (val & 1); } @@ -188,7 +188,7 @@ static void monitor(mbbiDirectRecord *prec) { epicsUInt16 events = recGblResetAlarms(prec); epicsUInt16 vl_events = events | DBE_VALUE | DBE_LOG; - epicsUInt16 val = prec->val; + epicsUInt32 val = prec->val; epicsUInt8 *pBn = &prec->b0; int i; diff --git a/src/std/rec/mbbiDirectRecord.dbd b/src/std/rec/mbbiDirectRecord.dbd index c4edcfd4e..0aa0cd496 100644 --- a/src/std/rec/mbbiDirectRecord.dbd +++ b/src/std/rec/mbbiDirectRecord.dbd @@ -8,7 +8,7 @@ #************************************************************************* recordtype(mbbiDirect) { include "dbCommon.dbd" - field(VAL,DBF_USHORT) { + field(VAL,DBF_LONG) { prompt("Current Value") promptgroup("40 - Input") asl(ASL0) @@ -39,7 +39,7 @@ recordtype(mbbiDirect) { special(SPC_NOMOD) interest(1) } - field(MLST,DBF_USHORT) { + field(MLST,DBF_LONG) { prompt("Last Value Monitored") special(SPC_NOMOD) interest(3) @@ -54,7 +54,7 @@ recordtype(mbbiDirect) { promptgroup("90 - Simulate") interest(1) } - field(SVAL,DBF_ULONG) { + field(SVAL,DBF_LONG) { prompt("Simulation Value") } field(SIML,DBF_INLINK) { @@ -153,4 +153,84 @@ recordtype(mbbiDirect) { pp(TRUE) interest(1) } + field(B10,DBF_UCHAR) { + prompt("Bit 16") + pp(TRUE) + interest(1) + } + field(B11,DBF_UCHAR) { + prompt("Bit 17") + pp(TRUE) + interest(1) + } + field(B12,DBF_UCHAR) { + prompt("Bit 18") + pp(TRUE) + interest(1) + } + field(B13,DBF_UCHAR) { + prompt("Bit 19") + pp(TRUE) + interest(1) + } + field(B14,DBF_UCHAR) { + prompt("Bit 20") + pp(TRUE) + interest(1) + } + field(B15,DBF_UCHAR) { + prompt("Bit 21") + pp(TRUE) + interest(1) + } + field(B16,DBF_UCHAR) { + prompt("Bit 22") + pp(TRUE) + interest(1) + } + field(B17,DBF_UCHAR) { + prompt("Bit 23") + pp(TRUE) + interest(1) + } + field(B18,DBF_UCHAR) { + prompt("Bit 24") + pp(TRUE) + interest(1) + } + field(B19,DBF_UCHAR) { + prompt("Bit 25") + pp(TRUE) + interest(1) + } + field(B1A,DBF_UCHAR) { + prompt("Bit 26") + pp(TRUE) + interest(1) + } + field(B1B,DBF_UCHAR) { + prompt("Bit 27") + pp(TRUE) + interest(1) + } + field(B1C,DBF_UCHAR) { + prompt("Bit 28") + pp(TRUE) + interest(1) + } + field(B1D,DBF_UCHAR) { + prompt("Bit 29") + pp(TRUE) + interest(1) + } + field(B1E,DBF_UCHAR) { + prompt("Bit 30") + pp(TRUE) + interest(1) + } + field(B1F,DBF_UCHAR) { + prompt("Bit 31") + pp(TRUE) + interest(1) + } } diff --git a/src/std/rec/mbboDirectRecord.c b/src/std/rec/mbboDirectRecord.c index 0a6e3391e..ff0747072 100644 --- a/src/std/rec/mbboDirectRecord.c +++ b/src/std/rec/mbboDirectRecord.c @@ -94,7 +94,7 @@ static void convert(mbboDirectRecord *); static void monitor(mbboDirectRecord *); static long writeValue(mbboDirectRecord *); -#define NUM_BITS 16 +#define NUM_BITS 32 static long init_record(struct dbCommon *pcommon, int pass) { @@ -116,7 +116,7 @@ static long init_record(struct dbCommon *pcommon, int pass) } recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm); - if (recGblInitConstantLink(&prec->dol, DBF_USHORT, &prec->val)) + if (recGblInitConstantLink(&prec->dol, DBF_ULONG, &prec->val)) prec->udf = FALSE; /* Initialize MASK if the user set NOBT instead */ @@ -141,8 +141,8 @@ static long init_record(struct dbCommon *pcommon, int pass) if (!prec->udf && prec->omsl == menuOmslsupervisory) { - /* Set initial B0 - BF from VAL */ - epicsUInt16 val = prec->val; + /* Set initial B0 - B1F from VAL */ + epicsUInt32 val = prec->val; epicsUInt8 *pBn = &prec->b0; int i; @@ -174,9 +174,9 @@ static long process(struct dbCommon *pcommon) if (!pact) { if (!dbLinkIsConstant(&prec->dol) && prec->omsl == menuOmslclosed_loop) { - epicsUInt16 val; + epicsUInt32 val; - if (dbGetLink(&prec->dol, DBR_USHORT, &val, 0, 0)) { + if (dbGetLink(&prec->dol, DBR_ULONG, &val, 0, 0)) { recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM); goto CONTINUE; } @@ -184,11 +184,11 @@ static long process(struct dbCommon *pcommon) } else if (prec->omsl == menuOmslsupervisory) { epicsUInt8 *pBn = &prec->b0; - epicsUInt16 val = 0; - epicsUInt16 bit = 1; + epicsUInt32 val = 0; + epicsUInt32 bit = 1; int i; - /* Construct VAL from B0 - BF */ + /* Construct VAL from B0 - B1F */ for (i = 0; i < NUM_BITS; i++, bit <<= 1) if (*pBn++) val |= bit; @@ -253,7 +253,7 @@ static long special(DBADDR *paddr, int after) if (prec->omsl == menuOmslsupervisory) { /* Adjust VAL corresponding to the bit changed */ epicsUInt8 *pBn = (epicsUInt8 *) paddr->pfield; - int bit = 1 << (pBn - &prec->b0); + epicsUInt32 bit = 1 << (pBn - &prec->b0); if (*pBn) prec->val |= bit; @@ -267,9 +267,9 @@ static long special(DBADDR *paddr, int after) case SPC_RESET: /* OMSL field modified */ if (prec->omsl == menuOmslclosed_loop) { - /* Construct VAL from B0 - BF */ + /* Construct VAL from B0 - B1F */ epicsUInt8 *pBn = &prec->b0; - epicsUInt16 val = 0, bit = 1; + epicsUInt32 val = 0, bit = 1; int i; for (i = 0; i < NUM_BITS; i++, bit <<= 1) @@ -278,8 +278,8 @@ static long special(DBADDR *paddr, int after) prec->val = val; } else if (prec->omsl == menuOmslsupervisory) { - /* Set B0 - BF from VAL and post monitors */ - epicsUInt16 val = prec->val; + /* Set B0 - B1F from VAL and post monitors */ + epicsUInt32 val = prec->val; epicsUInt8 *pBn = &prec->b0; int i; diff --git a/src/std/rec/mbboDirectRecord.dbd b/src/std/rec/mbboDirectRecord.dbd index ad57dc02c..08a5ff96c 100644 --- a/src/std/rec/mbboDirectRecord.dbd +++ b/src/std/rec/mbboDirectRecord.dbd @@ -8,7 +8,7 @@ #************************************************************************* recordtype(mbboDirect) { include "dbCommon.dbd" - field(VAL,DBF_USHORT) { + field(VAL,DBF_LONG) { prompt("Word") promptgroup("50 - Output") asl(ASL0) @@ -62,7 +62,7 @@ recordtype(mbboDirect) { special(SPC_NOMOD) interest(1) } - field(MLST,DBF_ULONG) { + field(MLST,DBF_LONG) { prompt("Last Value Monitored") special(SPC_NOMOD) interest(3) @@ -99,7 +99,7 @@ recordtype(mbboDirect) { interest(2) menu(menuIvoa) } - field(IVOV,DBF_USHORT) { + field(IVOV,DBF_LONG) { prompt("INVALID output value") promptgroup("50 - Output") interest(2) @@ -216,4 +216,116 @@ recordtype(mbboDirect) { pp(TRUE) interest(1) } + field(B10,DBF_UCHAR) { + prompt("Bit 16") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B11,DBF_UCHAR) { + prompt("Bit 17") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B12,DBF_UCHAR) { + prompt("Bit 18") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B13,DBF_UCHAR) { + prompt("Bit 19") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B14,DBF_UCHAR) { + prompt("Bit 20") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B15,DBF_UCHAR) { + prompt("Bit 21") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B16,DBF_UCHAR) { + prompt("Bit 22") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B17,DBF_UCHAR) { + prompt("Bit 23") + promptgroup("53 - Output 10-17") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B18,DBF_UCHAR) { + prompt("Bit 24") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B19,DBF_UCHAR) { + prompt("Bit 25") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B1A,DBF_UCHAR) { + prompt("Bit 26") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B1B,DBF_UCHAR) { + prompt("Bit 27") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B1C,DBF_UCHAR) { + prompt("Bit 28") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B1D,DBF_UCHAR) { + prompt("Bit 29") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B1E,DBF_UCHAR) { + prompt("Bit 30") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } + field(B1F,DBF_UCHAR) { + prompt("Bit 31") + promptgroup("54 - Output 18-1F") + special(SPC_MOD) + pp(TRUE) + interest(1) + } } From ccc8f75ec75e90d1407eded2e9010b5a861df5ce Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 7 Sep 2017 11:09:30 +0200 Subject: [PATCH 34/46] std/dev: adapt mbbiDirect/mbboDirect soft support to 32bit --- src/std/dev/devMbbiDirectSoft.c | 4 ++-- src/std/dev/devMbbiDirectSoftCallback.c | 6 +++--- src/std/dev/devMbboDirectSoft.c | 2 +- src/std/dev/devMbboDirectSoftCallback.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/std/dev/devMbbiDirectSoft.c b/src/std/dev/devMbbiDirectSoft.c index 9c929b2b6..4317ad807 100644 --- a/src/std/dev/devMbbiDirectSoft.c +++ b/src/std/dev/devMbbiDirectSoft.c @@ -47,7 +47,7 @@ epicsExportAddress(dset, devMbbiDirectSoft); static long init_record(mbbiDirectRecord *prec) { - if (recGblInitConstantLink(&prec->inp, DBF_ENUM, &prec->val)) + if (recGblInitConstantLink(&prec->inp, DBR_LONG, &prec->val)) prec->udf = FALSE; return 0; @@ -56,7 +56,7 @@ static long init_record(mbbiDirectRecord *prec) static long readLocked(struct link *pinp, void *dummy) { mbbiDirectRecord *prec = (mbbiDirectRecord *) pinp->precord; - long status = dbGetLink(pinp, DBR_USHORT, &prec->val, 0, 0); + long status = dbGetLink(pinp, DBR_LONG, &prec->val, 0, 0); if (status) return status; diff --git a/src/std/dev/devMbbiDirectSoftCallback.c b/src/std/dev/devMbbiDirectSoftCallback.c index 93016329f..c4c83f6c2 100644 --- a/src/std/dev/devMbbiDirectSoftCallback.c +++ b/src/std/dev/devMbbiDirectSoftCallback.c @@ -41,7 +41,7 @@ typedef struct devPvt { struct { DBRstatus DBRtime - epicsUInt16 value; + epicsUInt32 value; } buffer; } devPvt; @@ -58,7 +58,7 @@ static void getCallback(processNotify *ppn, notifyGetType type) } assert(type == getFieldType); - pdevPvt->status = dbChannelGetField(ppn->chan, DBR_USHORT, + pdevPvt->status = dbChannelGetField(ppn->chan, DBR_LONG, &pdevPvt->buffer, &pdevPvt->options, &no_elements, 0); } @@ -153,7 +153,7 @@ static long init(int pass) static long init_record(mbbiDirectRecord *prec) { - if (recGblInitConstantLink(&prec->inp, DBR_ENUM, &prec->val)) + if (recGblInitConstantLink(&prec->inp, DBR_LONG, &prec->val)) prec->udf = FALSE; return 0; diff --git a/src/std/dev/devMbboDirectSoft.c b/src/std/dev/devMbboDirectSoft.c index 0c0851980..ebf63a9f8 100644 --- a/src/std/dev/devMbboDirectSoft.c +++ b/src/std/dev/devMbboDirectSoft.c @@ -21,7 +21,7 @@ static long write_mbbo(mbboDirectRecord *prec) { - dbPutLink(&prec->out, DBR_USHORT, &prec->val, 1); + dbPutLink(&prec->out, DBR_LONG, &prec->val, 1); return 0; } diff --git a/src/std/dev/devMbboDirectSoftCallback.c b/src/std/dev/devMbboDirectSoftCallback.c index e64c3d41c..98aa7bb01 100644 --- a/src/std/dev/devMbboDirectSoftCallback.c +++ b/src/std/dev/devMbboDirectSoftCallback.c @@ -29,11 +29,11 @@ static long write_mbbo(mbboDirectRecord *prec) if (prec->pact) return 0; - status = dbPutLinkAsync(plink, DBR_USHORT, &prec->val, 1); + status = dbPutLinkAsync(plink, DBR_LONG, &prec->val, 1); if (!status) prec->pact = TRUE; else if (status == S_db_noLSET) - status = dbPutLink(plink, DBR_USHORT, &prec->val, 1); + status = dbPutLink(plink, DBR_LONG, &prec->val, 1); return status; } From 3b6a4ad5a69ec38610199a281a1351c497601a7f Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 15 May 2018 15:50:55 +0200 Subject: [PATCH 35/46] doc: update release notes --- documentation/RELEASE_NOTES.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index a4a09c7da..7eb9fdcc9 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -9,6 +9,8 @@

EPICS Base Release 3.16.2

+

Changes made between 3.16.1 and 3.16.2

+ +

Record types mbbiDirect and mbboDirect extended to 32 bit

+ +

The VAL fields of mbbiDirect and mbboDirect records have +been extended from DBF_USHORT (16 bit) to DBF_LONG (32 bit). +New bit fields B10...B1F have been added.

+ +

Device support which accesses the bit fields can test if the macro +mbbiDirectRecord1BF or mbboDirectRecord1BF is +defined. Device support which only accesses RVAL needs no modification.

+

Restore use of ledlib for VxWorks command editing

The epicsReadline refactoring work described below unfortunately disabled the From c80783dfa99844c36b58d34294fd6e70691d3b2c Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 15 May 2018 16:25:23 +0200 Subject: [PATCH 36/46] std/rec: fix promptgroup labels in mbboDirect --- src/std/rec/mbboDirectRecord.dbd | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/std/rec/mbboDirectRecord.dbd b/src/std/rec/mbboDirectRecord.dbd index 08a5ff96c..62c6973e9 100644 --- a/src/std/rec/mbboDirectRecord.dbd +++ b/src/std/rec/mbboDirectRecord.dbd @@ -162,168 +162,168 @@ recordtype(mbboDirect) { } field(B8,DBF_UCHAR) { prompt("Bit 8") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(B9,DBF_UCHAR) { prompt("Bit 9") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(BA,DBF_UCHAR) { prompt("Bit 10") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(BB,DBF_UCHAR) { prompt("Bit 11") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(BC,DBF_UCHAR) { prompt("Bit 12") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(BD,DBF_UCHAR) { prompt("Bit 13") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(BE,DBF_UCHAR) { prompt("Bit 14") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(BF,DBF_UCHAR) { prompt("Bit 15") - promptgroup("52 - Output 8-F") + promptgroup("52 - Output 8-15") special(SPC_MOD) pp(TRUE) interest(1) } field(B10,DBF_UCHAR) { prompt("Bit 16") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B11,DBF_UCHAR) { prompt("Bit 17") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B12,DBF_UCHAR) { prompt("Bit 18") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B13,DBF_UCHAR) { prompt("Bit 19") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B14,DBF_UCHAR) { prompt("Bit 20") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B15,DBF_UCHAR) { prompt("Bit 21") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B16,DBF_UCHAR) { prompt("Bit 22") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B17,DBF_UCHAR) { prompt("Bit 23") - promptgroup("53 - Output 10-17") + promptgroup("53 - Output 16-23") special(SPC_MOD) pp(TRUE) interest(1) } field(B18,DBF_UCHAR) { prompt("Bit 24") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B19,DBF_UCHAR) { prompt("Bit 25") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B1A,DBF_UCHAR) { prompt("Bit 26") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B1B,DBF_UCHAR) { prompt("Bit 27") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B1C,DBF_UCHAR) { prompt("Bit 28") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B1D,DBF_UCHAR) { prompt("Bit 29") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B1E,DBF_UCHAR) { prompt("Bit 30") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) } field(B1F,DBF_UCHAR) { prompt("Bit 31") - promptgroup("54 - Output 18-1F") + promptgroup("54 - Output 24-31") special(SPC_MOD) pp(TRUE) interest(1) From 7e293e60a6e9b92adea494403ca6159a2e910ec9 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 15 May 2018 16:54:46 +0200 Subject: [PATCH 37/46] std/dev,std/rec: treat val/sval/rval as ULONG for mbbiDirect/mbboDirect --- src/std/dev/devMbbiDirectSoft.c | 4 ++-- src/std/dev/devMbbiDirectSoftCallback.c | 4 ++-- src/std/dev/devMbbiDirectSoftRaw.c | 2 +- src/std/dev/devMbboDirectSoft.c | 2 +- src/std/dev/devMbboDirectSoftCallback.c | 4 ++-- src/std/rec/mbboDirectRecord.c | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/std/dev/devMbbiDirectSoft.c b/src/std/dev/devMbbiDirectSoft.c index 4317ad807..861952f8d 100644 --- a/src/std/dev/devMbbiDirectSoft.c +++ b/src/std/dev/devMbbiDirectSoft.c @@ -47,7 +47,7 @@ epicsExportAddress(dset, devMbbiDirectSoft); static long init_record(mbbiDirectRecord *prec) { - if (recGblInitConstantLink(&prec->inp, DBR_LONG, &prec->val)) + if (recGblInitConstantLink(&prec->inp, DBR_ULONG, &prec->val)) prec->udf = FALSE; return 0; @@ -56,7 +56,7 @@ static long init_record(mbbiDirectRecord *prec) static long readLocked(struct link *pinp, void *dummy) { mbbiDirectRecord *prec = (mbbiDirectRecord *) pinp->precord; - long status = dbGetLink(pinp, DBR_LONG, &prec->val, 0, 0); + long status = dbGetLink(pinp, DBR_ULONG, &prec->val, 0, 0); if (status) return status; diff --git a/src/std/dev/devMbbiDirectSoftCallback.c b/src/std/dev/devMbbiDirectSoftCallback.c index c4c83f6c2..d785f7386 100644 --- a/src/std/dev/devMbbiDirectSoftCallback.c +++ b/src/std/dev/devMbbiDirectSoftCallback.c @@ -58,7 +58,7 @@ static void getCallback(processNotify *ppn, notifyGetType type) } assert(type == getFieldType); - pdevPvt->status = dbChannelGetField(ppn->chan, DBR_LONG, + pdevPvt->status = dbChannelGetField(ppn->chan, DBR_ULONG, &pdevPvt->buffer, &pdevPvt->options, &no_elements, 0); } @@ -153,7 +153,7 @@ static long init(int pass) static long init_record(mbbiDirectRecord *prec) { - if (recGblInitConstantLink(&prec->inp, DBR_LONG, &prec->val)) + if (recGblInitConstantLink(&prec->inp, DBR_ULONG, &prec->val)) prec->udf = FALSE; return 0; diff --git a/src/std/dev/devMbbiDirectSoftRaw.c b/src/std/dev/devMbbiDirectSoftRaw.c index f6172cdec..98b4673fc 100644 --- a/src/std/dev/devMbbiDirectSoftRaw.c +++ b/src/std/dev/devMbbiDirectSoftRaw.c @@ -59,7 +59,7 @@ static long init_record(mbbiDirectRecord *prec) static long read_mbbi(mbbiDirectRecord *prec) { - if (!dbGetLink(&prec->inp, DBR_LONG, &prec->rval, 0, 0)) { + if (!dbGetLink(&prec->inp, DBR_ULONG, &prec->rval, 0, 0)) { prec->rval &= prec->mask; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) diff --git a/src/std/dev/devMbboDirectSoft.c b/src/std/dev/devMbboDirectSoft.c index ebf63a9f8..75359f283 100644 --- a/src/std/dev/devMbboDirectSoft.c +++ b/src/std/dev/devMbboDirectSoft.c @@ -21,7 +21,7 @@ static long write_mbbo(mbboDirectRecord *prec) { - dbPutLink(&prec->out, DBR_LONG, &prec->val, 1); + dbPutLink(&prec->out, DBR_ULONG, &prec->val, 1); return 0; } diff --git a/src/std/dev/devMbboDirectSoftCallback.c b/src/std/dev/devMbboDirectSoftCallback.c index 98aa7bb01..6d86507ae 100644 --- a/src/std/dev/devMbboDirectSoftCallback.c +++ b/src/std/dev/devMbboDirectSoftCallback.c @@ -29,11 +29,11 @@ static long write_mbbo(mbboDirectRecord *prec) if (prec->pact) return 0; - status = dbPutLinkAsync(plink, DBR_LONG, &prec->val, 1); + status = dbPutLinkAsync(plink, DBR_ULONG, &prec->val, 1); if (!status) prec->pact = TRUE; else if (status == S_db_noLSET) - status = dbPutLink(plink, DBR_LONG, &prec->val, 1); + status = dbPutLink(plink, DBR_ULONG, &prec->val, 1); return status; } diff --git a/src/std/rec/mbboDirectRecord.c b/src/std/rec/mbboDirectRecord.c index ff0747072..eaae38326 100644 --- a/src/std/rec/mbboDirectRecord.c +++ b/src/std/rec/mbboDirectRecord.c @@ -351,7 +351,7 @@ static long writeValue(mbboDirectRecord *prec) case menuYesNoYES: recGblSetSevr(prec, SIMM_ALARM, prec->sims); - return dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1); + return dbPutLink(&prec->siol, DBR_ULONG, &prec->val, 1); default: recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); From 3bc0805a89f765819d5d9f7354e647719b01e88e Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 18 May 2018 09:54:42 +0200 Subject: [PATCH 38/46] rec: fix missing includes in longin/longout --- src/rec/longinRecord.c | 1 + src/rec/longoutRecord.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/rec/longinRecord.c b/src/rec/longinRecord.c index 12da09c60..611bedb34 100644 --- a/src/rec/longinRecord.c +++ b/src/rec/longinRecord.c @@ -21,6 +21,7 @@ #include "dbDefs.h" #include "epicsPrint.h" +#include "epicsMath.h" #include "alarm.h" #include "dbAccess.h" #include "dbEvent.h" diff --git a/src/rec/longoutRecord.c b/src/rec/longoutRecord.c index c6ba45a4c..0a83f7732 100644 --- a/src/rec/longoutRecord.c +++ b/src/rec/longoutRecord.c @@ -19,6 +19,7 @@ #include "dbDefs.h" #include "epicsPrint.h" +#include "epicsMath.h" #include "alarm.h" #include "dbAccess.h" #include "dbEvent.h" From a732539eee73e137ed55e4333f21c28964e01297 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 19 May 2018 21:14:36 -0500 Subject: [PATCH 39/46] epicsMath.h defines 'finite()' not 'isfinite()' --- src/db/dbAccess.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c index b60594fed..0d84e7ebf 100644 --- a/src/db/dbAccess.c +++ b/src/db/dbAccess.c @@ -297,10 +297,10 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer, if (*options & DBR_AL_LONG) { struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer; - pal->upper_alarm_limit = isfinite(ald.upper_alarm_limit) ? (epicsInt32) ald.upper_alarm_limit : 0; - pal->upper_warning_limit = isfinite(ald.upper_warning_limit) ? (epicsInt32) ald.upper_warning_limit : 0; - pal->lower_warning_limit = isfinite(ald.lower_warning_limit) ? (epicsInt32) ald.lower_warning_limit : 0; - pal->lower_alarm_limit = isfinite(ald.lower_alarm_limit) ? (epicsInt32) ald.lower_alarm_limit : 0; + pal->upper_alarm_limit = finite(ald.upper_alarm_limit) ? (epicsInt32) ald.upper_alarm_limit : 0; + pal->upper_warning_limit = finite(ald.upper_warning_limit) ? (epicsInt32) ald.upper_warning_limit : 0; + pal->lower_warning_limit = finite(ald.lower_warning_limit) ? (epicsInt32) ald.lower_warning_limit : 0; + pal->lower_alarm_limit = finite(ald.lower_alarm_limit) ? (epicsInt32) ald.lower_alarm_limit : 0; if (no_data) *options ^= DBR_AL_LONG; /*Turn off option*/ From c1ece40f41ed44fef855e3253bb75fbd83394111 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 19 May 2018 22:42:23 -0500 Subject: [PATCH 40/46] Updated Release Notes for Base-3.14.12.8 --- documentation/RELEASE_NOTES.html | 50 ++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 20ff8f460..b454da0d6 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -3,16 +3,60 @@ - EPICS Base R3.14.12.7 Release Notes + EPICS Base R3.14.12.8 Release Notes -

EPICS Base Release 3.14.12.7

+

EPICS Base Release 3.14.12.8

-

Changes between 3.14.12.6 and 3.14.12.7

+

Changes between 3.14.12.7 and 3.14.12.8

+

Fixes for Launchpad bugs

+ +

The following launchpad bugs have fixes included:

+ + + +

Updated VxWorks Timezone settings

+ +

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

+ +

Back-port podToHtml.pl and Rules from Base-3.15

+ +

This script permits Base to be built with Perl installations that do not +provide the podchecker and pod2html scripts (e.g. Fedora 27).

+ +

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.

+ +

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.

+ +

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

+ +

Changes between 3.14.12.6 and 3.14.12.7

+

Extend maximum Posix epicsEventWaitWithTimeout() delay

The Posix implementation of epicsEventWaitWithTimeout() was limiting the From 498b248811cd6393b9a12d325935027bcf128e64 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 22 May 2018 14:14:10 +0200 Subject: [PATCH 41/46] std/rec/test: add test for mbbiDirect/mbboDirect (drop dysfunctional async test from original proposal) --- src/std/rec/test/Makefile | 7 ++ src/std/rec/test/mbbioDirectTest.c | 145 ++++++++++++++++++++++++++++ src/std/rec/test/mbbioDirectTest.db | 47 +++++++++ 3 files changed, 199 insertions(+) create mode 100644 src/std/rec/test/mbbioDirectTest.c create mode 100644 src/std/rec/test/mbbioDirectTest.db diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index 94afd4c01..bde69117f 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -116,6 +116,13 @@ regressTest_SRCS += regressTest_registerRecordDeviceDriver.cpp TESTFILES += $(COMMON_DIR)/regressTest.dbd ../regressArray1.db ../regressHex.db ../regressLinkMS.db TESTS += regressTest +TESTPROD_HOST += mbbioDirectTest +mbbioDirectTest_SRCS += mbbioDirectTest.c +mbbioDirectTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += mbbioDirectTest.c +TESTFILES += ../mbbioDirectTest.db +TESTS += mbbioDirectTest + # epicsRunRecordTests runs all the test programs in a known working order. testHarness_SRCS += epicsRunRecordTests.c diff --git a/src/std/rec/test/mbbioDirectTest.c b/src/std/rec/test/mbbioDirectTest.c new file mode 100644 index 000000000..fb011f662 --- /dev/null +++ b/src/std/rec/test/mbbioDirectTest.c @@ -0,0 +1,145 @@ +/*************************************************************************\ +* Copyright (c) 2017 Dirk Zimoch +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* Theory of Operation + * + * For each of the two soft device supports (soft/raw soft/soft), + * there is a combination of mbboDirect -> val / sim -> mbbiDirect. + * + * The intermediate records are of type double (val) and long (sim) to + * check conversion from/to double. + * + * For each device support, the following is done: + * 1. The mbboDirect record is set to a specific value through the database. + * 2. The initial value is checked on both ends. + * 3. Two single bits (5 & 31) are toggled, values checked on both ends. + * 4. Sim mode is activated, one bit (0) is toggled, values are checked, + * data path (old value in val, new value in sim) is checked. + */ + +#include + +#include "dbAccess.h" +#include "errlog.h" +#include "dbStaticLib.h" +#include "dbTest.h" +#include "dbUnitTest.h" +#include "testMain.h" +#include "epicsThread.h" +#include "epicsExport.h" + +static +void testmbbioFields(const char* rec, unsigned int value) +{ + char field[40]; + unsigned int i; + + testdbGetFieldEqual(rec, DBF_ULONG, value); + for (i=0; i < 32; i++) + { + sprintf(field,"%s.B%X", rec, i); + testdbGetFieldEqual(field, DBF_ULONG, (value>>i)&1); + } +} + +static +void testmbbioRecords(unsigned int count, unsigned int value) +{ + char rec[40]; + unsigned int i; + + for (i = 1; i <= count; i++) + { + sprintf(rec, "do%d", i); + testDiag(" ### %s ###", rec); + testmbbioFields(rec, value); + sprintf(rec, "di%d", i); + testmbbioFields(rec, value); + } +} + +static +void putN(const char* pattern, unsigned int count, unsigned int value) +{ + char field[40]; + unsigned int i; + + for (i = 1; i <= count; i++) + { + sprintf(field, pattern, i); + testdbPutFieldOk(field, DBF_ULONG, value); + } +} + +static +void testN(const char* pattern, unsigned int count, unsigned int value) +{ + char field[40]; + unsigned int i; + + for (i = 1; i <= count; i++) + { + sprintf(field, pattern, i); + testdbGetFieldEqual(field, DBF_ULONG, value); + } +} + + +void recTestIoc_registerRecordDeviceDriver(struct dbBase *); + +MAIN(mbbioDirectTest) +{ + unsigned int value = 0xdeadbeef; + unsigned int simvalue = 0; + char macros [40]; + const unsigned int N = 2; + + testPlan(N*((32+1)*2*4+4+3)); + + testdbPrepare(); + + testdbReadDatabase("recTestIoc.dbd", NULL, NULL); + + recTestIoc_registerRecordDeviceDriver(pdbbase); + + sprintf(macros, "INIT=%#x", value); + testdbReadDatabase("mbbioDirectTest.db", NULL, macros); + + eltc(0); + testIocInitOk(); + eltc(1); + + testDiag("##### check initial value #####"); + testmbbioRecords(N, value); + + testDiag("##### set bit 5 #####"); + putN("do%u.B5", N, 1); + value |= (1<<5); + testN("val%d", N, value); + testmbbioRecords(N, value); + + testDiag("##### clear bit 31 (0x1f) #####"); + putN("do%u.B1F", N, 0); + value &= ~(1<<31); + testN("val%d", N, value); + testmbbioRecords(N, value); + + testDiag("##### simulation mode #####"); + dbpf("sim", "1"); + simvalue = value & ~1; + putN("do%u.B0", N, 0); + /* old value in lo* */ + testN("val%d", N, value); + /* sim value in sim* */ + testN("sim%d", N, simvalue); + testmbbioRecords(N, simvalue); + + testIocShutdownOk(); + + testdbCleanup(); + + return testDone(); +} diff --git a/src/std/rec/test/mbbioDirectTest.db b/src/std/rec/test/mbbioDirectTest.db new file mode 100644 index 000000000..ed6e09175 --- /dev/null +++ b/src/std/rec/test/mbbioDirectTest.db @@ -0,0 +1,47 @@ +record(bo, "sim") { + field(ZNAM, "off") + field(ONAM, "simulation") +} + +record(mbboDirect, "do1") { + field(DOL, "$(INIT=0)") + field(DTYP, "Soft Channel") + field(OUT, "val1 PP") + field(SIOL, "sim1 PP") + field(SIML, "sim") + field(PINI, "YES") +} +record(ao, "val1") { + field(FLNK, "di1") +} +record(longout, "sim1") { + field(FLNK, "di1") +} +record(mbbiDirect, "di1") { + field(DTYP, "Soft Channel") + field(INP, "val1") + field(SIOL, "sim1 PP") + field(SIML, "sim") +} + + +record(mbboDirect, "do2") { + field(DOL, "$(INIT=0)") + field(DTYP, "Raw Soft Channel") + field(OUT, "val2 PP") + field(SIOL, "sim2 PP") + field(SIML, "sim") + field(PINI, "YES") +} +record(ao, "val2") { + field(FLNK, "di2") +} +record(longout, "sim2") { + field(FLNK, "di2") +} +record(mbbiDirect, "di2") { + field(DTYP, "Raw Soft Channel") + field(INP, "val2") + field(SIML, "sim") + field(SIOL, "sim2") +} From 7e7d230d8c6f89d62b0d569d354b1e793ccfeebf Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 23 May 2018 09:24:56 +0200 Subject: [PATCH 42/46] templates: fix warnings for xxxRecord.c in exampleApp (fixes #1772833) --- src/makeBaseApp/top/exampleApp/src/xxxRecord.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/makeBaseApp/top/exampleApp/src/xxxRecord.c b/src/makeBaseApp/top/exampleApp/src/xxxRecord.c index 4281eb983..109bd45dd 100644 --- a/src/makeBaseApp/top/exampleApp/src/xxxRecord.c +++ b/src/makeBaseApp/top/exampleApp/src/xxxRecord.c @@ -198,8 +198,8 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad) static void checkAlarms(xxxRecord *prec) { - double val; - float hyst, lalm, hihi, high, low, lolo; + double val, hyst, lalm; + float hihi, high, low, lolo; unsigned short hhsv, llsv, hsv, lsv; if(prec->udf == TRUE ){ From 67844bacc30e460fa43552e260f347065b1bb0c7 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 28 May 2018 16:13:14 -0500 Subject: [PATCH 43/46] Perl s/use vars/our/ --- src/tools/convertRelease.pl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl index fb2153a34..62e3d3eb3 100644 --- a/src/tools/convertRelease.pl +++ b/src/tools/convertRelease.pl @@ -21,8 +21,7 @@ use Getopt::Std; use EPICS::Path; use EPICS::Release; -use vars qw($arch $top $iocroot $root); - +our ($arch, $top, $iocroot, $root); our ($opt_a, $opt_t, $opt_T); $Getopt::Std::OUTPUT_HELP_VERSION = 1; From 23c4eb42a3eeb69d4043245372457d61a0579328 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 28 May 2018 17:31:16 -0500 Subject: [PATCH 44/46] Perl s/use vars/our/ --- src/tools/dbdToHtml.pl | 2 +- src/tools/dbdToMenuH.pl | 2 +- src/tools/dbdToRecordtypeH.pl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/dbdToHtml.pl b/src/tools/dbdToHtml.pl index bb1ca7d86..fac850a7e 100644 --- a/src/tools/dbdToHtml.pl +++ b/src/tools/dbdToHtml.pl @@ -43,7 +43,7 @@ BEGIN { my $tool = 'dbdToHtml'; -use vars qw($opt_D @opt_I $opt_o); +our ($opt_D, @opt_I, $opt_o); getopts('DI@o:') or die "Usage: $tool [-D] [-I dir] [-o file.html] file.dbd.pod\n"; diff --git a/src/tools/dbdToMenuH.pl b/src/tools/dbdToMenuH.pl index 8ad799d67..3470c1017 100755 --- a/src/tools/dbdToMenuH.pl +++ b/src/tools/dbdToMenuH.pl @@ -19,7 +19,7 @@ use EPICS::Readfile; my $tool = 'dbdToMenuH.pl'; -use vars qw($opt_D @opt_I $opt_o $opt_s); +our ($opt_D, @opt_I, $opt_o, $opt_s); getopts('DI@o:') or die "Usage: $tool: [-D] [-I dir] [-o menu.h] menu.dbd [menu.h]\n"; diff --git a/src/tools/dbdToRecordtypeH.pl b/src/tools/dbdToRecordtypeH.pl index 5c2380897..ce3c029d9 100755 --- a/src/tools/dbdToRecordtypeH.pl +++ b/src/tools/dbdToRecordtypeH.pl @@ -19,7 +19,7 @@ use EPICS::Readfile; my $tool = 'dbdToRecordtypeH.pl'; -use vars qw($opt_D @opt_I $opt_o $opt_s); +our ($opt_D, @opt_I, $opt_o, $opt_s); getopts('DI@o:s') or die "Usage: $tool [-D] [-I dir] [-o xRecord.h] xRecord.dbd [xRecord.h]\n"; From fe1ec6ed3132c40d4a4e2dbe7bcfff0ca234572c Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 28 May 2018 17:40:57 -0500 Subject: [PATCH 45/46] Replace > with > in Release Notes code examples --- documentation/RELEASE_NOTES.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 5dc38f409..a78197911 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -307,15 +307,15 @@ to implement the link APIs, so will work properly after these conversions:

link type, i.e. change this code:
-    if (prec->siml.type == CONSTANT) {
-        recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
+    if (prec->siml.type == CONSTANT) {
+        recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
     }
 
into this:
-    recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
+    recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
 
Note that recGblInitConstantLink() still returns TRUE if the field was @@ -328,20 +328,20 @@ or undefined links, FALSE for links whose dbGetLink() routine may return different values on different calls. For example this:
-    if (prec->dol.type != CONSTANT)
+    if (prec->dol.type != CONSTANT)
 
should become this:
-    if (!dbLinkIsConstant(&prec->dol))
+    if (!dbLinkIsConstant(&prec->dol))
 
When the converted software is also required to build against older versions of Base, this macro definition may be useful:
-#define dbLinkIsConstant(lnk) ((lnk)->type == CONSTANT)
+#define dbLinkIsConstant(lnk) ((lnk)->type == CONSTANT)
 
@@ -349,7 +349,7 @@ Base, this macro definition may be useful: link has been resolved as a CA link using code such as
-    if (prec->inp.type == CA_LINK)
+    if (prec->inp.type == CA_LINK)
 
will still compile and run, but will only work properly with the old CA link @@ -359,7 +359,7 @@ examine or modify data inside the link. After conversion the above line would probably become:
-    if (dbLinkIsVolatile(&prec->inp))
+    if (dbLinkIsVolatile(&prec->inp))
 
A volatile link is one like a Channel Access link which may disconnect and @@ -369,7 +369,7 @@ same state they started in. For compatibility when building against older versions of Base, this macro definition may be useful:
-#define dbLinkIsVolatile(lnk) ((lnk)->type == CA_LINK)
+#define dbLinkIsVolatile(lnk) ((lnk)->type == CA_LINK)
 
From a9d7f7be13d38a61b2ddea8b98d0178324368c32 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 4 Jun 2018 23:14:45 -0500 Subject: [PATCH 46/46] Template iocBoot/ioc Makefile fix for Unix-like OSs Fixes lp: #1766349 --- src/template/base/top/exampleBoot/ioc/Makefile@Common | 1 + src/template/base/top/iocBoot/ioc/Makefile@Common | 1 + 2 files changed, 2 insertions(+) diff --git a/src/template/base/top/exampleBoot/ioc/Makefile@Common b/src/template/base/top/exampleBoot/ioc/Makefile@Common index e064d7344..e1b9aa4ab 100644 --- a/src/template/base/top/exampleBoot/ioc/Makefile@Common +++ b/src/template/base/top/exampleBoot/ioc/Makefile@Common @@ -1,4 +1,5 @@ TOP = ../.. include $(TOP)/configure/CONFIG +ARCH = $(EPICS_HOST_ARCH) TARGETS = envPaths include $(TOP)/configure/RULES.ioc diff --git a/src/template/base/top/iocBoot/ioc/Makefile@Common b/src/template/base/top/iocBoot/ioc/Makefile@Common index e064d7344..e1b9aa4ab 100644 --- a/src/template/base/top/iocBoot/ioc/Makefile@Common +++ b/src/template/base/top/iocBoot/ioc/Makefile@Common @@ -1,4 +1,5 @@ TOP = ../.. include $(TOP)/configure/CONFIG +ARCH = $(EPICS_HOST_ARCH) TARGETS = envPaths include $(TOP)/configure/RULES.ioc