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 | 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 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Re: Lock/Mutex to prevent "caget" from cutting in between updating multiple fields |
From: | Till Straumann <[email protected]> |
To: | "Mooney, Tim M." <[email protected]>, "Zhang, Dehong" <[email protected]>, "[email protected]" <[email protected]> |
Date: | Fri, 29 Apr 2016 23:54:57 -0700 |
I would be a little bit more
conservative and stress that this kind of thinking is very
dangerous. Your scenario might work on a real-time system with properly assigned priorities "most of the time". However, if you have e.g., an unprivileged IOC running under linux then it will use a time-sharing scheduler where every thread essentially has the same priority and can be preempted when it's time-slice is consumed. Under such a scenario it can happen that record processing is pre-empted and the IOC side of caget could interfere. Even under a RTOS your assumption is dangerous: assume that the caget thread indeed has a lower priority than the record-processing one. It is still possible for the effective priority of caget to be raised above record-processing e.g., as a result of caget holding a priority-inheriting mutex on which a high-priority thread is waiting and then caget could preempt record-processing. Properly written code should IMHO use either lockfree algorithms or synchronization devices and never rely on assumptions about scheduling for synchronization. The good news are that EPICS is properly written code in that sense and caget respects the database locking. So it is ensured that you never get a field value with an incorrect timestamp since both are read 'atomically' by CA. OTOH, you cannot read multiple fields atomically with caget (AFAIK). I.e., if your record has fields 'A' and 'B' then you cannot be sure caget(A); caget(B) yields a consistent set. One could be new, one old. There are work-arounds: - you can use an 'array' field. All elements of an array are accessed by CÁ atomically. E.g., when you caget a waveform record then you always get a consistent waveform (with a consistent timestamp), never a half-old, half-new one. - you could introduce locking semantics yourself. E.g., a 'LOCK' field. Record processing may not modify the essential fields while this is set. The user then has to caput(LOCK, 1); caget(FIELD1); caget(FIELD2), ...; caput(LOCK, 0); but you have to rely on the user observing the semantics. -- Till On 04/29/2016 09:56 PM, Mooney, Tim M. wrote:
|