From: Mario de S. <ms...@fe...> - 2003-05-27 10:45:33
|
On Mon, 2003-05-26 at 23:14, John Kasunich wrote: > On Monday 26 May 2003 09:29 am, Mario de Sousa wrote: > > On Mon, 2003-05-26 at 00:25, John Kasunich wrote: > > > Hello: > > > I'm trying to understand how plc_update(), plc_get(), and plc_set() would > > > interact in a realtime environment. > > > In particular, I'm concerned about the use of semaphores for access to > > > the global memory map. > > (...) > > > Now assume that the hardware interrupt was instead from an I/O device, > > > and results in a real-time task starting to service the device. When the > > > real-time task calls plc_update() to access the global memory map, it > > > will see the locked semaphore. What to do? > > (...) > > I agree with your interpretation of the code... > > Nevertheless, if you look at the big picture, you will see we have no > > way around it. You are trying to have a RT and a non-RT task share a > > common resource. > > I think there is a way around it, depending on how you define the "common > resource". Currently MatPLC looks at the entire global memory map as > the shared resource, that's why plc_update() wraps it's entire loop in a > semaphore. I contend that if you view each individual I/O point as a > shared resource, the problem can be solved. > (...) > > Note no semaphores, therefore no risk of priority inversion or deadlock, > and no need for priority inheritance. No data point is ever read and then > written back, so no risk of data corruption by an interrupt at the wrong time. > Each data point is read or written as a single uninterruptable operation. > Of course nothing is free. Hi John, Yes, this is an interesting option. Please note nevertheless that doing it this way raises the possibility of inconsistencies. Arghhh! The dreaded word!!! Let me explain in more detail exactly what I mean, which, BTW, I believe is similar to what Herman was trying to drive at in previous posts. Your option guarantees the consistency of each data point considered individually, nevertheless the consistency between data points is no longer guaranteed. Say, for example, that you are driving a 3 axis machine. Your feedback includes 3 analogue signals with the position of each axis. The driver of a card reads all three analogue signals simultaneously (or as simultaneously as the card hardware allows), and updates each point to the MatPLC individually. Now, it may happen that the routine doing the contour following algorithm will read the data points of each axis, using the new data for 2 of the axis, and the old version of the third axis. The algorithm will then run with 'inconsistent' data. Well, my idea is that this is inconsistent data, but you maybe your EMC program will run correctly like this? (see note *1) Maybe: (a) you are disregarding this scenario (i.e. you are aware of it) because it seems obvious it will not affect your algorithm? (b) because you are expecting your algorithm to execute in lock step with the driver reading the inputs, which means that the inputs will always get updated correctly before the algorithm gets to read them? If (b) is correct, please consider that this is the same as running the MatPLC in shared access mode. It is exactly why I decided to implement it. Anyway, to sum things up, I wouldn't really like to do the plc_update() your way because of the semantics that are expected of a normal PLC (read inputs - run logic - update outputs). Without the semaphore locking, the MatPLC is little more than a scratch pad to which every module may read and write data. > Does this seem reasonable? I know that the performance and global > map size hit is hard to take - I personally think the original plc_update() > is a very nice piece of code, very fast and clean. Thanks, but unfortunately I can't take credit for it. My memory may be playing tricks on me (this was quite some time ago, at a hectic moment of the list), but I do believe that the main idea came from Herman, and the first version of the code from Jiri. Anyway, if we do decide to implement your version, it shouldn't be too hard to do it, even including the sharing of data points only among data points belonging to the same module. BTW, you guys seem to be delving into the details of our code, and I believe you are the first people to do it coming from outside. Could you give me your personal opinions on the code itself, and the quality of the comments? Note that I am not looking for praise, but rather for constructive criticism. If you believe the code is under par and the comments worthless please don't hold back. Just please do explain why and how you would do it better. The greatest good I personally get out of all this is to keep learning from others, and from the manuals I end up reading too ;-). Cheers, Mario. (*1) The difference between this scenario and the one mentioned by Herman is that in Herman's version the inconsistency is between data updated by two or more modules (which I don't consider inconsistent), while in this scenario the data inconsistency is between data updated by the same module! |