* Advice, tasking and hardware @ 2016-05-25 21:24 patrick 2016-05-26 1:09 ` Jeffrey R. Carter ` (2 more replies) 0 siblings, 3 replies; 33+ messages in thread From: patrick @ 2016-05-25 21:24 UTC (permalink / raw) Hi Everyone I don't want to troll the list, I need some honest advice and I need to be honest about my goals, I hope I don't offend anyone. I spent almost every night in 2012 studying Ada. I bought/printed 53 lbs of Ada books. I struggled to find a GUI binding I liked and I struggled to work with C. I wanted to use Ada to avoid using C and I didn't understand C well. For the past few years I have been using GnuCOBOL. I absolutely love it. It is much easier to interface to C with and it compiles to intermediate C so it's easier to see what is happening rather then going from Ada to Assembly. While the interfaces.COBOL package is quite outdated and does not have knowledge of modern COBOL it does work well and I can mix the two languages. I am thinking about writing a backend in Ada again. I could do it in COBOL but tasking and exceptions sound like a wise idea. I feel I am going to have an easier time with C this time around. I don't have any experience with tasking though and while I have many examples of tasking in my books, none of them seem to call low level functions such as drivers or driver-like functions. I am planning on using the Linux-GPIB library. Sorry for the long introduction, to the point... Do you have any examples of tasking calling low level functions? Spark doesn't use tasking, are there many dangers in using tasking with hardware? Would it be wise to wrap C driver calls in a protected object or are most drivers in Linux thread safe and suitable for being called from different threads? Could anyone give me some general guidelines? any pitfalls to avoid before I set out to attempt this? Thanks for reading-Patrick ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-25 21:24 Advice, tasking and hardware patrick @ 2016-05-26 1:09 ` Jeffrey R. Carter 2016-05-26 8:13 ` Simon Wright 2016-05-26 7:26 ` Dmitry A. Kazakov 2016-05-28 0:25 ` rieachus 2 siblings, 1 reply; 33+ messages in thread From: Jeffrey R. Carter @ 2016-05-26 1:09 UTC (permalink / raw) On 05/25/2016 02:24 PM, patrick@spellingbeewinnars.org wrote: > > I struggled to find a GUI binding I liked and I struggled to work with C. I > wanted to use Ada to avoid using C and I didn't understand C well. > > For the past few years I have been using GnuCOBOL. I absolutely love it. It > is much easier to interface to C with and it compiles to intermediate C so > it's easier to see what is happening rather then going from Ada to Assembly. > While the interfaces.COBOL package is quite outdated and does not have > knowledge of modern COBOL it does work well and I can mix the two languages. I'm not sure what you're getting at here. A compiler's intermediate code is usually of no interest to a developer. I've done more interfacing to C from Ada than I'd like, and it's usually straightforward. > I don't have any experience with tasking though and while I have many > examples of tasking in my books, none of them seem to call low level > functions such as drivers or driver-like functions. I am planning on using > the Linux-GPIB library. Every call to a subprogram in Ada, be it high-level or low-level, is made by a task. The elaboration and the the main-program subprogram are executed by the environment task. Any subprogram calls made, directly or indirectly, by the main program are made by the environment task. I see no reason why you should expect calls from user-defined tasks to be any different. > Spark doesn't use tasking, are there many dangers in using tasking with > hardware? SPARK 2014 includes Ravenscar tasking. (http://docs.adacore.com/spark2014-docs/html/lrm/tasks-and-synchronization.html) I don't know how you'd use tasking without hardware. Concurrent development is a superset of sequential development, and some who are competent at the latter have difficulty with the former, even after extensive experience. Deadlock and race conditions are common dangers if you don't understand concurrency (and sometimes if you do). > Would it be wise to wrap C driver calls in a protected object or are most > drivers in Linux thread safe and suitable for being called from different > threads? That will depend on the library you're binding to, and you should refer to its documentation. If in doubt, wrapping the calls in a PO will ensure they are made sequentially. -- Jeff Carter "He didn't get that nose from playing ping-pong." Never Give a Sucker an Even Break 110 ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 1:09 ` Jeffrey R. Carter @ 2016-05-26 8:13 ` Simon Wright 0 siblings, 0 replies; 33+ messages in thread From: Simon Wright @ 2016-05-26 8:13 UTC (permalink / raw) "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes: >> Spark doesn't use tasking, are there many dangers in using tasking >> with hardware? > > SPARK 2014 includes Ravenscar > tasking. (http://docs.adacore.com/spark2014-docs/html/lrm/tasks-and-synchronization.html) But SPARK GPL 2015 doesn't support tasking. We live in hope that SPARK GPL 2016 will. I'm not sure of the best way to delegate tasking to the non-SPARK part of a program while maintaining SPARK for as much as possible. I suppose you'd have to be very restrained in your use of tasking (e.g. perhaps only use Ravenscar tasking, have the task call a SPARK subprogram to do the work). I had a program with a large PO/task job dispatcher with multiple entries and requeues in the PO, which was hugely improved when I had to reimplement under Ravenscar. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-25 21:24 Advice, tasking and hardware patrick 2016-05-26 1:09 ` Jeffrey R. Carter @ 2016-05-26 7:26 ` Dmitry A. Kazakov 2016-05-26 16:41 ` patrick 2016-05-26 19:35 ` Jeffrey R. Carter 2016-05-28 0:25 ` rieachus 2 siblings, 2 replies; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-05-26 7:26 UTC (permalink / raw) On 25/05/2016 23:24, patrick@spellingbeewinnars.org wrote: > Do you have any examples of tasking calling low level functions? Just call it as any other subprogram. > Spark doesn't use tasking, are there many dangers in using tasking with hardware? Dangers to the hardware? (:-)) Pre-/postcondition based proofs (SPARK's business) are pretty much orthogonal to tasking issues. Schedulability and other tasking stuff has a non-functional aspect whereas proofs are about functional issues. If you are concerned about static analysis regarding tasks, see Ravenscar profile. > Would it be wise to wrap C driver calls in a protected object or are > most drivers in Linux thread safe and suitable for being called from > different threads? Driver calls are thread safe. It does not mean that they are safe from the higher level semantics point of view. E.g. it is safe to delete a file in one process and open it in another, safe at the filesystem level, but unsafe at the application level. Anyway, you never call driver operations from a protected action because it is a "potentially blocking" call. Even if not blocking in the sense of being asynchronous to the CPU/memory bus cycles, accessing hardware might be quite slow, e.g. reading/writing a hardware port, dual-ported memory access etc. A protected action is considered logically instant. If you want interlocking for doing blocking calls use a mutex etc. A mutex implementation based on protected objects is two actions: Seize and Release. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 7:26 ` Dmitry A. Kazakov @ 2016-05-26 16:41 ` patrick 2016-05-26 17:56 ` Dmitry A. Kazakov 2016-05-26 20:35 ` Jeffrey R. Carter 2016-05-26 19:35 ` Jeffrey R. Carter 1 sibling, 2 replies; 33+ messages in thread From: patrick @ 2016-05-26 16:41 UTC (permalink / raw) Hi Guys Thanks for the feedback this is very helpful :) I work with scientific instruments. I have been trying to write an application to control this instrumentation on and off for many years. It's back on. I doubt that any of the software I see in my industry is written in Ada, there is no real exception handling. Joel is a an exception, they work with high end mass spectrometers and were featured in an Adacore commercial. If there is a hardware failure of any kind software in this business just locks up silently or there is a non-descriptive error like "instrument error", even when there are multiple instruments networked into a system. Does this approach sound logical for a first attempt with tasking: I could write a mostly single threaded application that used tasking for error detection/handling only. I could queue tasks. One would be called just before calling into a driver. The task would delay for a given amount of time and if the call to the driver blocked unexpectedly the task would reach a point were it will notify the user with a detailed error message. If the driver call did not block another task would be called to signal that the driver call completed on time and the first task would be notified at rendezvous that it was on time and the tasks would queue again and wait for the next driver call. This may not be a full use of Ada but it would be better then what's currently being used on the market in my industry. Thanks again-Patrick ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 16:41 ` patrick @ 2016-05-26 17:56 ` Dmitry A. Kazakov 2016-05-26 20:35 ` Jeffrey R. Carter 1 sibling, 0 replies; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-05-26 17:56 UTC (permalink / raw) On 2016-05-26 18:41, patrick@spellingbeewinnars.org wrote: > I work with scientific instruments. I have been trying to write an > application to control this instrumentation on and off for many years. > It's back on.. > > I doubt that any of the software I see in my industry is written in > Ada, there is no real exception handling. It is the "state of the art" in all automation industry. There is practically no diagnostics at all. The software is written by technical engineers with no understanding of software and protocols design. > If there is a hardware failure of any kind software in this business > just locks up silently or there is a non-descriptive error like > "instrument error", even when there are multiple instruments networked > into a system. It is a software failure most of the time. The hardware is usually just fine. > Does this approach sound logical for a first attempt with tasking: > > I could write a mostly single threaded application that used tasking > for error detection/handling only. For handling timeouts, you mean. > I could queue tasks. One would be called just before calling into a > driver. The task would delay for a given amount of time and if the call > to the driver blocked unexpectedly the task would reach a point were it > will notify the user with a detailed error message. If the driver call > did not block another task would be called to signal that the driver > call completed on time and the first task would be notified at > rendezvous that it was on time and the tasks would queue again and wait > for the next driver call. You should beware using vendor libraries, many of them are not thread-safe. Some require that all calls be from the same task. E.g. if you open the device and get a handle to it, then all subsequent operations must occur on the context of the same thread. [ Under Linux and Windows Ada task corresponds to a thread ] A typical Ada design is writing an interface object encapsulating an I/O task that does all exchange with the device. That is when you have a half-duplex communication with the device. [ Software designed by technical engineers cannot go full duplex, it is an alien concept to them... ] The calls involving communication to the device will do an entry call to the I/O task, e.g. procedure Write_Something ( Device : in out Device_Type; Data : Data_Type; Timeout : Duration ) is Deadline : Time := Clock + Timeout; begin select Device.IO_Task.Initiate_Write (Data); -- Begin I/O or delay until Deadline; raise Timeout_Error with "Device is busy"; end select; select Device.IO_Task.Wait_For_Completion; -- Wait for I/O to end or delay until Deadline; raise Timeout_Error with "Device I/O is stalled"; end select; end Write_Something; type IO_State is (Idle, Write_Completed); task IO_Task (Device : not null access Device_Type'Class) is entry Initiate_Write (Data : Data_Type); entry Wait_For_Completion; entry Shut_Down; end IO_Task; task body IO_Task is Data_To_Write : Data_Type; State : IO_State := Idle; begin -- Open device etc loop select accept Initiate_Write (Data : Data_Type) do Data_To_Write := Data; -- Store data end; Call_Driver (Data); -- This may block forever State := Completed; or accept Wait_For_Completion do if State = Write_Completed then State := Idle; else raise Use_Error with "No I/O pending"; end if; or accept Shut_Down; exit; end select; end loop; -- Close device, cleanup end IO_Task; Of course with this there is no way to do anything useful after a timeout. Unless the library supports closing the device from outside. E.g. socket library allows closing the socket from another thread to terminate blocking socket I/O. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 16:41 ` patrick 2016-05-26 17:56 ` Dmitry A. Kazakov @ 2016-05-26 20:35 ` Jeffrey R. Carter 1 sibling, 0 replies; 33+ messages in thread From: Jeffrey R. Carter @ 2016-05-26 20:35 UTC (permalink / raw) On 05/26/2016 09:41 AM, patrick@spellingbeewinnars.org wrote: > > I could write a mostly single threaded application that used tasking for > error detection/handling only. > > I could queue tasks. One would be called just before calling into a driver. > The task would delay for a given amount of time and if the call to the driver > blocked unexpectedly the task would reach a point were it will notify the > user with a detailed error message. If the driver call did not block another > task would be called to signal that the driver call completed on time and the > first task would be notified at rendezvous that it was on time and the tasks > would queue again and wait for the next driver call. It sounds like you're interested in a "watchdog", which does something if an action doesn't complete in time. Possible ways to implement this include the selective abort (ATC), a timing event, or using a task. ATC is simple: select delay until Deadline; -- Whatever reporting or corrective action is needed then abort Perform_Action; -- Whatever success reporting is needed end select; If the delay expires, an attempt is made to abort the "then abort" part. Obviously you wouldn't use it if you don't want to abort the call. Note also that there are things that cannot be aborted, so this may not work if Perform_Action contains any of them. You should review ARM 9.8 to see if they apply to you. http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-9-8.html A timing event (ARM D.15) has an associated handler, which is a protected procedure. Depending on what your compiler will let you get away with in a protected operation, and how concerned you are about portability, you may be able to put your reporting/recovery in the handler, and this is almost as simple as ATC, though it's a bit harder to find out what the recovery options are. If you want to do any potentially blocking operations, to be portable, your handler needs to simply open the barrier on an entry of the same PO, and a task that waits on that entry does the actual recovery. If you're going to do that, it's simpler and clearer to just use a task. You'd use a timing event this way Event.Set_Handler (At_Time => Deadline, Handler => PO.Handler'access); Perform_Action; Event.Cancel_Handler (Cancelled => Canceled); Deadline needs to have enough slack in it to prevent a race condition between the handler being invoked and Cancel_Handler being called. A task would look like task Watchdog is entry Start (Deadline : in Time); entry Stop; end Watchdog; and is used similarly to a timing event Watchdog.Start (Deadline => Deadline); Perform_Action; Watchdog.Stop; and has a similar comment about race conditions. The body of Watchdog is like Forever : loop select accept Start (Deadline : in Time) do Expiry := Deadline; end Start; or terminate; end select; select accept Stop; or delay until Expiry; -- Recovery end select; end loop Forever; Note that this could be generic on the recovery action. -- Jeff Carter "This trial is a travesty. It's a travesty of a mockery of a sham of a mockery of a travesty of two mockeries of a sham. ... Do you realize there's not a single homosexual on that jury?" Bananas 27 ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 7:26 ` Dmitry A. Kazakov 2016-05-26 16:41 ` patrick @ 2016-05-26 19:35 ` Jeffrey R. Carter 2016-05-26 20:51 ` patrick 2016-05-27 7:50 ` Dmitry A. Kazakov 1 sibling, 2 replies; 33+ messages in thread From: Jeffrey R. Carter @ 2016-05-26 19:35 UTC (permalink / raw) On 05/26/2016 12:26 AM, Dmitry A. Kazakov wrote: > > If you want interlocking for doing blocking calls use a mutex etc. A mutex > implementation based on protected objects is two actions: Seize and Release. To the OP: This is terrible advice. One should only use a low-level mechanism such as a semaphore when one can't achieve what one needs with the high-level mechanisms provided by the language: tasks and protected objects. Since there's no way for the compiler to know that the subprogram is potentially blocking, there's no reason not to put the call in a PO and make use of the high-level mutual exclusion it provides. Even if the system has problems with the call being in a protected operation, it's better to put a request for the call on a protected queue and have a task that gets the requests from the queue and makes the calls than to use a semaphore. -- Jeff Carter "This trial is a travesty. It's a travesty of a mockery of a sham of a mockery of a travesty of two mockeries of a sham. ... Do you realize there's not a single homosexual on that jury?" Bananas 27 ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 19:35 ` Jeffrey R. Carter @ 2016-05-26 20:51 ` patrick 2016-05-27 7:50 ` Dmitry A. Kazakov 1 sibling, 0 replies; 33+ messages in thread From: patrick @ 2016-05-26 20:51 UTC (permalink / raw) Hi Jeffery I value your advice but I also want to say that Dmitry has been a huge help to me and I have learned to trust his advice. I can't count the posts he answered for me in 2012, I won't forget his kindness. -Patrick ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-26 19:35 ` Jeffrey R. Carter 2016-05-26 20:51 ` patrick @ 2016-05-27 7:50 ` Dmitry A. Kazakov 2016-05-27 18:00 ` Simon Wright ` (2 more replies) 1 sibling, 3 replies; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-05-27 7:50 UTC (permalink / raw) On 26/05/2016 21:35, Jeffrey R. Carter wrote: > On 05/26/2016 12:26 AM, Dmitry A. Kazakov wrote: >> >> If you want interlocking for doing blocking calls use a mutex etc. A mutex >> implementation based on protected objects is two actions: Seize and Release. > > To the OP: This is terrible advice. One should only use a low-level mechanism > such as a semaphore when one can't achieve what one needs with the high-level > mechanisms provided by the language: tasks and protected objects. In practice it is not just a semaphore. The implementation protected object frequently carries higher level functions, e.g. protecting a queue of requests. BTW an explicit queue is used only in the case of asynchronous processing of requests. The rule of thumb is that if all requests are done synchronously to the caller, no task is used, only a protected interlocking object is. The entry of the protected object serves as a queue. If some requests are asynchronous, a task and a protected object are necessary. A task alone is a rare case. > Since there's > no way for the compiler to know that the subprogram is potentially blocking, > there's no reason not to put the call in a PO and make use of the high-level > mutual exclusion it provides. Even if the system has problems with the call > being in a protected operation, it's better to put a request for the call on a > protected queue and have a task that gets the requests from the queue and makes > the calls than to use a semaphore. Tasks and protected objects have advantages and disadvantages. Regarding tasks the disadvantages are: 1. You need a task. 2. Ada tasks are difficult to compose, especially to have encapsulated tasks. Task components do not work in practical cases, so a pointer to the task will be required. 3. Ada tasks have problems with termination. The termination alternative design makes is unusable in most cases. There must be Shut_Down entry instead and a caller of it as well. 4. Task objects are tricky to deallocate. You must wait for task termination before calling Unchecked_Deallocation on it. Waiting within a Finalize is no fun. 5. Tasks entries have parameter passing problems. If you don't handle everything in the rendezvous in order to release the caller as soon as possible, you need to copy parameters and store them locally. The design of the select statement prevents doing this in a structured way. E.g. select accept String_Call (Text : String) do Local_Text := Text; -- Accept scope end; declare -- Handler's scope Local_Text : String -- This does not work! begin -- Process Local_Text end; or accept ... 6. Task entries cannot return unconstrained objects. 7 + 5-6. Task design requires sometimes a very complex state machine implementation to remember the order of accepted entries. It cannot be decomposed in a structured way because tasks are not composable. Protected objects have this too but they are somewhat simpler because some handling of the states could be done at the caller's side. So in the end there could be a lot more low-level stuff regarding task maintenance, result passing, elaboration and finalization. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 7:50 ` Dmitry A. Kazakov @ 2016-05-27 18:00 ` Simon Wright 2016-05-27 19:06 ` Jeffrey R. Carter 2016-05-27 19:13 ` Shark8 2 siblings, 0 replies; 33+ messages in thread From: Simon Wright @ 2016-05-27 18:00 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > The rule of thumb is that if all requests are done synchronously to > the caller, no task is used, only a protected interlocking object > is. The entry of the protected object serves as a queue. I think Ravenscar was mentioned? if using an RTS which only supports Ravenscar, you can't have entry queues. I'm not sure whether you can mix Ravenscar and unrestricted profiles within the same partition using the full RTS? ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 7:50 ` Dmitry A. Kazakov 2016-05-27 18:00 ` Simon Wright @ 2016-05-27 19:06 ` Jeffrey R. Carter 2016-05-27 22:05 ` Randy Brukardt 2016-05-27 19:13 ` Shark8 2 siblings, 1 reply; 33+ messages in thread From: Jeffrey R. Carter @ 2016-05-27 19:06 UTC (permalink / raw) On 05/27/2016 12:50 AM, Dmitry A. Kazakov wrote: [a lot of irrelevant stuff] No response to this post is needed, since it had nothing to do with the specific point I made and to which he was apparently responding. However, there is a false statement that should be corrected. > 3. Ada tasks have problems with termination. The termination alternative design > makes is unusable in most cases. There must be Shut_Down entry instead and a > caller of it as well. I have personally written hundreds of tasks that cannot use a terminate alternative and do not have an entry to cause them to terminate, yet which terminate normally when they should. Anyone who can't see multiple ways to achieve this using only tasks and protected objects should not be considered competent to develop concurrent software. -- Jeff Carter "I'm a kike, a yid, a heebie, a hook nose! I'm Kosher, Mum! I'm a Red Sea pedestrian, and proud of it!" Monty Python's Life of Brian 77 ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 19:06 ` Jeffrey R. Carter @ 2016-05-27 22:05 ` Randy Brukardt 2016-05-27 23:09 ` Jeffrey R. Carter 0 siblings, 1 reply; 33+ messages in thread From: Randy Brukardt @ 2016-05-27 22:05 UTC (permalink / raw) "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message news:nia5lo$oik$1@dont-email.me... > On 05/27/2016 12:50 AM, Dmitry A. Kazakov wrote: > > [a lot of irrelevant stuff] > > No response to this post is needed, since it had nothing to do with the > specific > point I made and to which he was apparently responding. However, there is > a > false statement that should be corrected. > >> 3. Ada tasks have problems with termination. The termination alternative >> design >> makes is unusable in most cases. There must be Shut_Down entry instead >> and a >> caller of it as well. > > I have personally written hundreds of tasks that cannot use a terminate > alternative and do not have an entry to cause them to terminate, yet which > terminate normally when they should. Anyone who can't see multiple ways to > achieve this using only tasks and protected objects should not be > considered > competent to develop concurrent software. Huh. Most people *aren't* competent to develop concurrent software -- it's way too hard and (unlike sequential code) the compiler and language is no help. (Race conditions and deadlocks are trivial in Ada code; very little practical code doesn't have them.). But most of us have to develop such software anyway, whether or not we're competent. So I don't find that much of an argument for any point vis-a-vis concurrency. [Especially as I've never figured out how to properly shut down the tasks in any of my service programs. Maybe I could have figured out something, but it would have greatly complicated an already complicated system. Instead, I kill the process manually in the rare case that I need to restart a service (and I also have a watchdog program that kills and restarts non-responsive services, and triggers a full system reboot if that doesn't work - that probably would be needed in any case, just to keep services up as much as possible {in case of DoS bugs}). A club rather than a screwdriver, but a lot easier.] Randy. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 22:05 ` Randy Brukardt @ 2016-05-27 23:09 ` Jeffrey R. Carter 0 siblings, 0 replies; 33+ messages in thread From: Jeffrey R. Carter @ 2016-05-27 23:09 UTC (permalink / raw) On 05/27/2016 03:05 PM, Randy Brukardt wrote: > > Huh. Most people *aren't* competent to develop concurrent software -- it's > way too hard and (unlike sequential code) the compiler and language is no > help. (Race conditions and deadlocks are trivial in Ada code; very little > practical code doesn't have them.). But most of us have to develop such > software anyway, whether or not we're competent. Most people aren't competent to develop any software. That doesn't make it acceptable that some incompetent is creating yet another buffer-overflow vulnerability right now. I don't suppose there's any way to stop such people, but we shouldn't encourage them. > [Especially as I've never figured out how to properly shut down the tasks in > any of my service programs. Maybe I could have figured out something, but it > would have greatly complicated an already complicated system. Instead, I > kill the process manually in the rare case that I need to restart a service > (and I also have a watchdog program that kills and restarts non-responsive > services, and triggers a full system reboot if that doesn't work - that > probably would be needed in any case, just to keep services up as much as > possible {in case of DoS bugs}). A club rather than a screwdriver, but a lot > easier.] I suspect it's a characteristic, if not a requirement, for these programs that they be able to die suddenly without harm. Would you have taken the same approach if not shutting down cleanly would cause problems? (I designed the shutdown mechanism for a program with hundreds of tasks that ran as a service. The program intercepted the signal sent by the service stop command, and everything terminated cleanly as required.) -- Jeff Carter "I'm a kike, a yid, a heebie, a hook nose! I'm Kosher, Mum! I'm a Red Sea pedestrian, and proud of it!" Monty Python's Life of Brian 77 ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 7:50 ` Dmitry A. Kazakov 2016-05-27 18:00 ` Simon Wright 2016-05-27 19:06 ` Jeffrey R. Carter @ 2016-05-27 19:13 ` Shark8 2016-05-27 20:27 ` Dmitry A. Kazakov 2 siblings, 1 reply; 33+ messages in thread From: Shark8 @ 2016-05-27 19:13 UTC (permalink / raw) On Friday, May 27, 2016 at 1:50:50 AM UTC-6, Dmitry A. Kazakov wrote: > 5. Tasks entries have parameter passing problems. If you don't handle > everything in the rendezvous in order to release the caller as soon as > possible, you need to copy parameters and store them locally. The design > of the select statement prevents doing this in a structured way. E.g. > > select > accept String_Call (Text : String) do > Local_Text := Text; -- Accept scope > end; > declare -- Handler's scope > Local_Text : String -- This does not work! > begin > -- Process Local_Text > end; > or accept ... Pretty much a non-problem in Ada 2012: package Example is Task Text_IO is Entry Get( Data : String ); Entry Put; Entry Done; End Text_IO; end Example; package body Example is Task Body Text_IO is Package String_Holder is new Ada.Containers.Indefinite_Holders( Element_Type => String ); Internal_Data : String_Holder.Holder:= String_Holder.To_Holder(""); Finished : Boolean := False; begin loop select accept Done do Finished:= True; end Done; or accept Get (Data : in String) do Internal_Data:= String_Holder.To_Holder( Data ); end Get; or accept Put do Ada.Text_IO.Put_Line( "DATA: "& Internal_Data.Element ); end Put; end select; Exit when Finished; end loop; End Text_IO; end Example; and used via: Example.Text_IO.Put; Example.Text_IO.Get( "Test Data" ); Example.Text_IO.Put; Example.Text_IO.Get( "Something Else" ); Example.Text_IO.Put; Example.Text_IO.Done; > 6. Task entries cannot return unconstrained objects. This can be worked around: We can add to the previous task the following: Entry Data( Item : out Natural ); Entry Data( Item : out String ); Where the one returns the constraints needed for the other... it would be used something like this: declare Length : Natural renames Example.Text_IO.Data; Test : constant String(1..Length):= Example.Text_IO.Data; begin Put_Line ( "----- " & Test & " -----" ); end; ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 19:13 ` Shark8 @ 2016-05-27 20:27 ` Dmitry A. Kazakov 2016-05-27 22:27 ` Randy Brukardt 2016-05-28 14:38 ` Shark8 0 siblings, 2 replies; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-05-27 20:27 UTC (permalink / raw) On 2016-05-27 21:13, Shark8 wrote: > On Friday, May 27, 2016 at 1:50:50 AM UTC-6, Dmitry A. Kazakov wrote: >> 5. Tasks entries have parameter passing problems. If you don't handle >> everything in the rendezvous in order to release the caller as soon as >> possible, you need to copy parameters and store them locally. The design >> of the select statement prevents doing this in a structured way. E.g. >> >> select >> accept String_Call (Text : String) do >> Local_Text := Text; -- Accept scope >> end; >> declare -- Handler's scope >> Local_Text : String -- This does not work! >> begin >> -- Process Local_Text >> end; >> or accept ... > > Pretty much a non-problem in Ada 2012: > > package Example is > > Task Text_IO is > Entry Get( Data : String ); > Entry Put; > Entry Done; > End Text_IO; > > end Example; > > package body Example is > > Task Body Text_IO is > Package String_Holder is new Ada.Containers.Indefinite_Holders( > Element_Type => String ); That is no solution. You still have to move entry-specific local data to the task-wide scope, which was the main point of being unstructured. And you certainly don't want pool-allocated stuff in drivers. Finally, this is no different from Unbounded_String. >> 6. Task entries cannot return unconstrained objects. > > This can be worked around: > We can add to the previous task the following: > Entry Data( Item : out Natural ); > Entry Data( Item : out String ); This is a very low-level and very fragile design. Consider ensuring that nothing comes between querying the length and the body that could change the string. You start doing that with entry barriers risking running into a deadlock. Then consider a possibility that the caller of a get-length request dies prematurely, or that another task steals the string body and so on. Note that the "discussion" started around the claim that design based on semaphore is more low-level than one based on monitor (the task serves as a monitor). (There was a reason why protected objects were introduced in Ada 95) P.S. The Ada-way of returning string is this: entry Get_Text (Text : in out String; Last : out Integer); I am using a bit more general: entry Get_Text (Text : in out String; Pointer : in out Integer); -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 20:27 ` Dmitry A. Kazakov @ 2016-05-27 22:27 ` Randy Brukardt 2016-05-28 6:49 ` Dmitry A. Kazakov 2016-05-28 14:38 ` Shark8 1 sibling, 1 reply; 33+ messages in thread From: Randy Brukardt @ 2016-05-27 22:27 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:niaaji$1nar$1@gioia.aioe.org... > On 2016-05-27 21:13, Shark8 wrote: >> On Friday, May 27, 2016 at 1:50:50 AM UTC-6, Dmitry A. Kazakov wrote: >>> 5. Tasks entries have parameter passing problems. If you don't handle >>> everything in the rendezvous in order to release the caller as soon as >>> possible, you need to copy parameters and store them locally. The design >>> of the select statement prevents doing this in a structured way. E.g. >>> >>> select >>> accept String_Call (Text : String) do >>> Local_Text := Text; -- Accept scope >>> end; >>> declare -- Handler's scope >>> Local_Text : String -- This does not work! >>> begin >>> -- Process Local_Text >>> end; >>> or accept ... >> >> Pretty much a non-problem in Ada 2012: >> >> package Example is >> >> Task Text_IO is >> Entry Get( Data : String ); >> Entry Put; >> Entry Done; >> End Text_IO; >> >> end Example; >> >> package body Example is >> >> Task Body Text_IO is >> Package String_Holder is new Ada.Containers.Indefinite_Holders( >> Element_Type => String ); > > That is no solution. You still have to move entry-specific local data to > the task-wide scope, which was the main point of being unstructured. > > And you certainly don't want pool-allocated stuff in drivers. > Finally, this is no different from Unbounded_String. Sure, if the only unconstrained type you ever use is a String. The Indefinite_Holders solution works for any unconstrained type, not just String. And no one (I hope!) is putting tasks in drivers in the first place; one wants as little as possible in OS drivers, because they necessarily are outside of the control of the OS (written without the standards used for the OS, etc.) The caller of the driver needs to manage concurrency. So how one writes tasks isn't particularly relevant to writing drivers. (Whether or not the OS should avoid pool allocation is a different question altogether...) Aside: I get the feeling that the term "drivers" has been totally corrupted in recent systems, including all kinds of higher-level junk that belongs to the OS. So we might be talking about different things. Randy. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 22:27 ` Randy Brukardt @ 2016-05-28 6:49 ` Dmitry A. Kazakov 0 siblings, 0 replies; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-05-28 6:49 UTC (permalink / raw) On 2016-05-28 00:27, Randy Brukardt wrote: > And no one (I hope!) is putting tasks in drivers in the first place; one > wants as little as possible in OS drivers, because they necessarily are > outside of the control of the OS (written without the standards used for the > OS, etc.) Right. On the contexts (there are several) of an OS driver proper, one simply could not start/switch to a thread. Theoretically one could have Ada-scheduled tasks in a driver in a way one does it on bare-boards, but that would be useless. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-27 20:27 ` Dmitry A. Kazakov 2016-05-27 22:27 ` Randy Brukardt @ 2016-05-28 14:38 ` Shark8 2016-05-28 15:45 ` Dmitry A. Kazakov 1 sibling, 1 reply; 33+ messages in thread From: Shark8 @ 2016-05-28 14:38 UTC (permalink / raw) On Friday, May 27, 2016 at 2:27:37 PM UTC-6, Dmitry A. Kazakov wrote: > On 2016-05-27 21:13, Shark8 wrote: > > On Friday, May 27, 2016 at 1:50:50 AM UTC-6, Dmitry A. Kazakov wrote: > >> 6. Task entries cannot return unconstrained objects. > > > > This can be worked around: > > We can add to the previous task the following: > > Entry Data( Item : out Natural ); > > Entry Data( Item : out String ); > > This is a very low-level and very fragile design. Consider ensuring that > nothing comes between querying the length and the body that could change > the string. That's actually easy to do with Ada's tasking: select accept Done do Finished:= True; end Done; or accept Get (Data : in String) do Internal_Data:= String_Holder.To_Holder( Data ); end Get; or accept Put do Ada.Text_IO.Put_Line( "DATA: "& Internal_Data.Element ); end Put; or accept Data (Item : out Natural) do Item:= Internal_Data.Element'Length; end Data; accept Data (Item : out String) do Item:= Internal_Data.Element; end Data; end select; > You start doing that with entry barriers risking running > into a deadlock. As you can see, no barrier needed. This is one of the nice things about Ada's tasking: you can directly encode a protocol. -- And with package specifications, you can put the task in the private part and declare the public interface in the public portion as [inline]subprograms which, in the body do the proper entry-calls. package example is Function Get_String return String with Inline; -- ... private Task Text_IO is --... end example; package body example is Function Get_String return String is Length : Natural; begin Text_IO.Data( Length ); Return Result : String(1..Length) do Text_IO.Data( Result ); End Return; end Get_String; --... end example; > Then consider a possibility that the caller of a > get-length request dies prematurely, or that another task steals the > string body and so on. Again, precluded by the construction of the select statement shown above. Once the task accepts a get-length it *MUST* next accept a get-data, so if multiple threads call the get-data then only one gets processed and that one is the only one that can then be accepted for a get-data because all the rest are waiting on get-length to be serviced. > Note that the "discussion" started around the claim that design based on > semaphore is more low-level than one based on monitor (the task serves > as a monitor). > (There was a reason why protected objects were introduced in Ada 95) And tasking shows itself to be a higher-level construct; sure, protected objects have their place, but they *AREN'T* capable of directly mapping to a protocol w/o forcing the manual creation of barriers. > P.S. The Ada-way of returning string is this: > > entry Get_Text (Text : in out String; Last : out Integer); I would argue that the Ada way would be creating a function that returns the string of the proper length in the public part of the spec and keeping the implementation hidden in the body. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-28 14:38 ` Shark8 @ 2016-05-28 15:45 ` Dmitry A. Kazakov 0 siblings, 0 replies; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-05-28 15:45 UTC (permalink / raw) On 2016-05-28 16:38, Shark8 wrote: > On Friday, May 27, 2016 at 2:27:37 PM UTC-6, Dmitry A. Kazakov wrote: >> On 2016-05-27 21:13, Shark8 wrote: >>> On Friday, May 27, 2016 at 1:50:50 AM UTC-6, Dmitry A. Kazakov wrote: >>>> 6. Task entries cannot return unconstrained objects. >>> >>> This can be worked around: >>> We can add to the previous task the following: >>> Entry Data( Item : out Natural ); >>> Entry Data( Item : out String ); >> >> This is a very low-level and very fragile design. Consider ensuring that >> nothing comes between querying the length and the body that could change >> the string. > > That's actually easy to do with Ada's tasking: > select > accept Done do > Finished:= True; > end Done; > or > accept Get (Data : in String) do > Internal_Data:= String_Holder.To_Holder( Data ); > end Get; > or > accept Put do > Ada.Text_IO.Put_Line( "DATA: "& Internal_Data.Element ); > end Put; > or > accept Data (Item : out Natural) do > Item:= Internal_Data.Element'Length; > end Data; > accept Data (Item : out String) do > Item:= Internal_Data.Element; > end Data; You have a deadlock here when the order of calls is violated, e.g. when the caller does not call second Data entry. >> Then consider a possibility that the caller of a >> get-length request dies prematurely, or that another task steals the >> string body and so on. > > Again, precluded by the construction of the select statement shown above. How do you preclude the caller from not calling the second Data entry? > Once the task accepts a get-length it *MUST* next accept a get-data, > so if multiple threads call the get-data then only one gets processed > and that one is the only one that can then be accepted for a get-data > because all the rest are waiting on get-length to be serviced. That happen only if other tasks call Data entries in the exact same order. Which is why this is fragile. The proper design of an Ada task is that *all* declared entries were callable in any task state. So if a certain order need to be enforced it is better done with barriers than with replicating accept statements and nesting selects. > And tasking shows itself to be a higher-level construct; sure, Not really. First of all, are you talking about the level of a language construct or about the level of a concurrent programming pattern? That is: 1. task type vs protected object type 2. semaphore vs monitor It is frequently said that Ada concurrent programming primitives are higher level. The meaning of this is that they allow implementation of other primitives (event, mutex etc) and are integrated into the language control flow and type system. Claiming that tasks are higher level than protected objects or reverse is meaningless. > protected objects have their place, but they *AREN'T* capable of > directly mapping to a protocol w/o forcing the manual creation of barriers. As you see it is a quite bad idea to map protocol this way. When dealing with protocols, error handing is more important than protocol implementation itself. The latter is pretty much trivial. The former is what makes software reliable or not. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-25 21:24 Advice, tasking and hardware patrick 2016-05-26 1:09 ` Jeffrey R. Carter 2016-05-26 7:26 ` Dmitry A. Kazakov @ 2016-05-28 0:25 ` rieachus 2016-05-28 1:57 ` patrick 2016-05-28 4:13 ` Jeffrey R. Carter 2 siblings, 2 replies; 33+ messages in thread From: rieachus @ 2016-05-28 0:25 UTC (permalink / raw) I think there is a lot of well argued stuff here which is several months ahead of where the OP is. If you are writing a controller for a wall of instruments talking IEEE 488 or some such, and the goal is to write programs for automated testing, the first huge win with Ada is: In Ada you model the environment, not the problem set. It is not unusual to have changes in the requirements for automated testing (or just about any other field) at the last minute. If you modeled the environment/solution space, a small (in text terms) change in the requirements with require only a small change in the code. Next, there are choices you have to make in doing your modelling. Having a package corresponding to each instrument, and putting a task inside iff you need to deal with state in the instrument. Otherwise use a protected object to insure sequential communications. Some instruments have state, lots of state, others are nice and use a stateless protocol. To use POs, to control other hardware you definitely want to do a classic semaphore. Any thread/task talking to that device does a Seize, and a Release when done. For devices with state, you need a task that tracks the state of the device. Would it were so simple as that makes it sound. The interface the package presents to the rest of the world is clean, but your task may end up pages long to deal with error states and recovery. Finally how you deal with task termination will depend to a great deal on the safety requirements. There is a design pattern when you need each active device to have a call during shutdown and multiple shutdowns are the way to go. Basically you have a shutdown package in the with list of packages with hidden tasks. You create a new task which does what is necessary and it waits on a task entry provided by the shutdown package: package Shutdown is task Suspend is entry Stop; entry Wait; end Suspend; end Shutdown; ... package body Shutdown is begin task body Suspend is begin accept Stop; loop select accept Wait; or accept Stop; -- in case of multiple calls to Stop. or terminate; end select; end loop; end Shutdown; Now any package can call Shutdown.Suspend.Wait from a task that does the necessary shutdown actions. (This is about the only situation where you want to call abort in Ada. You have a task which deals with normal operations, and a emergency task which turns of the gas, high voltage, fuel, or whatever.) task Killer is end Killer -- no entries. task body Killer is begin Shutdown.Suspend.Wait; select Local_Task.Shutdown; or delay XXX; --- delay time will depend on physical system properties. end select; delay YYY; --- delay time will depend on physical system properties. abort Local_Task; -- shut down everything controlled by Local_Task here. end Killer; ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-28 0:25 ` rieachus @ 2016-05-28 1:57 ` patrick 2016-05-28 4:13 ` Jeffrey R. Carter 1 sibling, 0 replies; 33+ messages in thread From: patrick @ 2016-05-28 1:57 UTC (permalink / raw) Thanks so much for this, it's very helpful. I am a little surprised you even know what IEEE 488 is, it's not that common anymore. There are still hundreds of scientific instruments out there using it though not to mention test and measurement equipment. Have a great weekend-Patrick ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-28 0:25 ` rieachus 2016-05-28 1:57 ` patrick @ 2016-05-28 4:13 ` Jeffrey R. Carter 2016-06-01 14:37 ` rieachus 1 sibling, 1 reply; 33+ messages in thread From: Jeffrey R. Carter @ 2016-05-28 4:13 UTC (permalink / raw) On 05/27/2016 05:25 PM, rieachus@comcast.net wrote: > > package Shutdown is > task Suspend is > entry Stop; > entry Wait; > end Suspend; > end Shutdown; > ... > package body Shutdown is > begin > task body Suspend is > begin > accept Stop; > loop > select > accept Wait; > or > accept Stop; -- in case of multiple calls to Stop. > or > terminate; > end select; > end loop; > end Shutdown; Is there any reason for this to be a task? I've always used a protected object: package Shutdown is protected Control is procedure Time_To_Die; -- Tell the system to shut down function Time_To_Die return Boolean; -- Returns True if the system is shutting down entry Wait; -- Blocks until the system is shutting down private -- Control Shutting_Down : Boolean := False; end Control; end Shutdown; Procedure Time_To_Die sets Shutting_Down to True, function Time_To_Die returns Shutting_Down, and Wait is null and has the barrier "when Shutting_Down". Procedure Time_To_Die and Wait work the same as Stop and Wait. The function is useful for sporadic tasks that block on an entry waiting for something to do. -- Jeff Carter "I'm a kike, a yid, a heebie, a hook nose! I'm Kosher, Mum! I'm a Red Sea pedestrian, and proud of it!" Monty Python's Life of Brian 77 ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-05-28 4:13 ` Jeffrey R. Carter @ 2016-06-01 14:37 ` rieachus 2016-06-01 19:09 ` Dmitry A. Kazakov 0 siblings, 1 reply; 33+ messages in thread From: rieachus @ 2016-06-01 14:37 UTC (permalink / raw) On Saturday, May 28, 2016 at 12:13:15 AM UTC-4, Jeffrey R. Carter wrote: > > Is there any reason for this to be a task? I've always used a protected object: Shrug. If it ain't broke don't fix it? Seriously I started doing this avoiding of terminate options back when they were expensive in some implementations, and before protected objects came along. Never rethought it since the complex calls were outside the hard real time parts. Hmmm. The other difference is you can't call abort in a protected object. My way I can abort any hung tasks when shutting down. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-01 14:37 ` rieachus @ 2016-06-01 19:09 ` Dmitry A. Kazakov 2016-06-06 3:33 ` rieachus 0 siblings, 1 reply; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-06-01 19:09 UTC (permalink / raw) On 2016-06-01 16:37, rieachus@comcast.net wrote: > Hmmm. The other difference is you can't call abort in a protected object. Protected object never blocks, thus there is nothing to abort. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-01 19:09 ` Dmitry A. Kazakov @ 2016-06-06 3:33 ` rieachus 2016-06-06 7:18 ` Dmitry A. Kazakov 0 siblings, 1 reply; 33+ messages in thread From: rieachus @ 2016-06-06 3:33 UTC (permalink / raw) On Wednesday, June 1, 2016 at 3:09:33 PM UTC-4, Dmitry A. Kazakov wrote: > Protected object never blocks, thus there is nothing to abort. If you look at my code, I am interested in aborting any other task that did not shut down properly before restarting: abort Local_Task; ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-06 3:33 ` rieachus @ 2016-06-06 7:18 ` Dmitry A. Kazakov 2016-06-07 16:53 ` rieachus 0 siblings, 1 reply; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-06-06 7:18 UTC (permalink / raw) On 06/06/2016 05:33, rieachus@comcast.net wrote: > On Wednesday, June 1, 2016 at 3:09:33 PM UTC-4, Dmitry A. Kazakov wrote: > >> Protected object never blocks, thus there is nothing to abort. > > If you look at my code, I am interested in aborting any other task that did not shut down properly before restarting: As questionable aborting task is, if do, that is unrelated to any protected objects. They block nothing unless erroneous, e.g. when you run an infinite loop within a protected action. If you do you would not be able to abort the task stuck in the action, it is abort-deferred. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-06 7:18 ` Dmitry A. Kazakov @ 2016-06-07 16:53 ` rieachus 2016-06-07 20:21 ` Dmitry A. Kazakov 2016-06-08 0:19 ` Dennis Lee Bieber 0 siblings, 2 replies; 33+ messages in thread From: rieachus @ 2016-06-07 16:53 UTC (permalink / raw) On Monday, June 6, 2016 at 3:19:20 AM UTC-4, Dmitry A. Kazakov wrote: > As questionable aborting task is, if do, that is unrelated to any > protected objects. They block nothing unless erroneous, e.g. when you > run an infinite loop within a protected action. If you do you would not > be able to abort the task stuck in the action, it is abort-deferred. Sigh! This is the one instance where aborting a task is not just appropriate, but sometimes necessary. I have no control over, for example, bit flipping by cosmic rays. If the deadman timer runs out, there is a serious problem and the airplane (or launch vehicle) is falling out of the sky. For tasks which close as expected, my code does not abort them. For tasks that keep running, abort may clear the issue. If it doesn't? You have a very expensive pile of wreckage to analyze. If a task got stuck in a loop but not in an abort deferred area, the abort works, and if the times are set right, you may recover the system. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-07 16:53 ` rieachus @ 2016-06-07 20:21 ` Dmitry A. Kazakov 2016-06-08 4:06 ` rieachus 2016-06-08 0:19 ` Dennis Lee Bieber 1 sibling, 1 reply; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-06-07 20:21 UTC (permalink / raw) On 2016-06-07 18:53, rieachus@comcast.net wrote: > On Monday, June 6, 2016 at 3:19:20 AM UTC-4, Dmitry A. Kazakov wrote: > >> As questionable aborting task is, if do, that is unrelated to any >> protected objects. They block nothing unless erroneous, e.g. when you >> run an infinite loop within a protected action. If you do you would not >> be able to abort the task stuck in the action, it is abort-deferred. > > Sigh! This is the one instance where aborting a task is not just > appropriate, but sometimes necessary. I have no control over, for > example, bit flipping by cosmic rays. Why do you think aborting task would heal that? Why not zeroing a random section of memory, sending an SMS, or assigning 666 to the process counter? > If the deadman timer runs out, > there is a serious problem and the airplane (or launch vehicle) is > falling out of the sky. Yes, but that is not to address by some random actions. You have to bring the system to the nearest known safe state. Restarting a task might be one, unless the cosmic ray hit the task body's code, external objects the task uses, other tasks and hardware it communicates to etc. Regarding protected objects, an equivalent of aborting task is deleting the protected object and creating another instance of. If you believe in voodoo magic protected objects are as good as tasks. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-07 20:21 ` Dmitry A. Kazakov @ 2016-06-08 4:06 ` rieachus 2016-06-08 7:29 ` Dmitry A. Kazakov 0 siblings, 1 reply; 33+ messages in thread From: rieachus @ 2016-06-08 4:06 UTC (permalink / raw) On Tuesday, June 7, 2016 at 4:21:15 PM UTC-4, Dmitry A. Kazakov wrote: > On 2016-06-07 18:53, rieachus@comcast.net wrote: > > On Monday, June 6, 2016 at 3:19:20 AM UTC-4, Dmitry A. Kazakov wrote: > > > >> As questionable aborting task is, if do, that is unrelated to any > >> protected objects. They block nothing unless erroneous, e.g. when you > >> run an infinite loop within a protected action. If you do you would not > >> be able to abort the task stuck in the action, it is abort-deferred. > > > > Sigh! This is the one instance where aborting a task is not just > > appropriate, but sometimes necessary. I have no control over, for > > example, bit flipping by cosmic rays. > > Why do you think aborting task would heal that? Why not zeroing a random > section of memory, sending an SMS, or assigning 666 to the process counter? > > > If the deadman timer runs out, > > there is a serious problem and the airplane (or launch vehicle) is > > falling out of the sky. > > Yes, but that is not to address by some random actions. You have to > bring the system to the nearest known safe state. Restarting a task > might be one, unless the cosmic ray hit the task body's code, external > objects the task uses, other tasks and hardware it communicates to etc. Code is in Flash, with caches that get flushed on a restart. the software consists of a number of tasks all dispatched by a 50 Hz (or some such) clock. In other words, the tasking (source) code is a few dozen lines, and the select statement is about the only tasking operation used in the operating code, absent extreme events. It is fairly common for flipped bits to result in a task which is in an indefinite loop, and no lower priority tasks get to run. The code example I gave tries stopping and restarting every task, and any that don't stop get aborted and then restarted. May not be perfect, but about the best you can do with cosmic rays around. (The operating tasks where possible detect a restart and don't depend on any data they own in DRAM memory.) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-08 4:06 ` rieachus @ 2016-06-08 7:29 ` Dmitry A. Kazakov 2016-06-08 12:56 ` rieachus 0 siblings, 1 reply; 33+ messages in thread From: Dmitry A. Kazakov @ 2016-06-08 7:29 UTC (permalink / raw) On 08/06/2016 06:06, rieachus@comcast.net wrote: > On Tuesday, June 7, 2016 at 4:21:15 PM UTC-4, Dmitry A. Kazakov wrote: >> On 2016-06-07 18:53, rieachus@comcast.net wrote: >>> On Monday, June 6, 2016 at 3:19:20 AM UTC-4, Dmitry A. Kazakov wrote: >>> >>>> As questionable aborting task is, if do, that is unrelated to any >>>> protected objects. They block nothing unless erroneous, e.g. when you >>>> run an infinite loop within a protected action. If you do you would not >>>> be able to abort the task stuck in the action, it is abort-deferred. >>> >>> Sigh! This is the one instance where aborting a task is not just >>> appropriate, but sometimes necessary. I have no control over, for >>> example, bit flipping by cosmic rays. >> >> Why do you think aborting task would heal that? Why not zeroing a random >> section of memory, sending an SMS, or assigning 666 to the process counter? >> >>> If the deadman timer runs out, >>> there is a serious problem and the airplane (or launch vehicle) is >>> falling out of the sky. >> >> Yes, but that is not to address by some random actions. You have to >> bring the system to the nearest known safe state. Restarting a task >> might be one, unless the cosmic ray hit the task body's code, external >> objects the task uses, other tasks and hardware it communicates to etc. > > Code is in Flash, with caches that get flushed on a restart. But the system's state is not in there, e.g. the memory pools, external objects, states of other tasks, states of external devices. In order to be able to repair the system by restarting one task, there must be some very strong conditions to satisfy, which are not except for very rare and very special cases. So if a watchdog fires, the nearest safe state is restart of whole partition. > It is fairly common for flipped bits to result in a task which is in > an indefinite loop, That is the visible effect, the point is if restarting a task heals a symptom or the illness. P.S. It would be nice if Ada had, as well, a non-cooperative model of private, protected and task. That is, private parts inacessible without memory mapping only to occur through publicly visible calls. Such tasks and objects could be resurrected without partition restart. They would also be great for distributed systems done high-level instead of low-level Annex E. Unfortunately there is no demand... -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-08 7:29 ` Dmitry A. Kazakov @ 2016-06-08 12:56 ` rieachus 0 siblings, 0 replies; 33+ messages in thread From: rieachus @ 2016-06-08 12:56 UTC (permalink / raw) On Wednesday, June 8, 2016 at 3:30:07 AM UTC-4, Dmitry A. Kazakov wrote: > That is the visible effect, the point is if restarting a task heals a > symptom or the illness. > > P.S. It would be nice if Ada had, as well, a non-cooperative model of > private, protected and task. That is, private parts inacessible without > memory mapping only to occur through publicly visible calls. Such tasks > and objects could be resurrected without partition restart. They would > also be great for distributed systems done high-level instead of > low-level Annex E. Unfortunately there is no demand... Um. Hard real-time systems are hard, and it is harder still to recover from (transient) hardware errors. However, there are tools, and SPARK helps a lot. In the systems I worked on, each priority level corresponded to a thread, and was fired off every 20 ms. There was a time requirement on restarting any task from scratch that basically resulted in a (small) collection of state variables, and the large swaths of state data like radar tracks would be discarded by hardware transient recovery. Oh, all physical memory allocations had to be done before the system was started. You could, and often did have a per task memory pool, and restart just changed the allocated amount to zero. Of course, any package which contained state had to be task specific. The tasks that updated the HUD was relatively low priority, and some cockpit displays lower still. So telling the pilot to try cycling the power to the computer system wasn't a solution. Hmm. I remember some older systems A6A DIANE? Where the watchdog timer was connected to a cockpit light. That system though, did nav, radar and weapons, but was not involved in flight control. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Advice, tasking and hardware 2016-06-07 16:53 ` rieachus 2016-06-07 20:21 ` Dmitry A. Kazakov @ 2016-06-08 0:19 ` Dennis Lee Bieber 1 sibling, 0 replies; 33+ messages in thread From: Dennis Lee Bieber @ 2016-06-08 0:19 UTC (permalink / raw) On Tue, 7 Jun 2016 09:53:37 -0700 (PDT), rieachus@comcast.net declaimed the following: >On Monday, June 6, 2016 at 3:19:20 AM UTC-4, Dmitry A. Kazakov wrote: > >> As questionable aborting task is, if do, that is unrelated to any >> protected objects. They block nothing unless erroneous, e.g. when you >> run an infinite loop within a protected action. If you do you would not >> be able to abort the task stuck in the action, it is abort-deferred. > >Sigh! This is the one instance where aborting a task is not just appropriate, but sometimes necessary. I have no control over, for example, bit flipping by cosmic rays. If the deadman timer runs out, there is a serious problem and the airplane (or launch vehicle) is falling out of the sky. For tasks which close as expected, my code does not abort them. For tasks that keep running, abort may clear the issue. If it doesn't? You have a very expensive pile of wreckage to analyze. If a task got stuck in a loop but not in an abort deferred area, the abort works, and if the times are set right, you may recover the system. Based on the systems I've seen at my current employer... If, for example, a deadman timer does go off... The entire system is restarted -- recreating ALL tasks -- but attempting to save the data state (a cold start does destructive RAM tests, a warm start skips those). No attempt is made to abort pieces of the system or restart them. All tasks are created during the initialization phase, before the system is "active". -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2016-06-08 12:56 UTC | newest] Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-05-25 21:24 Advice, tasking and hardware patrick 2016-05-26 1:09 ` Jeffrey R. Carter 2016-05-26 8:13 ` Simon Wright 2016-05-26 7:26 ` Dmitry A. Kazakov 2016-05-26 16:41 ` patrick 2016-05-26 17:56 ` Dmitry A. Kazakov 2016-05-26 20:35 ` Jeffrey R. Carter 2016-05-26 19:35 ` Jeffrey R. Carter 2016-05-26 20:51 ` patrick 2016-05-27 7:50 ` Dmitry A. Kazakov 2016-05-27 18:00 ` Simon Wright 2016-05-27 19:06 ` Jeffrey R. Carter 2016-05-27 22:05 ` Randy Brukardt 2016-05-27 23:09 ` Jeffrey R. Carter 2016-05-27 19:13 ` Shark8 2016-05-27 20:27 ` Dmitry A. Kazakov 2016-05-27 22:27 ` Randy Brukardt 2016-05-28 6:49 ` Dmitry A. Kazakov 2016-05-28 14:38 ` Shark8 2016-05-28 15:45 ` Dmitry A. Kazakov 2016-05-28 0:25 ` rieachus 2016-05-28 1:57 ` patrick 2016-05-28 4:13 ` Jeffrey R. Carter 2016-06-01 14:37 ` rieachus 2016-06-01 19:09 ` Dmitry A. Kazakov 2016-06-06 3:33 ` rieachus 2016-06-06 7:18 ` Dmitry A. Kazakov 2016-06-07 16:53 ` rieachus 2016-06-07 20:21 ` Dmitry A. Kazakov 2016-06-08 4:06 ` rieachus 2016-06-08 7:29 ` Dmitry A. Kazakov 2016-06-08 12:56 ` rieachus 2016-06-08 0:19 ` Dennis Lee Bieber
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox