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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user