Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  <20072008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  <20072008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020 
<== Date ==> <== Thread ==>

Subject: ASYN - calling read after interrupt - fix :)
From: Heinrich du Toit <heinrichdt@tlabs.ac.za>
To: TechTalk EPICS <tech-talk@aps.anl.gov>
Date: Wed, 10 Oct 2007 10:19:08 +0200
Hi there

A while ago I posted a question asking why asyn calls my read and write
routines after interrupts. And it was said it shouldn't.

Well I think I figured it out.

The interrupt callback in asyn does pPvt->gotValue = 1.
This is then suppose to let the process part just put the value in and
not call read.

Well the problem is this:
If you where to call interrupts very close to each other (something not
always avoidable) then gotvalue = 1 and scanIoRequest is called once for
each interrupt.
This seems to mean process is called once for each interrupt.

Well the first process see gotvalue = 1 and skips the read part. This
then works correctly and sets gotvalue = 0.
Now the second and so on process execution finds gotvalue = 0 and then
calls the read routine. 
This offcourse only happens if the second interruptCallback executes
before the queued process request can run.

The fix is actually pretty simple it seems:

in devAsynFloat64Array.c I changed the interruptCallbackInput to this:


static void interruptCallbackInput(void *drvPvt, asynUser *pasynUser, 
                epicsFloat64 *value, size_t len)
{
    devAsynWfPvt *pPvt = (devAsynWfPvt *)drvPvt;
    waveformRecord *pwf = (waveformRecord *)pPvt->pr;
    int i;
    epicsFloat64 *pfloat64 = (epicsFloat64 *)pwf->bptr;

    asynPrintIO(pPvt->pasynUser, ASYN_TRACEIO_DEVICE,
        (char *)value, len*sizeof(epicsFloat64),
        "%s devAsynFloat64Array::interruptCallbackInput\n",
        pwf->name);
    if (len > pwf->nelm) len = pwf->nelm;
    for (i=0; i<len; i++) pfloat64[i] = value[i];
    pPvt->nord = len;
    if (pPvt->gotValue = 0){
      pPvt->gotValue = 1;
      scanIoRequest(pPvt->ioScanPvt);
    }
}


(See the last 4 lines)


I'm not sure if this is 100% bullet proof

As technically the interrupt can run while gotValue is still = 1 but
pwf->nord = pPvt->nord is already executed in processCommon.

so to make this 100% bullet proof a mutex is needed I believe.

But I think doing this:



static long processCommon(dbCommon *pr)
{
    devAsynWfPvt *pPvt = (devAsynWfPvt *)pr->dpvt;
    waveformRecord *pwf = (waveformRecord *)pr;
    int status;

    if (!pPvt->gotValue && !pr->pact) {   /* This is an initial call
from record */
        if(pPvt->canBlock) pr->pact = 1;
        status = pasynManager->queueRequest(pPvt->pasynUser, 0, 0);
        if((status==asynSuccess) && pPvt->canBlock) return 0;
        if(pPvt->canBlock) pr->pact = 0;
        if (status != asynSuccess) {
            asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR,
                "%s processCommon, error queuing request %s\n",
                 pr->name, pPvt->pasynUser->errorMessage);
            recGblSetSevr(pr, READ_ALARM, INVALID_ALARM);
        }
    }
    if (pPvt->gotValue){
      pPvt->gotValue = 0;
      pwf->nord = pPvt->nord;
    }
    pPvt->gotValue = 0;
    return 0;
} 

Might improve things a little.


I'm not sure if I got all my facts correct since I'm still not 100% sure
how the threading thing works inside ASYN.

But this seems atleast on my initial checks as if it stop the exstra
read commands that seem to happen between bursts of interrupts :)

-Heinrich




Replies:
Re: ASYN - calling read after interrupt - fix :) Heinrich du Toit
RE: ASYN - calling read after interrupt - fix :) Mark Rivers

Navigate by Date:
Prev: CAMAC IO Szalata, Zenon M.
Next: Re: ASYN - calling read after interrupt - fix :) Heinrich du Toit
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  <20072008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020 
Navigate by Thread:
Prev: Re: CAMAC IO Luedeke Andreas
Next: Re: ASYN - calling read after interrupt - fix :) Heinrich du Toit
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  <20072008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020 
ANJ, 10 Nov 2011 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·