Merge changes from 3.16 branch into 7.0

This commit is contained in:
Andrew Johnson
2018-06-20 21:42:43 -05:00
39 changed files with 1207 additions and 330 deletions
+84
View File
@@ -45,6 +45,7 @@
#include "epicsExport.h"
#include "link.h"
#include "recSup.h"
#include "dbUnitTest.h" /* for testSyncCallback() */
static int callbackQueueSize = 2000;
@@ -352,3 +353,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<NUM_CALLBACK_PRIORITIES; i++) {
helper[i].wait_phase2 = epicsEventMustCreate(epicsEventEmpty);
helper[i].wait_phase4 = epicsEventMustCreate(epicsEventEmpty);
/* no real need to lock here, but do so anyway so that valgrind can establish
* the locking requirements for sync_helper.
*/
testGlobalLock();
helper[i].nphase2 = helper[i].nphase3 = callbackQueue[i].threadsRunning;
testGlobalUnlock();
callbackSetUser(&helper[i], &helper[i].cb);
callbackSetPriority(i, &helper[i].cb);
callbackSetCallback(sync_callback, &helper[i].cb);
callbackRequest(&helper[i].cb);
}
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
epicsEventMustWait(helper[i].wait_phase4);
}
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
testGlobalLock();
epicsEventDestroy(helper[i].wait_phase2);
epicsEventDestroy(helper[i].wait_phase4);
testGlobalUnlock();
}
testDiag("Complete testSyncCallback()");
}
+3 -1
View File
@@ -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*);
+8 -4
View File
@@ -293,10 +293,14 @@ 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 = 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*/
+46 -39
View File
@@ -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 */
@@ -109,8 +109,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;
@@ -247,11 +247,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,
@@ -315,24 +310,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) {
@@ -420,14 +408,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)) {
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", pel->event_name, priorityName[prio]);
sprintf(message, " Priority %s", priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
}
@@ -478,20 +464,52 @@ event_list *eventNameToHandle(const char *eventname)
int prio;
event_list *pel;
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
double eventnumber = 0;
size_t namelength;
if (!eventname || eventname[0] == 0)
return NULL;
if (!eventname) return NULL;
while (isspace((int) eventname[0])) eventname++;
if (!eventname[0]) return NULL;
namelength = strlen(eventname);
while (isspace((int) 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, NULL) == 0)
{
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 between 1 and 255 */
}
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 = calloc(1, sizeof(event_list));
pel = calloc(1, sizeof(event_list) + namelength);
if (!pel)
goto done;
strcpy(pel->event_name, eventname);
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;
}
}
done:
epicsMutexUnlock(event_lock);
@@ -528,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)
+1 -1
View File
@@ -51,7 +51,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);
+24
View File
@@ -20,6 +20,7 @@
#include "osiUnistd.h"
#include "registry.h"
#include "epicsEvent.h"
#include "epicsThread.h"
#define epicsExportSharedSymbols
#include "dbAccess.h"
@@ -415,3 +416,26 @@ unsigned testMonitorCount(testMonitor *mon, unsigned reset)
return count;
}
static
epicsMutexId test_global;
static
epicsThreadOnceId test_global_once = EPICS_THREAD_ONCE_INIT;
static
void test_global_init(void* ignored)
{
test_global = epicsMutexMustCreate();
}
void testGlobalLock(void)
{
epicsThreadOnce(&test_global_once, &test_global_init, NULL);
epicsMutexMustLock(test_global);
}
void testGlobalUnlock(void)
{
epicsMutexUnlock(test_global);
}
+59
View File
@@ -98,6 +98,65 @@ epicsShareFunc void testMonitorWait(testMonitor*);
*/
epicsShareFunc unsigned testMonitorCount(testMonitor*, unsigned reset);
/** Synchronize the shared callback queues.
*
* Block until all callback queue jobs which were queued, or running,
* have completed.
*/
epicsShareFunc void testSyncCallback(void);
/** Global mutex for use by test code.
*
* This utility mutex is intended to be used to avoid races in situations
* where some other syncronization primitive is being destroyed (epicsEvent,
* epicsMutex, ...).
*
* For example. The following has a subtle race where the event may be
* destroyed (free()'d) before the call to epicsEventMustSignal() has
* returned. On some targets this leads to a use after free() error.
*
@code
epicsEventId evt;
void thread1() {
evt = epicsEventMustCreate(...);
// spawn thread2()
epicsEventMustWait(evt);
epicsEventDestroy(evt);
}
// ...
void thread2() {
epicsEventMustSignal(evt);
}
@endcode
*
* One way to avoid this race is to use a global mutex to ensure
* that epicsEventMustSignal() has returned before destroying
* the event.
*
@code
epicsEventId evt;
void thread1() {
evt = epicsEventMustCreate(...);
// spawn thread2()
epicsEventMustWait(evt);
testGlobalLock(); // <-- added
epicsEventDestroy(evt);
testGlobalUnlock(); // <-- added
}
// ...
void thread2() {
testGlobalLock(); // <-- added
epicsEventMustSignal(evt);
testGlobalUnlock(); // <-- added
}
@endcode
*
* This must be a global mutex to avoid simply shifting the race
* from the event to a locally allocated mutex.
*/
epicsShareFunc void testGlobalLock(void);
epicsShareFunc void testGlobalUnlock(void);
#ifdef __cplusplus
}
#endif
@@ -1064,32 +1064,39 @@ 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));
yyerror(NULL);
return;
}
if (*value == '"') {
/* jsonSTRING values still have their quotes */
/* jsonSTRING values still have their quotes */
value++;
value[strlen(value) - 1] = 0;
value[strlen(value) - 1] = 0;
}
dbTranslateEscape(value, value); /* in-place; safe & legal */
status = dbPutString(pdbentry,value);
if(status) {
if (status) {
char msg[128];
errSymLookup(status, msg, sizeof(msg));
epicsPrintf("Can't set \"%s.%s\" to \"%s\" %s\n",
dbGetRecordName(pdbentry), name, value, msg);
dbGetRecordName(pdbentry), name, value, msg);
yyerror(NULL);
return;
}
@@ -1097,39 +1104,39 @@ 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;
if (*value == '"') {
/* jsonSTRING values still have their quotes */
/* jsonSTRING values still have their quotes */
value++;
value[strlen(value) - 1] = 0;
value[strlen(value) - 1] = 0;
}
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
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);
@@ -1139,15 +1146,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);
@@ -1157,14 +1165,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);
}
@@ -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_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_USHORT, &prec->val, 0, 0);
long status = dbGetLink(pinp, DBR_ULONG, &prec->val, 0, 0);
if (status) return status;
@@ -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_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_ENUM, &prec->val))
if (recGblInitConstantLink(&prec->inp, DBR_ULONG, &prec->val))
prec->udf = FALSE;
return 0;
@@ -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)
@@ -21,7 +21,7 @@
static long write_mbbo(mbboDirectRecord *prec)
{
dbPutLink(&prec->out, DBR_USHORT, &prec->val, 1);
dbPutLink(&prec->out, DBR_ULONG, &prec->val, 1);
return 0;
}
@@ -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_ULONG, &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_ULONG, &prec->val, 1);
return status;
}
@@ -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">
+11 -8
View File
@@ -22,6 +22,7 @@
#include "dbDefs.h"
#include "epicsPrint.h"
#include "epicsMath.h"
#include "alarm.h"
#include "callback.h"
#include "dbAccess.h"
@@ -248,15 +249,17 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
{
longinRecord *prec=(longinRecord *)paddr->precord;
if(dbGetFieldIndex(paddr) == indexof(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;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
if (dbGetFieldIndex(paddr) == indexof(VAL)){
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;
}
static void checkAlarms(longinRecord *prec, epicsTimeStamp *timeLast)
{
enum {
+11 -8
View File
@@ -19,6 +19,7 @@
#include "dbDefs.h"
#include "epicsPrint.h"
#include "epicsMath.h"
#include "alarm.h"
#include "callback.h"
#include "dbAccess.h"
@@ -282,15 +283,17 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
{
longoutRecord *prec=(longoutRecord *)paddr->precord;
if(dbGetFieldIndex(paddr) == indexof(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;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
if (dbGetFieldIndex(paddr) == indexof(VAL)) {
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;
}
static void checkAlarms(longoutRecord *prec)
{
epicsInt32 val, hyst, lalm;
@@ -6,10 +6,10 @@
* Copyright (c) 2002 Southeastern Universities Research Association, as
* Operator of Thomas Jefferson National Accelerator Facility.
* 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.
\*************************************************************************/
/* 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
@@ -93,7 +93,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)
}
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
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);
}
@@ -208,7 +208,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;
@@ -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) {
@@ -151,32 +151,112 @@ 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)
}
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)
}
+15 -15
View File
@@ -95,7 +95,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)
{
@@ -117,7 +117,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
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 */
@@ -142,8 +142,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;
@@ -175,9 +175,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;
}
@@ -185,11 +185,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;
@@ -264,7 +264,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;
@@ -278,9 +278,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)
@@ -289,8 +289,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;
@@ -362,7 +362,7 @@ static long writeValue(mbboDirectRecord *prec)
case menuYesNoYES: {
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
if (prec->pact || (prec->sdly < 0.)) {
status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1);
status = dbPutLink(&prec->siol, DBR_ULONG, &prec->val, 1);
prec->pact = FALSE;
} else { /* !prec->pact && delay >= 0. */
CALLBACK *pvt = prec->simpvt;
+206 -94
View File
@@ -7,8 +7,8 @@
# in file LICENSE that is included with this distribution.
#*************************************************************************
recordtype(mbboDirect) {
include "dbCommon.dbd"
field(VAL,DBF_USHORT) {
include "dbCommon.dbd"
field(VAL,DBF_LONG) {
prompt("Word")
promptgroup("50 - Output")
asl(ASL0)
@@ -38,6 +38,99 @@ 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_LONG) {
prompt("Last Value Monitored")
special(SPC_NOMOD)
interest(3)
}
field(SHFT,DBF_USHORT) {
prompt("Shift")
promptgroup("50 - Output")
interest(1)
}
field(SIOL,DBF_OUTLINK) {
prompt("Simulation Output Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("CALLBACK *simpvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID outpt action")
promptgroup("50 - Output")
interest(2)
menu(menuIvoa)
}
field(IVOV,DBF_LONG) {
prompt("INVALID output value")
promptgroup("50 - Output")
interest(2)
}
field(B0,DBF_UCHAR) {
prompt("Bit 0")
promptgroup("51 - Output 0-7")
@@ -96,151 +189,170 @@ recordtype(mbboDirect) {
}
field(B8,DBF_UCHAR) {
prompt("Bit 8")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B9,DBF_UCHAR) {
prompt("Bit 9")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(BA,DBF_UCHAR) {
prompt("Bit 10")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(BB,DBF_UCHAR) {
prompt("Bit 11")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(BC,DBF_UCHAR) {
prompt("Bit 12")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(BD,DBF_UCHAR) {
prompt("Bit 13")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(BE,DBF_UCHAR) {
prompt("Bit 14")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(BF,DBF_UCHAR) {
prompt("Bit 15")
promptgroup("52 - Output 9-F")
promptgroup("52 - Output 8-15")
special(SPC_MOD)
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("Simulation Output Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
field(B10,DBF_UCHAR) {
prompt("Bit 16")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
field(B11,DBF_UCHAR) {
prompt("Bit 17")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
field(B12,DBF_UCHAR) {
prompt("Bit 18")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("CALLBACK *simpvt")
field(B13,DBF_UCHAR) {
prompt("Bit 19")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(IVOA,DBF_MENU) {
prompt("INVALID outpt action")
promptgroup("50 - Output")
interest(2)
menu(menuIvoa)
field(B14,DBF_UCHAR) {
prompt("Bit 20")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(IVOV,DBF_USHORT) {
prompt("INVALID output value")
promptgroup("50 - Output")
interest(2)
field(B15,DBF_UCHAR) {
prompt("Bit 21")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B16,DBF_UCHAR) {
prompt("Bit 22")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B17,DBF_UCHAR) {
prompt("Bit 23")
promptgroup("53 - Output 16-23")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B18,DBF_UCHAR) {
prompt("Bit 24")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B19,DBF_UCHAR) {
prompt("Bit 25")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B1A,DBF_UCHAR) {
prompt("Bit 26")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B1B,DBF_UCHAR) {
prompt("Bit 27")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B1C,DBF_UCHAR) {
prompt("Bit 28")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B1D,DBF_UCHAR) {
prompt("Bit 29")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B1E,DBF_UCHAR) {
prompt("Bit 30")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
field(B1F,DBF_UCHAR) {
prompt("Bit 31")
promptgroup("54 - Output 24-31")
special(SPC_MOD)
pp(TRUE)
interest(1)
}
}
+22 -8
View File
@@ -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);
}
@@ -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 ){
@@ -1,4 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = $(EPICS_HOST_ARCH)
TARGETS = envPaths
include $(TOP)/configure/RULES.ioc
@@ -1,4 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = $(EPICS_HOST_ARCH)
TARGETS = envPaths
include $(TOP)/configure/RULES.ioc
+1 -1
View File
@@ -46,7 +46,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";
+1 -1
View File
@@ -21,7 +21,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";
@@ -21,7 +21,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";