Hi Folks,
A colleague puzzled me with a db that shows surprising behavior.
An aSub record is triggered periodically though a CP input link. It
looks up if it needs re-initialization (the user can press a button to
request that). If yes it does an additional calculation. After
processing it resets the record that requested the re-initialization.
See the attached .db file.
Usually when the user presses the button to re-initialize, the aSub does
the additional calculation once and then goes back to normal processing.
But the calculation may may take a bit too long -- longer than the rate
of the CP input link monitors. In that case, the record never leaves
initialization mode!
I have simulated the slow calculation with the attached subroutine code
which simply waits. (I know that is is a bad idea to wait in a
synchronous subroutine. The original code does not wait but calculates.)
I think that this is an effect of lock sets because the "mode" record is
as well input being processed by a caput as well as output of the aSub
record. But is this the intended behavior?
The CP monitor finds the record busy (PACT=1) and arranges for
re-processing when the record is done. But should not the FLNK be
processed and the mode record go to 1 before the aSub runs again?
Any idea how to fix this? Is it necessary to make the subroutine
asynchonous? Making the links from and to "mode" CA links does not fix
it. Scanning the aSub itself with ".1 second" does not show the strange
behavior, it simply delays the scan thread.
Puzzle for the weekend...
Dirk
record(calc, "trigger") {
field(INPA, "trigger")
field(CALC, "A+1")
field(SCAN, ".1 second")
}
record(aSub, "slow_aSub") {
field(SNAM, "slow_aSub")
field(INPA, "trigger CP")
field(INPB, "mode")
field(INPD, ".2")
field(FLNK, "seq")
}
record(seq, "seq") {
field(DOL1, "1")
field(LNK1, "mode")
}
record(bo, "mode") {
field(ZNAM, "uninitialized")
field(ONAM, "initialized")
}
#include <stdio.h>
#include <aSubRecord.h>
#include <epicsThread.h>
void slow_aSub(aSubRecord* rec)
{
double delay = *(double*)rec->d;
int mode = *(double*)rec->b;
static int i=0;
printf("%3d: entering subroutine: mode=%d\n", i, mode);
if (mode == 0)
{
printf("%3d: delay %.3g sec\n", i, delay);
epicsThreadSleep(delay);
printf("%3d: done\n", i);
}
i++;
}
- Replies:
- RE: Puzzled with lockset(?) problem Mark Engbretson
- Re: Puzzled with lockset(?) problem Mooney, Tim M.
- Re: Puzzled with lockset(?) problem Michael Davidsaver
- Navigate by Date:
- Prev:
Re: Channel Archiver compilation error Michael Davidsaver
- Next:
RE: Puzzled with lockset(?) problem Mark Engbretson
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
<2017>
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: Channel Archiver compilation error Heinz Junkes
- Next:
RE: Puzzled with lockset(?) problem Mark Engbretson
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
<2017>
2018
2019
2020
2021
2022
2023
2024
|