diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 17b5946c6..4da494f4a 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -20,6 +20,17 @@ --> +

Synchronized Timestamps with TSEL=-2

+ +

Most Soft Channel input device support routines have supported fetching the +timestamp through the INP link along with the input data. However before now +there was no guarantee that the timestamp provided by a CA link came from the +same update as the data, since the two were read at separate times without +maintaining a lock on the CA input buffer. This shortcoming has been fixed as +part of the new link support code, which allows code using a link to pass a +subroutine to the link type to be run with the link locked. The subroutine may +make multiple requests for metadata from the link, but must not block.

+

Device Support Address Type JSON_LINK

Device support may be written to expect hardware addresses in the new diff --git a/src/std/dev/devAaiSoft.c b/src/std/dev/devAaiSoft.c index ab6476ea9..a9d1c7615 100644 --- a/src/std/dev/devAaiSoft.c +++ b/src/std/dev/devAaiSoft.c @@ -75,11 +75,11 @@ static long init_record(aaiRecord *prec) return 0; } -static long read_aai(aaiRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { + aaiRecord *prec = (aaiRecord *) pinp->precord; long nRequest = prec->nelm; - long status = dbGetLink(prec->simm == menuYesNoYES ? &prec->siol : - &prec->inp, prec->ftvl, prec->bptr, 0, &nRequest); + long status = dbGetLink(pinp, prec->ftvl, prec->bptr, 0, &nRequest); if (!status && nRequest > 0) { prec->nord = nRequest; @@ -87,7 +87,18 @@ static long read_aai(aaiRecord *prec) if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return status; } + +static long read_aai(aaiRecord *prec) +{ + struct link *pinp = prec->simm == menuYesNoYES ? &prec->siol : &prec->inp; + long status = dbLinkDoLocked(pinp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(pinp, NULL); + + return status; +} diff --git a/src/std/dev/devAiSoft.c b/src/std/dev/devAiSoft.c index 74a2a759a..85c78c242 100644 --- a/src/std/dev/devAiSoft.c +++ b/src/std/dev/devAiSoft.c @@ -57,29 +57,43 @@ static long init_record(aiRecord *prec) return 0; } +static long readLocked(struct link *pinp, void *dummy) +{ + aiRecord *prec = (aiRecord *) pinp->precord; + double val; + long status = dbGetLink(pinp, DBR_DOUBLE, &val, 0, 0); + + if (status) return status; + + /* Apply smoothing algorithm */ + if (prec->smoo != 0.0 && prec->dpvt && finite(prec->val)) + prec->val = val * (1.00 - prec->smoo) + (prec->val * prec->smoo); + else + prec->val = val; + + prec->udf = FALSE; + prec->dpvt = &devAiSoft; /* Any non-zero value */ + + if (dbLinkIsConstant(&prec->tsel) && + prec->tse == epicsTimeEventDeviceTime) + dbGetTimeStamp(pinp, &prec->time); + + return 0; +} + static long read_ai(aiRecord *prec) { - double val; + long status; if (dbLinkIsConstant(&prec->inp)) return 2; - if (!dbGetLink(&prec->inp, DBR_DOUBLE, &val, 0, 0)) { + status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); - /* Apply smoothing algorithm */ - if (prec->smoo != 0.0 && prec->dpvt && finite(prec->val)) - prec->val = val * (1.00 - prec->smoo) + (prec->val * prec->smoo); - else - prec->val = val; - - prec->udf = FALSE; - prec->dpvt = &devAiSoft; /* Any non-zero value */ - - if (dbLinkIsConstant(&prec->tsel) && - prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); - } else { + if (status) prec->dpvt = NULL; - } + return 2; } diff --git a/src/std/dev/devAiSoftRaw.c b/src/std/dev/devAiSoftRaw.c index 1ec289b38..b06e245d2 100644 --- a/src/std/dev/devAiSoftRaw.c +++ b/src/std/dev/devAiSoftRaw.c @@ -55,12 +55,26 @@ static long init_record(aiRecord *prec) return 0; } -static long read_ai(aiRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - if (!dbGetLink(&prec->inp, DBR_LONG, &prec->rval, 0, 0) && - dbLinkIsConstant(&prec->tsel) && + aiRecord *prec = (aiRecord *) pinp->precord; + long status = dbGetLink(pinp, DBR_LONG, &prec->rval, 0, 0); + + if (status) return status; + + if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); return 0; } + +static long read_ai(aiRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devBiSoft.c b/src/std/dev/devBiSoft.c index a9364debc..b1b3c17a3 100644 --- a/src/std/dev/devBiSoft.c +++ b/src/std/dev/devBiSoft.c @@ -53,13 +53,25 @@ static long init_record(biRecord *prec) return 0; } -static long read_bi(biRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - if (!dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0)) { + biRecord *prec = (biRecord *) pinp->precord; + + if (!dbGetLink(pinp, DBR_USHORT, &prec->val, 0, 0)) { prec->udf = FALSE; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return 2; } + +static long read_bi(biRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devBiSoftRaw.c b/src/std/dev/devBiSoftRaw.c index 2d8dc25e5..afddd4712 100644 --- a/src/std/dev/devBiSoftRaw.c +++ b/src/std/dev/devBiSoftRaw.c @@ -52,12 +52,24 @@ static long init_record(biRecord *prec) return 0; } -static long read_bi(biRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - if (!dbGetLink(&prec->inp, DBR_ULONG, &prec->rval, 0, 0) && + biRecord *prec = (biRecord *) pinp->precord; + + if (!dbGetLink(pinp, DBR_ULONG, &prec->rval, 0, 0) && dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); return 0; } + +static long read_bi(biRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devEventSoft.c b/src/std/dev/devEventSoft.c index c9a5f273e..b5cc02f5c 100644 --- a/src/std/dev/devEventSoft.c +++ b/src/std/dev/devEventSoft.c @@ -53,13 +53,14 @@ static long init_record(eventRecord *prec) return 0; } -static long read_event(eventRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { + eventRecord *prec = (eventRecord *) pinp->precord; long status; char newEvent[MAX_STRING_SIZE]; - if (!dbLinkIsConstant(&prec->inp)) { - status = dbGetLink(&prec->inp, DBR_STRING, newEvent, 0, 0); + if (!dbLinkIsConstant(pinp)) { + status = dbGetLink(pinp, DBR_STRING, newEvent, 0, 0); if (status) return status; if (strcmp(newEvent, prec->val) != 0) { strcpy(prec->val, newEvent); @@ -69,6 +70,16 @@ static long read_event(eventRecord *prec) prec->udf = FALSE; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); return 0; } + +static long read_event(eventRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devLiSoft.c b/src/std/dev/devLiSoft.c index 0752b4f30..b48baccf9 100644 --- a/src/std/dev/devLiSoft.c +++ b/src/std/dev/devLiSoft.c @@ -54,14 +54,24 @@ static long init_record(longinRecord *prec) return 0; } -static long read_longin(longinRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - long status; + longinRecord *prec = (longinRecord *) pinp->precord; + long status = dbGetLink(pinp, DBR_LONG, &prec->val, 0, 0); - status = dbGetLink(&prec->inp, DBR_LONG, &prec->val, 0, 0); if (!status && dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); + return status; +} + +static long read_longin(longinRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + return status; } diff --git a/src/std/dev/devLsiSoft.c b/src/std/dev/devLsiSoft.c index aadd48f0d..8ec5ea2fa 100644 --- a/src/std/dev/devLsiSoft.c +++ b/src/std/dev/devLsiSoft.c @@ -24,14 +24,25 @@ static long init_record(lsiRecord *prec) return 0; } -static long read_string(lsiRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - long status = dbGetLinkLS(&prec->inp, prec->val, prec->sizv, &prec->len); + lsiRecord *prec = (lsiRecord *) pinp->precord; + long status = dbGetLinkLS(pinp, prec->val, prec->sizv, &prec->len); if (!status && dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); + + return status; +} + +static long read_string(lsiRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); return status; } diff --git a/src/std/dev/devMbbiDirectSoft.c b/src/std/dev/devMbbiDirectSoft.c index 27dd2eb1f..8160bdfad 100644 --- a/src/std/dev/devMbbiDirectSoft.c +++ b/src/std/dev/devMbbiDirectSoft.c @@ -54,13 +54,25 @@ static long init_record(mbbiDirectRecord *prec) return 0; } -static long read_mbbi(mbbiDirectRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - if (!dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0)) { + mbbiDirectRecord *prec = (mbbiDirectRecord *) pinp->precord; + + if (!dbGetLink(pinp, DBR_USHORT, &prec->val, 0, 0)) { prec->udf = FALSE; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return 2; } + +static long read_mbbi(mbbiDirectRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devMbbiSoft.c b/src/std/dev/devMbbiSoft.c index 406e8b6ec..b7411aea4 100644 --- a/src/std/dev/devMbbiSoft.c +++ b/src/std/dev/devMbbiSoft.c @@ -54,14 +54,26 @@ static long init_record(mbbiRecord *prec) return 0; } -static long read_mbbi(mbbiRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - if (!dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0)) { + mbbiRecord *prec = (mbbiRecord *) pinp->precord; + + if (!dbGetLink(pinp, DBR_USHORT, &prec->val, 0, 0)) { prec->udf = FALSE; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return 2; } + +static long read_mbbi(mbbiRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devMbbiSoftRaw.c b/src/std/dev/devMbbiSoftRaw.c index ffe0b00f7..ddaecfc29 100644 --- a/src/std/dev/devMbbiSoftRaw.c +++ b/src/std/dev/devMbbiSoftRaw.c @@ -58,13 +58,25 @@ static long init_record(mbbiRecord *prec) return 0; } -static long read_mbbi(mbbiRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - if (!dbGetLink(&prec->inp, DBR_LONG, &prec->rval, 0, 0)) { + mbbiRecord *prec = (mbbiRecord *) pinp->precord; + + if (!dbGetLink(pinp, DBR_LONG, &prec->rval, 0, 0)) { prec->rval &= prec->mask; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return 0; } + +static long read_mbbi(mbbiRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devSASoft.c b/src/std/dev/devSASoft.c index 84c31c5a6..b197f7eff 100644 --- a/src/std/dev/devSASoft.c +++ b/src/std/dev/devSASoft.c @@ -60,18 +60,19 @@ static long init_record(subArrayRecord *prec) return status; } -static long read_sa(subArrayRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { + subArrayRecord *prec = (subArrayRecord *) pinp->precord; long nRequest = prec->indx + prec->nelm; long ecount; if (nRequest > prec->malm) nRequest = prec->malm; - if (dbLinkIsConstant(&prec->inp)) + if (dbLinkIsConstant(pinp)) nRequest = prec->nord; else - dbGetLink(&prec->inp, prec->ftvl, prec->bptr, 0, &nRequest); + dbGetLink(pinp, prec->ftvl, prec->bptr, 0, &nRequest); ecount = nRequest - prec->indx; if (ecount > 0) { @@ -89,7 +90,17 @@ static long read_sa(subArrayRecord *prec) if (nRequest > 0 && dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); return 0; } + +static long read_sa(subArrayRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devSiSoft.c b/src/std/dev/devSiSoft.c index a969185b7..b1f3255f4 100644 --- a/src/std/dev/devSiSoft.c +++ b/src/std/dev/devSiSoft.c @@ -55,17 +55,27 @@ static long init_record(stringinRecord *prec) return 0; } -static long read_stringin(stringinRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { - long status; + stringinRecord *prec = (stringinRecord *) pinp->precord; + long status = dbGetLink(pinp, DBR_STRING, prec->val, 0, 0); - status = dbGetLink(&prec->inp, DBR_STRING, prec->val, 0, 0); if (!status) { - if (!dbLinkIsConstant(&prec->inp)) + if (!dbLinkIsConstant(pinp)) prec->udf = FALSE; if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return status; } + +static long read_stringin(stringinRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +} diff --git a/src/std/dev/devWfSoft.c b/src/std/dev/devWfSoft.c index 35ddf73b6..124f615c9 100644 --- a/src/std/dev/devWfSoft.c +++ b/src/std/dev/devWfSoft.c @@ -61,10 +61,11 @@ static long init_record(waveformRecord *prec) return status; } -static long read_wf(waveformRecord *prec) +static long readLocked(struct link *pinp, void *dummy) { + waveformRecord *prec = (waveformRecord *) pinp->precord; long nRequest = prec->nelm; - long status = dbGetLink(&prec->inp, prec->ftvl, prec->bptr, 0, &nRequest); + long status = dbGetLink(pinp, prec->ftvl, prec->bptr, 0, &nRequest); if (!status && nRequest > 0) { prec->nord = nRequest; @@ -72,7 +73,17 @@ static long read_wf(waveformRecord *prec) if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + dbGetTimeStamp(pinp, &prec->time); } return status; } + +static long read_wf(waveformRecord *prec) +{ + long status = dbLinkDoLocked(&prec->inp, readLocked, NULL); + + if (status == S_db_noLSET) + status = readLocked(&prec->inp, NULL); + + return status; +}