From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,bdf72b2364b0da13 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII Received: by 10.68.191.2 with SMTP id gu2mr13422288pbc.0.1323802264055; Tue, 13 Dec 2011 10:51:04 -0800 (PST) Path: lh20ni18680pbb.0!nntp.google.com!news1.google.com!postnews.google.com!j9g2000vby.googlegroups.com!not-for-mail From: Ada BRL Newsgroups: comp.lang.ada Subject: Re: Interrupts handling in ADA Date: Tue, 13 Dec 2011 10:51:03 -0800 (PST) Organization: http://groups.google.com Message-ID: <70e4b2ba-62c4-41d3-b603-a20e37d3d332@j9g2000vby.googlegroups.com> References: <30143086.6.1323549838421.JavaMail.geo-discussion-forums@vbbfq24> <1f0ump3yhi731$.1gh4827ra0a87.dlg@40tude.net> <7a17c1d0-30dd-47b8-a800-3575a8793fbe@d10g2000vbf.googlegroups.com> NNTP-Posting-Host: 86.169.132.157 Mime-Version: 1.0 X-Trace: posting.google.com 1323802263 18214 127.0.0.1 (13 Dec 2011 18:51:03 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Tue, 13 Dec 2011 18:51:03 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: j9g2000vby.googlegroups.com; posting-host=86.169.132.157; posting-account=yig7mwoAAAAAcduNbH7Dpal1sjCSAijA User-Agent: G2/1.0 X-Google-Web-Client: true X-Google-Header-Order: HNKUARELSC X-HTTP-UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2,gzip(gfe) Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Date: 2011-12-13T10:51:03-08:00 List-Id: On 13 Dic, 15:39, "Dmitry A. Kazakov" wrote: > On Tue, 13 Dec 2011 06:51:25 -0800 (PST), Ada BRL wrote: > > On 13 Dic, 14:04, "Dmitry A. Kazakov" > > wrote: > >> On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote: > >>> On 11 Dic, 09:23, "Dmitry A. Kazakov" > >>> wrote: > >>>> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote: > >>>>> The environment of ADA applcation is: > >>>>> I have 4 tasks that execute at the same time: > >>>>> one is the main task, > >>>>> the other three execute a "read" from network (socket) function ins= ide > >>>>> their bodies (on the other side there's the C/C++ application with = 3 > >>>>> network sockets). > >>>>> [I decided to use the sockets instead of dll/lib import because thi= s approach hasn't worked... =3D( ] > > >>>> What dll import has to do with sockets, except that sockets usually = are > >>>> provided by a library? > > >>> I would have liked to use dll import to exchange data between C stuff > >>> and Ada program instead of using two programs (C and Ada) > >>> communicating through sockets... > > >> You can link to an import library from Ada without any problems. Which= OS > >> are you using? > > > Windows 7 64 bit, Home Premium SP1 ... > > I have tried in many ways to import symbols but it was impossible... > > I had a linker error: couldn't find exported symbols... > > I've copied the dll into all the possible folder of my project. > > No, you link to the import library, that is *.lib, not *.dll. It is also > possible to load dynamically using LoadLibrary etc. Both works perfectly > well and simple with GNAT. I've tried either with dll and lib but it hasn't worked...I've used pragma Import(Convention, Entity, External_name) because I've read to do so to link libraries into the Ada 95 programming book... I prefer to load a static library (lib) instead of a dll (I've read it's better for efficiency reasons); what I have to do, without pragma Import(...)? > > The simplest way is to create a gpr-file for the external library and > include it into your Ada project using "with." GNAT knows what to do next= . How can I create a gpr file for the external library? What I have to code inside? I suppose it will be a .ads file that I'll link to the other ads and adb files. [Ok, it's clear the use of "with" and "use"] > > >> No, OS event objects and entry calls assume that the recipient is inac= tive > >> and thus is ready to accept the notification. That is a non-preemptive > >> model. > > > Does this means that the main task has to be in wait for event state > > (blocked and so NOT running)? > > Yes, if the main task is the subscriber. If subscriber means the task that has defined inside its declaration "entry data_available", and inside its body "accept data_available" it's clear. > > If you look at how GUI's are built, they do exactly this: run the > messages/events/signal processing loop, which does nothing when there is = no > messages/events/signals. > > >> Software interrupts are preemptive. An interrupt breaks the execution = of > >> the recipient. Like with exceptions there are two models of what happe= ns > >> after interrupt has been serviced: continuation back from the point wh= ere > >> the task was interrupted vs. winding up the stack and aborting some st= uff > >> with continuation from a definite point. AST's are usually like former= , > >> Ada's ATC are like latter. > > > Sorry what does ATC stand for? > > Asynchronous Transfer of Control. > > >> the task was interrupted vs. winding up the stack and aborting some st= uff > >> with continuation from a definite point. AST's are usually like former= , > >> Ada's ATC are like latter. > > > I haven't understood well... > > > With entry / accept will I use AST or ATC? > > ATC in Ada is like this (example from the language manual): > > =A0 =A0 select > =A0 =A0 =A0 =A0 Terminal.Wait_For_Interrupt; > =A0 =A0 =A0 =A0 Put_Line("Interrupted"); > =A0 =A0 then abort > =A0 =A0 =A0 =A0 -- This will be abandoned upon terminal interrupt > =A0 =A0 =A0 =A0 Put_Line("-> "); > =A0 =A0 =A0 =A0 Get_Line(Command, Last); > =A0 =A0 =A0 =A0 Process_Command (Command (1..Last)); > =A0 =A0 end select; > > You have some piece of code executing (between abort and end select) whil= e > waiting for some event (the entry call right after select). When event > happens, the code is aborted and you go to the part > Put_Line("Interrupted"); > > BUT: Just don't worry about ATC, it is not a good idea to use it, almost > always. Ok, but I've understood how it works =3D) thanks! The thing is that the "then abort" statement is not very evocative and it has lead me to a misunderstanding... The high level strucure roughly is: while (!event){ do stuff } exit program but in addition with "select" structure I guess you can exit from the while at any time, just after the event occurs (asynchronous behaviour). It's like to check, before executing every atomic action, if the event is active or not. If it's so exit from the while. > > > if I have this piece of code inside main task body: > > > do stuff before; > > accept event; > > do stuff after; > > A more complete picture is: > > =A0 =A0do stuff before; > =A0 =A0accept event do > =A0 =A0 =A0 do stuff upon rendezvous; > =A0 =A0end; > =A0 =A0do stuff after; Yes, you are definitely right =3D) > > > The main thread is blocked onto "event" barrier, when socket calls > > Main.event it can continue and perform "do stuff after". > > > Code of socket body: > > > do stuff before; > > Main.event; > > do stuff after; > > > Does the socket continue its execution after calling to Main.event, in > > parallel with main task or will it be blocked until the main task > > blocks itself again onto a barrier? > > When the socket task calls an entry of the main task, it is blocked until > the main task accepts the call. This could be a problem...read at the bottom of this post... > There is a queue of calls to each entry, so > multiple tasks can await there for a rendezvous. At a time only one > rendezvous is accepted and the corresponding task call is removed from th= e > queue. Does this means that it can be resumed and continue its execution or does it must wait until all the calls to the entry are removed? Eg: Queue of entry calls: 123 After the "pop" of the first event, can the fist socket continue its execution or does it have to wait until the queue is empty? In my program I can have for example this situation of the event queue: 1121321 Is it possible to deal with it using rendez vous / accept - entry? See bottom for more details. > Then both tasks engage the rendezvous. Upon the rendezvous the code > "do stuff upon rendezvous" is executed. Any exceptions in this code > propagate into both tasks. When the code completes this or that way the > rendezvous ends, and both tasks continue their execution independently on > each other. I.e. concurrently executing "do stuff after." Here is a > diagram: > > =A0 =A0 Main =A0 =A0 =A0 =A0 =A0 =A0 Socket task > =A0 =A0 =A0 | =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| > do stuff before =A0 do stuff before; > =A0 =A0 =A0 | =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| > =A0 =A0 accept =A0 =A0 =A0 =A0 =A0 =A0 call > =A0 =A0 =A0 =A0\ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/ > =A0 =A0 =A0 do stuff upon rendezvous (synchronously) > =A0 =A0 =A0 =A0/ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0\ > do stuff after; =A0 =A0do stuff after > =A0 =A0 =A0 | =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| > > Consider the rendezvous code executed as if both tasks were one. OK! So in this phase do they share objects? May you plase make a very simple code example? > > > Please tell me if I'm not right: every task append it's event > > (data_arrived event) onto the queue. > > Rendezvous are better than that, because the queue contains the tasks > themselves. No data are actually copied. If you want to copy data from on= e > task to another, you simply pass them as a parameter of the call and make= a > copy of the parameter during the rendezvous. > > > For this reason the main task enters the running state and pops all > > the elements of the queue (events); after having processed all the > > events it will enter the blocked state again. Am I right? > > Yes. A task can wait for multiple entries (see the select statement). If > all alternatives of the select are closed, the task is blocked. The > simplest case is just one accept. The task is blocked until nobody calls = to > the entry. > > >>>> 3. "Queue": socket readers enqueue some data (the queue is implement= ed > >>>> using a protected object). Other tasks (there could be many) dequeue= data > >>>> and do something meaningful with them. There are many kinds of queue= s for > >>>> different purposes and of different behavior. > > > Is it the same of using Mailbox? > > Yes, mailbox is a sort of queue. But there are queues of different flavor= s. > E.g. blocking, non-blocking, waitable on the ends, queues of different > policies at their ends, blackboards etc. > > > Roughly speaking, are you suggesting me not to copy the data from > > sockets but accessing the same data through "pointers"? > > Not necessarily pointers. I don't know why socket tasks cannot process > their data concurrently. If they need to be synchronized at certain point= s > why not to do just this. It is a balance which depends on the problem at > hand. In some cases monitors are preferable in other cases they are not. > > > Or, are you suggesting me to avoid context switching? > > That is the next step. The worst case is both to copy data and to switch > the context. This is what a queue-based solution [*] would do. The best > case is same data same context. BUT, as always, "premature optimization i= s > the root ..." etc. Solve the problem in the simplest way, only if the > performance is poor consider other solutions. I think it's better to explain the environment: The socket tasks are not synchronized each other, they don't have to wait for the completion of another, they are completely disjoint, they just have to: - notify the main task that data is arrived, - let data be available to the main task in order be elaborated, - don't be blocked at any time (even when main task is executing) because they are receiving data from other sockets, so they must be able to read data from the network at any time. The main task has to: - wait until some data (from any of the sockets) is available, so wait for the event generated by the sockets, - don't miss any "incoming new data" event generated by the sockets (must append all the new data events into a queue...) - process the data until the queue of events is empty, - come back to "wait event" state. I hope to have been clearer and to have you helped to better understand my problem :-)! The sockets have an input buffer for data from the network and for every message coming from the network they have to generate a "data_available" event. The elaboration of the data must be done inside the main task, the sockets are just a way to connect two programs. Thank you very much for your help! > > ----- > * Which does not do processing at the context of a protected action. > > -- > Regards, > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de