EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields
From: Andrew Johnson <[email protected]>
To: <[email protected]>
Date: Tue, 3 May 2016 14:15:09 -0500
Hi Dehong,

On 05/03/2016 12:31 PM, Zhang, Dehong wrote:
> From the name, dbScanLock() seems to be for updating (writing) requests from outside
> the record.  Of course the record support itself can also call it, when the record wants to
> update itself, to block updating requests from outside.  Is it easy to let the CA server
> also call it when the CA server wants to reply to "caget" or broadcast to the "camonitor"
> list.

You are mistaken there, dbScanLock() is always called before *anything*
accesses a record field, for either reading or writing data. For CA
requests the path from the RSRV server is always via
    db_get_field() => dbGetField() => dbScanLock()
no matter whether the request is directly from a CA Get request or from
the thread at the low-priority end of an event queue that is sending out
a monitor update. A similar path applies to CA Put requests, and for
record scanning dbScanLock() is called before entering the record's
process() routine.

The reason why for arrays and string values the alarm+timestamp data may
come from a different update than the value data is that the
alarm+timestamp are saved into the event queues by the call to
db_post_events() inside the record's process() routine, but the objects
we put onto those queues are too small to hold more than 8 bytes of
value data. Every CA client gets an event queue with storage for at
least 128 of these objects, so we don't want to make them too large.

For the larger data types the queue instead stores a pointer to the
original data, and when the objects are read out of the queues by the
low-priority threads that forward them to each client they call
db_get_field() a second time (the first time was on entry to the queue)
which again locks the record before extracting just the value data from
the stored pointer. The alarm+timestamp from the event queue are
provided in the db_field_log object pflin that is also passed to
db_get_field(). However while the update was waiting on the event queue
the record was unlocked, so it is possible for another thread to lock
the record and cause it to process first, thus changing the data in the
array/string being monitored.

Note also that if you have 2 different CA clients monitoring the same
PV, it is possible for a single db_post_events() call to result in the 2
clients seeing different data for the same alarm+timestamp, since each
client has its own queue and and its own low-priority thread that reads
out the event queue and forwards the data to the appropriate TCP socket.
The low priority threads are not synchronized, they each have to call
db_get_field() independently and at different times (in order to get
access to the record data they must take the lock, which is a mutex so
only one of them can "own" the record at once even if they're only
reading from it).


It is actually relatively easy to increase the size of the db_field_log
object so it can store a 40 character DBF_STRING value, but making it
larger than that would have no effect other than wasting memory. IOC
memory sizes have grown since the event queue code was written, and we
should now be able to afford the extra RAM needed by the IOC (32 bytes
extra * 128 items = 4KB minimum per CA client).

HTH,

- Andrew

-- 
Arguing for surveillance because you have nothing to hide is no
different than making the claim, "I don't care about freedom of
speech because I have nothing to say." -- Edward Snowdon

Replies:
Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Till Straumann
References:
Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Zhang, Dehong
RE: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Mooney, Tim M.
Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Till Straumann
Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Zhang, Dehong
Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Till Straumann
RE: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Kim, Kukhee
Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Zhang, Dehong

Navigate by Date:
Prev: RE: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Kim, Kukhee
Next: EPICS and CANbus? Grelle, Austin L.
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Kim, Kukhee
Next: Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields Till Straumann
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 15 Jul 2016 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·