Modify soft devices to synchronize TSEL=-2 timestamps

Use dbLinkDoLocked() to ensure a timestamp set by TSEL=-2
comes from the same update as the value.
This commit is contained in:
Andrew Johnson
2017-04-19 16:50:38 -05:00
parent d2db634ed2
commit 89f13aa51b
15 changed files with 236 additions and 62 deletions

View File

@@ -20,6 +20,17 @@
-->
<h3>Synchronized Timestamps with TSEL=-2</h3>
<p>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.</p>
<h3>Device Support Address Type <tt>JSON_LINK</tt></h3>
<p>Device support may be written to expect hardware addresses in the new

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}