Hi Heinrich,
Thanks for finding this problem and suggesting one solution.
A recap of the problem for those who have not followed it: if 2 or
more
interrupts come in rapid sucession to asyn device support, it can
result
in the the device support routine (called from scanIoRequest record
processing) calling the drivers read() routine when it should not
do so.
It seems like there are 2 possible solutions.
Solution 1) (basically Heinrich's suggestion):
Ignore callbacks that happen before the previous callback has finished
executing processCommon in asyn device support. The right way to do
this would be to add a mutex to protect access to the gotValue and
data
fields. This has the disadvantage of missing data when interrupts
come
close together, even if the system could handle the average interrupt
rate.
Solution 2).
Rather than have the callback routine call scanIoRequest, have it
directly call dbScanLock and pr->process. This way the callback and
record processing are done in the same thread, and there is no need
for
a mutex. The consequences of this solution are:
- There is no missed data, as long as the system can keep up with the
average data rate.
- The callback routine must not be called at interrupt level, because
the record will not be processed in a separate callback thread.
However, the asyn documentation is already explicit that the
pasynManager->interruptStart routine cannot be called at interrupt
level, so the callback routine cannot be running at interrupt level.
- The asyn driver must have already created a thread that the callback
will run in. Under the new scheme this callback thread will not just
copy the data to the device support private, set a flag and call
scanIoRequest, but it will actually process the record. It will also
process any records that this record forward links to. This could
require more stack, and will take somewhat more time.