comp.lang.ada
 help / color / mirror / Atom feed
* Tasks and C/C++ code.
@ 1998-11-09  0:00 Barry L. Dorough
  1998-11-09  0:00 ` Mats Weber
  1998-11-10  0:00 ` dennison
  0 siblings, 2 replies; 28+ messages in thread
From: Barry L. Dorough @ 1998-11-09  0:00 UTC (permalink / raw)


    I am working on a project where we need to call the same C function
from multiple tasks.  I am wondering how to do this safely.  Can I make
a generic with my C pragma defined there are do I need to define the
prama in the task type so each task will have its own copy of the C
function.

                                                    Thanks,
                                                    Barry L. Dorough





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-09  0:00 Tasks and C/C++ code Barry L. Dorough
@ 1998-11-09  0:00 ` Mats Weber
  1998-11-10  0:00 ` dennison
  1 sibling, 0 replies; 28+ messages in thread
From: Mats Weber @ 1998-11-09  0:00 UTC (permalink / raw)


"Barry L. Dorough" wrote:
> 
>     I am working on a project where we need to call the same C function
> from multiple tasks.  I am wondering how to do this safely.  Can I make
> a generic with my C pragma defined there are do I need to define the
> prama in the task type so each task will have its own copy of the C
> function.

Doing it either way won't change anything, the result will be exactly
the same: there will be only one copy of the C function, possibly being
called concurrently by more than one Ada task.

What you have to make sure is that your C function is task-safe, or
thread-safe in the pthreads terminology. Look at its use of global
variables and non thread-safe system calls, among others (e.g.
gethostbyname is generally not thread-safe).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-09  0:00 Tasks and C/C++ code Barry L. Dorough
  1998-11-09  0:00 ` Mats Weber
@ 1998-11-10  0:00 ` dennison
  1998-11-11  0:00   ` dbotton
  1 sibling, 1 reply; 28+ messages in thread
From: dennison @ 1998-11-10  0:00 UTC (permalink / raw)


In article <364702E5.F6987321@hiwaay.net>,
  bdorough@phaseiv.com wrote:
>     I am working on a project where we need to call the same C function
> from multiple tasks.  I am wondering how to do this safely.  Can I make
> a generic with my C pragma defined there are do I need to define the
> prama in the task type so each task will have its own copy of the C
> function.

If the C function truly isn't safe to call from multiple threads (iaw: relies
on global data, "static" local declarations, or calls other non-thread safe
routines) then you have to ensure that calls to it happen from only one
thread. The safest way to do it is to make *one* server task responsible for
calling the routine and returning its results. Client tasks rendezvous with
the server task to request a call to the unsafe C routine. This is the method
used in at least one set of X/Motif Ada bindings.

A generic won't do any good, because you end up with multiple bindings to the
*same* C routine, not multiple copies of the C routine itself. A task type
won't work for roughly the same reason, unless you only allow *one* object of
that type. Even then you could have problems with object caching and
thread-local data.

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-10  0:00 ` dennison
@ 1998-11-11  0:00   ` dbotton
  1998-11-11  0:00     ` Barry L. Dorough
                       ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: dbotton @ 1998-11-11  0:00 UTC (permalink / raw)


I think it would be practical to create a protected type that wrapped your C
function to insure that it is not be run concurrently (if it isn't safe). If
it's safe then just call it as you would any other Ada Procedure/Function.

David Botton


  dennison@telepath.com wrote:
> In article <364702E5.F6987321@hiwaay.net>,
>   bdorough@phaseiv.com wrote:
> >     I am working on a project where we need to call the same C function
> > from multiple tasks.  I am wondering how to do this safely.  Can I make
> > a generic with my C pragma defined there are do I need to define the
> > prama in the task type so each task will have its own copy of the C
> > function.
>
> If the C function truly isn't safe to call from multiple threads (iaw: relies
> on global data, "static" local declarations, or calls other non-thread safe
> routines) then you have to ensure that calls to it happen from only one
> thread. The safest way to do it is to make *one* server task responsible for
> calling the routine and returning its results. Client tasks rendezvous with
> the server task to request a call to the unsafe C routine. This is the method
> used in at least one set of X/Motif Ada bindings.
>
>
> --
> T.E.D.
>

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-11  0:00   ` dbotton
@ 1998-11-11  0:00     ` Barry L. Dorough
  1998-11-11  0:00       ` dennison
                         ` (2 more replies)
  1998-11-11  0:00     ` dennison
  1998-11-18  0:00     ` Samuel Tardieu
  2 siblings, 3 replies; 28+ messages in thread
From: Barry L. Dorough @ 1998-11-11  0:00 UTC (permalink / raw)


So, if I understand correctly defining the pragma to C in the declaration part of
the task body will give me multiple binding to the same function if there are
multiple tasks?
If this is correct what happens when you write an Ada procedure/function in a
task?  Does each task get it own copy?  I hope the answer is yes or I have
completely misunderstood the Ada tasking model!

dbotton@hotmail.com wrote:

> I think it would be practical to create a protected type that wrapped your C
> function to insure that it is not be run concurrently (if it isn't safe). If
> it's safe then just call it as you would any other Ada Procedure/Function.
>
> David Botton
>
>   dennison@telepath.com wrote:
> > In article <364702E5.F6987321@hiwaay.net>,
> >   bdorough@phaseiv.com wrote:
> > >     I am working on a project where we need to call the same C function
> > > from multiple tasks.  I am wondering how to do this safely.  Can I make
> > > a generic with my C pragma defined there are do I need to define the
> > > prama in the task type so each task will have its own copy of the C
> > > function.
> >
> > If the C function truly isn't safe to call from multiple threads (iaw: relies
> > on global data, "static" local declarations, or calls other non-thread safe
> > routines) then you have to ensure that calls to it happen from only one
> > thread. The safest way to do it is to make *one* server task responsible for
> > calling the routine and returning its results. Client tasks rendezvous with
> > the server task to request a call to the unsafe C routine. This is the method
> > used in at least one set of X/Motif Ada bindings.
> >
> >
> > --
> > T.E.D.
> >
>
> -----------== Posted via Deja News, The Discussion Network ==----------
> http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own







^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-11  0:00   ` dbotton
  1998-11-11  0:00     ` Barry L. Dorough
@ 1998-11-11  0:00     ` dennison
  1998-11-18  0:00     ` Samuel Tardieu
  2 siblings, 0 replies; 28+ messages in thread
From: dennison @ 1998-11-11  0:00 UTC (permalink / raw)


In article <72b35b$pll$1@nnrp1.dejanews.com>,
  dbotton@hotmail.com wrote:
> I think it would be practical to create a protected type that wrapped your C
> function to insure that it is not be run concurrently (if it isn't safe). If
> it's safe then just call it as you would any other Ada Procedure/Function.

That will only work under both of the following conditions:

 o There is only *one* object of that protected type in use.

If there are multiple objects of the protected type declared, then there's
nothing stopping two tasks from using different protected objects to call the
same routine simultaniously.

 o The C routine in question does not rely on task-local data for proper
operation or for parameter data.

In Ada we are used to data being either local in *scope*, or visible to all
tasks. But this is not nessecarily true when we leave Ada's happy confines.

eg: The Nighthawk Ada compiler splits tasks into separate Unix processes. All
Ada memory allocations are performed from shared memory sections. However,
their C compiler and OS library routines allocate memory from process space.
That means any data that was dynamicly allocated by a different task within a
C routine or OS library routine is unreadable from any but the calling task.
Thus calling X or Motif routines directly from different tasks will blow up,
regarless of how the calls are synchronized.

Many of the newer threaded OS'es have the concept of "thread-local" data. That
could cause the same problem.

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-11  0:00     ` Barry L. Dorough
@ 1998-11-11  0:00       ` dennison
  1998-11-12  0:00       ` Jerry van Dijk
  1998-11-13  0:00       ` Mats Weber
  2 siblings, 0 replies; 28+ messages in thread
From: dennison @ 1998-11-11  0:00 UTC (permalink / raw)


In article <3649A4C4.4D3D22A2@hiwaay.net>,
  bdorough@phaseiv.com wrote:
> So, if I understand correctly defining the pragma to C in the declaration part
of
> the task body will give me multiple binding to the same function if there are
> multiple tasks?

If there are multiple tasks of that type, or if there are multiple tasks with
"pragma Import"s using the same "External_Name" value, yes.

> If this is correct what happens when you write an Ada procedure/function in a
> task?  Does each task get it own copy?  I hope the answer is yes or I have
> completely misunderstood the Ada tasking model!

Yes again. If the body of a subprogram is physically *in* the task's body,
then every task gets its own copy of that subprogram (along with all the
other objects it declares). However, the body for the "pragma Import" is
really in an object file which was declared (in C) at the top scope level. In
this sense, its much like doing a "renames" clause on a library unit.

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-11  0:00     ` Barry L. Dorough
  1998-11-11  0:00       ` dennison
@ 1998-11-12  0:00       ` Jerry van Dijk
  1998-11-13  0:00       ` Mats Weber
  2 siblings, 0 replies; 28+ messages in thread
From: Jerry van Dijk @ 1998-11-12  0:00 UTC (permalink / raw)


> So, if I understand correctly defining the pragma to C in the declaration
part of
> the task body will give me multiple binding to the same function if there
are
> multiple tasks?

This is still confused.

Forget about tasks for the moment.

If you call a C function it will be in some C library. Therefore, there is
only one
copy of this function, namely the one in this C library.

The question whether or not this C function is thread (task) safe, depends
on
how the function is written. Consult the documentation or source code of
the 
function to find out. 

All this has absolutely nothing to do with either Ada or Tasking, only with
C.

Now think about tasking again.

Every task that generates a _call_ to this C function will address only
this
single function in this specific library. Ada is not about to generate C
functions
for you!

So, if the C function you want to use is not thread (task) safe, you need
to make
sure that it is only accessed by a single task at the time. One of the
solutions
is to put the C function call in a separate task.

-- 
-- Jerry van Dijk | Leiden, Holland
-- Team Ada       | email: jdijk@acm.org
-- Ada & Win32: http://stad.dsl.nl/~jvandyk





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-11  0:00     ` Barry L. Dorough
  1998-11-11  0:00       ` dennison
  1998-11-12  0:00       ` Jerry van Dijk
@ 1998-11-13  0:00       ` Mats Weber
  2 siblings, 0 replies; 28+ messages in thread
From: Mats Weber @ 1998-11-13  0:00 UTC (permalink / raw)


"Barry L. Dorough" wrote:
> 
> So, if I understand correctly defining the pragma to C in the declaration part of
> the task body will give me multiple binding to the same function if there are
> multiple tasks?

Yes. There is only one copy of the C function anyway. Putting the pragma
Interface/Import in a package, in a procedure, in a task, or in multiple
places does not change this and has _exactly_ the same effect, except
for the visibility of the function in your Ada code.

> If this is correct what happens when you write an Ada procedure/function in a
> task?  Does each task get it own copy?  I hope the answer is yes or I have
> completely misunderstood the Ada tasking model!

Yes, every instance of the task type gets its own copy, conceptually.
But the code of the local procedure will exist only once in the
object/executable file, and in memory, even if multiple calls are
simultaneously active.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-11  0:00   ` dbotton
  1998-11-11  0:00     ` Barry L. Dorough
  1998-11-11  0:00     ` dennison
@ 1998-11-18  0:00     ` Samuel Tardieu
  1998-11-19  0:00       ` Mats Weber
  2 siblings, 1 reply; 28+ messages in thread
From: Samuel Tardieu @ 1998-11-18  0:00 UTC (permalink / raw)


>>>>> "David" == dbotton  <dbotton@hotmail.com> writes:


David> I think it would be practical to create a protected type that
David> wrapped your C function to insure that it is not be run
David> concurrently (if it isn't safe). If it's safe then just call it
David> as you would any other Ada Procedure/Function.

You can't do that for abitraries C functions: it must not contain any
potentially blocking code.

  Sam
-- 
Samuel Tardieu -- sam@ada.eu.org




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-18  0:00     ` Samuel Tardieu
@ 1998-11-19  0:00       ` Mats Weber
  1998-11-20  0:00         ` Samuel Tardieu
  0 siblings, 1 reply; 28+ messages in thread
From: Mats Weber @ 1998-11-19  0:00 UTC (permalink / raw)


Samuel Tardieu wrote:
> 
> >>>>> "David" == dbotton  <dbotton@hotmail.com> writes:
> 
> David> I think it would be practical to create a protected type that
> David> wrapped your C function to insure that it is not be run
> David> concurrently (if it isn't safe). If it's safe then just call it
> David> as you would any other Ada Procedure/Function.
> 
> You can't do that for abitraries C functions: it must not contain any
> potentially blocking code.

Why not ? If the C function is potentially blocking _and_ non-reentrant
(as is gethostbyname for example, which can take some time), then it's
the only option.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-19  0:00       ` Mats Weber
@ 1998-11-20  0:00         ` Samuel Tardieu
  1998-11-23  0:00           ` Mats Weber
  0 siblings, 1 reply; 28+ messages in thread
From: Samuel Tardieu @ 1998-11-20  0:00 UTC (permalink / raw)


>>>>> "Mats" == Mats Weber <Mats.Weber@elca-matrix.ch> writes:


Mats> Why not ? If the C function is potentially blocking _and_
Mats> non-reentrant (as is gethostbyname for example, which can take
Mats> some time), then it's the only option.

9.5.1 (8) During a protected action, it is a bounded error to invoke
          an operation that is potentially blocking.

I think that the spirit of protected operations is to be really short.

  Sam
-- 
Samuel Tardieu -- sam@ada.eu.org




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-20  0:00         ` Samuel Tardieu
@ 1998-11-23  0:00           ` Mats Weber
  1998-11-23  0:00             ` Tom Moran
  0 siblings, 1 reply; 28+ messages in thread
From: Mats Weber @ 1998-11-23  0:00 UTC (permalink / raw)


Samuel Tardieu wrote:

> Mats> Why not ? If the C function is potentially blocking _and_
> Mats> non-reentrant (as is gethostbyname for example, which can take
> Mats> some time), then it's the only option.
> 
> 9.5.1 (8) During a protected action, it is a bounded error to invoke
>           an operation that is potentially blocking.
> 
> I think that the spirit of protected operations is to be really short.

OK, but the definition of "potentially blocking" does not include
imported subprograms (RM 9.5.1(8-18)). So I guess this is undefined. But
given the spirit of the definition, I agree that it would be better to
put the call in a task body instead of in a protected body, in order not
to be too close to the boundaries of the standard.

Anyway I have seen gethostbyname protected by a protected object (I
think it is in GLADE). So it does work.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Tasks and C/C++ code.
  1998-11-23  0:00           ` Mats Weber
@ 1998-11-23  0:00             ` Tom Moran
  1998-11-24  0:00               ` Blocking protected ops (was: Tasks and C/C++ code) Mats Weber
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Moran @ 1998-11-23  0:00 UTC (permalink / raw)


>Anyway I have seen gethostbyname protected by a protected object (I
>think it is in GLADE). So it does work.
  Does the call to gethostbyname occur inside a protected procedure,
even though it blocks, or is it controlled by a semaphore or something
that is a protected object?  eg
procedure Get_Host_By_Name(...) is
  Grab : gethostbyname_grabber;
begin
  gethostbyname(....);
end Get_Host_By_Name;
  where the controlled type gethostbyname_grabber has an Initialize
that calls a guarded entry, and thus waits for the guard to allow it
in.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-23  0:00             ` Tom Moran
@ 1998-11-24  0:00               ` Mats Weber
  1998-11-24  0:00                 ` Robert I. Eachus
  0 siblings, 1 reply; 28+ messages in thread
From: Mats Weber @ 1998-11-24  0:00 UTC (permalink / raw)


Tom Moran wrote:
> 
> >Anyway I have seen gethostbyname protected by a protected object (I
> >think it is in GLADE). So it does work.
>   Does the call to gethostbyname occur inside a protected procedure,
> even though it blocks, or is it controlled by a semaphore or something
> that is a protected object?

I checked the GLADE sources and it's a semaphore, so the protected call
itself will not block on gethostbyname.

Anyway, the question remains: is it legal for a protected body to call
some imported subprogram that could block (in the pthreads sense of the
term) ?

Does someone know why the rule 9.5.1(8-18) is there at all ?




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-24  0:00               ` Blocking protected ops (was: Tasks and C/C++ code) Mats Weber
@ 1998-11-24  0:00                 ` Robert I. Eachus
  1998-11-25  0:00                   ` Mats Weber
  0 siblings, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 1998-11-24  0:00 UTC (permalink / raw)


In article <365AD980.5729FCD8@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes:

 > Anyway, the question remains: is it legal for a protected body to call
 > some imported subprogram that could block (in the pthreads sense of the
 > term) ?

    You quoted the answer yourself, it is a bounded error per
9.5.1(8&16) seem to cover it completely.

 > Does someone know why the rule 9.5.1(8-18) is there at all ?

    To rigorously define the conditions where you should allow for
the possibility of deadlocks and other blocking problems.  Some
deadlocks (or worse, race conditions) can't be ruled out, because they
are inherent in the nature of the beast.  Subclause 9.5.1 limits the
number of programs that are potentially affected by this, in part by
strongly encouraging programmers not to do that!

    This is a perfect example.  Most compilers will generate code to
call gethostbyname within a protected subprogram, but most users will
be encouraged by the RM to do it right.  In this case really right is
probably to put the potentially offensive call in a task (or protected
object) that encapsulates all potentially locking OS calls.  If you
are on a symmetric multiprocessor, you may be able to have several
such guards.
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-24  0:00                 ` Robert I. Eachus
@ 1998-11-25  0:00                   ` Mats Weber
  1998-11-25  0:00                     ` Robert I. Eachus
  1998-11-25  0:00                     ` Jean-Pierre Rosen
  0 siblings, 2 replies; 28+ messages in thread
From: Mats Weber @ 1998-11-25  0:00 UTC (permalink / raw)


"Robert I. Eachus" wrote:
> 
> In article <365AD980.5729FCD8@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes:
> 
>  > Anyway, the question remains: is it legal for a protected body to call
>  > some imported subprogram that could block (in the pthreads sense of the
>  > term) ?
> 
>     You quoted the answer yourself, it is a bounded error per
> 9.5.1(8&16) seem to cover it completely.

I don't think so. Look closely at 9.5.1(16&18). Subprograms imported
with pragma Import are not covered.

>  > Does someone know why the rule 9.5.1(8-18) is there at all ?
> 
>     To rigorously define the conditions where you should allow for
> the possibility of deadlocks and other blocking problems.  Some
> deadlocks (or worse, race conditions) can't be ruled out, because they
> are inherent in the nature of the beast.  Subclause 9.5.1 limits the
> number of programs that are potentially affected by this, in part by
> strongly encouraging programmers not to do that!

I still don't see why an accept statement is allowed to contain a
potentially blocking call, but a protected procedure is not.

To me, this looks a little like incorrect order dependences in Ada 83,
where the compiler was allowed to raise Program_Error if it detected
one, but it is generally not able to detect them. How could a protected
body detect that a blocking operation is being called, if that operation
was imported ?

>     This is a perfect example.  Most compilers will generate code to
> call gethostbyname within a protected subprogram, but most users will
> be encouraged by the RM to do it right.  In this case really right is
> probably to put the potentially offensive call in a task (or protected
> object) that encapsulates all potentially locking OS calls. [...]

I think this should be a task, but _not_ a protected object. If you want
to use a protected object and not call gethostbyname from within the
protected body, you have to make two calls:

   Semaphore.Seize;  -- Semaphore is a protected object
   gethostbyname();
   Semaphore.Release;

which seems silly because you need two protected calls.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-25  0:00                   ` Mats Weber
  1998-11-25  0:00                     ` Robert I. Eachus
@ 1998-11-25  0:00                     ` Jean-Pierre Rosen
  1998-11-27  0:00                       ` Mats Weber
  1 sibling, 1 reply; 28+ messages in thread
From: Jean-Pierre Rosen @ 1998-11-25  0:00 UTC (permalink / raw)



Mats Weber a �crit dans le message
<365BE117.59209A5@elca-matrix.ch>...
>I still don't see why an accept statement is allowed to contain a
>potentially blocking call, but a protected procedure is not.
>
Because a protected type is much lower level than tasks.
On a multi-processor, the protection can be implemented
by busy-waiting on a global lock; you don't want to allow
a task to be stuck in the protected object for a long time.
There is no such issue for tasks (which is BTW why
tasks and rendezvous are still useful).

My own rule of thumb:
if it's simple, low-level and quick, use a protected type.
Otherwise, and especially if it's a high level operation,
or if you need to do more that checking a boolean or
bumping a counter, use tasks.

----------------------------------------------------------------------
------
                  J-P. Rosen (Rosen.Adalog@wanadoo.fr)
      Visit Adalog's web site at http://perso.wanadoo.fr/adalog






^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-25  0:00                   ` Mats Weber
@ 1998-11-25  0:00                     ` Robert I. Eachus
  1998-11-26  0:00                       ` Simon Wright
  1998-11-25  0:00                     ` Jean-Pierre Rosen
  1 sibling, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 1998-11-25  0:00 UTC (permalink / raw)


In article <365BE117.59209A5@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes:

 > I don't think so. Look closely at 9.5.1(16&18). Subprograms imported
 > with pragma Import are not covered.

   Eighteen only says that language-defined subprograms are not
potentially blocking unless the RM says otherwise.  Language-defined
here is a technical term applying to subprograms defined by the
Reference Manual.  Sixteen is the key here.  Within Ada, the RM can
define what is a potentially blocking subprogram, outside the
programmer has to figure it out for himself, which is why this is a
bounded error.
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-25  0:00                     ` Robert I. Eachus
@ 1998-11-26  0:00                       ` Simon Wright
  1998-11-27  0:00                         ` David Botton
  1998-11-29  0:00                         ` Tucker Taft
  0 siblings, 2 replies; 28+ messages in thread
From: Simon Wright @ 1998-11-26  0:00 UTC (permalink / raw)


eachus@spectre.mitre.org (Robert I. Eachus) writes:

> In article <365BE117.59209A5@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes:
> 
>  > I don't think so. Look closely at 9.5.1(16&18). Subprograms imported
>  > with pragma Import are not covered.
> 
>    Eighteen only says that language-defined subprograms are not
> potentially blocking unless the RM says otherwise.  Language-defined
> here is a technical term applying to subprograms defined by the
> Reference Manual.  Sixteen is the key here.  Within Ada, the RM can
> define what is a potentially blocking subprogram, outside the
> programmer has to figure it out for himself, which is why this is a
> bounded error.

I for one understood the language of 9.5.8 as meaning that _only_ the
operations stated in 9-16 are 'potentially blocking', ie the list is a
definition of what it is to be 'potentially blocking' and hence
subject to possible checking by the runtime.

There must be a difference between bad design and illegal design!




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-27  0:00                         ` David Botton
  1998-11-27  0:00                           ` Mats Weber
@ 1998-11-27  0:00                           ` Tom Moran
  1998-11-27  0:00                             ` Jerry van Dijk
  1 sibling, 1 reply; 28+ messages in thread
From: Tom Moran @ 1998-11-27  0:00 UTC (permalink / raw)


The Claw Windows binding uses WSAAsyncGetHostByName, which gets
around most of the blocking.  But more generally, to call a blocking
routine in a task safe way, Mats Weber's example is basically what
you need to do.

If you are going to have multiple semaphores, you will want to
create a protected semaphore type, so you can declare different
semaphores for different resources.

If your code between Seize and Release is complex, you might find it
less error-prone to create a controlled type whose Initialize calls
Seize and whose Finalize calls Release, to make sure those are both
called properly, ie something like this:

protected type Semaphore -- like Mats Weber's example, but a type

type Access_Semaphore is access all Semaphore;

type Seizer(What : Access_Semaphore)
  is new Ada.Finalization.Limited_Controlled with null record;

procedure Initialize(S : in out Siezer);
procedure Finalize(S : in out Siezer);

...

procedure Initialize(S : in out Siezer) is
begin
  Seizer.What.Seize;
end Initialize;

procedure Finalize(S : in out Siezer) is
begin
  Seizer.What.Release;
end Finalize;

...
Gethostbyname_Protector : Semaphore;

function Protected_Gethostbyname (Name : ...
   Owner : Seizer(Gethostbyname_Protector'access);
begin
   return Gethostbyname(Name);
end Protected_Gethostbyname;


Another_Resource : Semaphore;

procedure Something ...
   Owner : Seizer(Another_Resource'access);
begin
   ....
end Something;

etc.
(I've indicated elsewhere some of the reasons I think using
System.Address is a poor idea, but that's an orthogonal issue.)





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-27  0:00                           ` Tom Moran
@ 1998-11-27  0:00                             ` Jerry van Dijk
  1998-11-28  0:00                               ` Tom Moran
  0 siblings, 1 reply; 28+ messages in thread
From: Jerry van Dijk @ 1998-11-27  0:00 UTC (permalink / raw)


Tom Moran (tmoran@bix.com) wrote:

: If you are going to have multiple semaphores, you will want to
: create a protected semaphore type, so you can declare different
: semaphores for different resources.

Hmmm, I would say that this really is a OS dependend problem. On
Win32 I would follow the Claw approach, on Unix I would use a task,
on OS/2 I would use a mutex, on ....

Jerry.

-- 
-- Jerry van Dijk  | email: jdijk@acm.org
-- Leiden, Holland | member Team-Ada
-- Ada & Win32: http://stad.dsl.nl/~jvandyk




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-26  0:00                       ` Simon Wright
@ 1998-11-27  0:00                         ` David Botton
  1998-11-27  0:00                           ` Mats Weber
  1998-11-27  0:00                           ` Tom Moran
  1998-11-29  0:00                         ` Tucker Taft
  1 sibling, 2 replies; 28+ messages in thread
From: David Botton @ 1998-11-27  0:00 UTC (permalink / raw)


After all the discussion on this issue, I am not sure how to implement a
call to gethosbyname any more.

Would some one post a correct implementation of this and if one can wrap
gethostbyname in to a protected type so it can be called by multiple task
instances even if it (gethostbyname) is not thread safe.

Thanks,
David Botton

Simon Wright wrote in message ...
>eachus@spectre.mitre.org (Robert I. Eachus) writes:
>
>> In article <365BE117.59209A5@elca-matrix.ch> Mats Weber
<Mats.Weber@elca-matrix.ch> writes:
>>
>>  > I don't think so. Look closely at 9.5.1(16&18). Subprograms imported
>>  > with pragma Import are not covered.
>>
>>    Eighteen only says that language-defined subprograms are not
>> potentially blocking unless the RM says otherwise.  Language-defined
>> here is a technical term applying to subprograms defined by the
>> Reference Manual.  Sixteen is the key here.  Within Ada, the RM can
>> define what is a potentially blocking subprogram, outside the
>> programmer has to figure it out for himself, which is why this is a
>> bounded error.
>
>I for one understood the language of 9.5.8 as meaning that _only_ the
>operations stated in 9-16 are 'potentially blocking', ie the list is a
>definition of what it is to be 'potentially blocking' and hence
>subject to possible checking by the runtime.
>
>There must be a difference between bad design and illegal design!






^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-25  0:00                     ` Jean-Pierre Rosen
@ 1998-11-27  0:00                       ` Mats Weber
  0 siblings, 0 replies; 28+ messages in thread
From: Mats Weber @ 1998-11-27  0:00 UTC (permalink / raw)


BTW, is an entry body a protected action ? 9.5.1 does not seem to
include entries, so is it allowed to have a potentially blocking call in
an entry body ?




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-27  0:00                         ` David Botton
@ 1998-11-27  0:00                           ` Mats Weber
  1998-11-27  0:00                           ` Tom Moran
  1 sibling, 0 replies; 28+ messages in thread
From: Mats Weber @ 1998-11-27  0:00 UTC (permalink / raw)


David Botton wrote:
> 
> After all the discussion on this issue, I am not sure how to implement a
> call to gethosbyname any more.
> 
> Would some one post a correct implementation of this and if one can wrap
> gethostbyname in to a protected type so it can be called by multiple task
> instances even if it (gethostbyname) is not thread safe.

An example of how to do it can be found in:

<ftp://cs.nyu.edu//pub/gnat/glade/glade-1.03p.tar.gz>

or copy this code (compiled, not tested):

   protected Semaphore is
      entry Seize;
      entry Release;
   private
      Busy : Boolean := False;
   end Semaphore;

   protected body Semaphore is

      entry Seize when not Busy is
      begin
         Busy := True;
      end;

      entry Release when Busy is
      begin
         Busy := False;
      end;

   end Semaphore;

   function Gethostbyname (Name : in System.Address)
      return System.Address; -- pointer to hostent

   pragma Import(C, Gethostbyname);

   function Protected_Gethostbyname (Name : in System.Address)
      return System.Address is

      Result : System.Address;

   begin
      Semaphore.Seize;
      Result := Gethostbyname(Name);
      Semaphore.Release;
      return Result;
   exception
      when others =>
         Semaphore.Release;
         raise;
   end Protected_Gethostbyname;

it would be nice to put the call to gethostbyname inside a protected
procedure (so that you need only one protected call instead of two), but
this does not seem to be allowed as gethostbyname could be potentially blocking.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-27  0:00                             ` Jerry van Dijk
@ 1998-11-28  0:00                               ` Tom Moran
  0 siblings, 0 replies; 28+ messages in thread
From: Tom Moran @ 1998-11-28  0:00 UTC (permalink / raw)


>: If you are going to have multiple semaphores, you will want to
>: create a protected semaphore type, so you can declare different
>: semaphores for different resources.

>Hmmm, I would say that this really is a OS dependend problem. On
>Win32 I would follow the Claw approach, on Unix I would use a task,
>on OS/2 I would use a mutex, on ....
  For gethostbyname in specific, or in general for multiple resources?
If the latter, why?




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-26  0:00                       ` Simon Wright
  1998-11-27  0:00                         ` David Botton
@ 1998-11-29  0:00                         ` Tucker Taft
  1998-11-30  0:00                           ` Simon Wright
  1 sibling, 1 reply; 28+ messages in thread
From: Tucker Taft @ 1998-11-29  0:00 UTC (permalink / raw)


Simon Wright (simon@pogner.demon.co.uk) wrote:
: ...
: I for one understood the language of 9.5.8 as meaning that _only_ the
                                       ^^^^^ 9.5.1

: operations stated in 9-16 are 'potentially blocking', ie the list is a
: definition of what it is to be 'potentially blocking' and hence
: subject to possible checking by the runtime.

: There must be a difference between bad design and illegal design!

The underlying rule is that anything which might result in
a task switch (or a deadlock) is a bad idea.  It is safe to call an O/S 
routine during a protected action if and only if no task switch could happen.

It is a "bounded error" rather than one which must result in an
exception being raised because it is not always easy for the run-time
to detect violations.

--
-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Burlington, MA  USA
An AverStar Company




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Blocking protected ops (was: Tasks and C/C++ code)
  1998-11-29  0:00                         ` Tucker Taft
@ 1998-11-30  0:00                           ` Simon Wright
  0 siblings, 0 replies; 28+ messages in thread
From: Simon Wright @ 1998-11-30  0:00 UTC (permalink / raw)


stt@houdini.camb.inmet.com (Tucker Taft) writes:

> Simon Wright (simon@pogner.demon.co.uk) wrote:
> : ...
> : I for one understood the language of 9.5.8 as meaning that _only_ the
>                                        ^^^^^ 9.5.1

oops, yes, I meant 9.5.1(8)

> : operations stated in 9-16 are 'potentially blocking', ie the list is a

.. and (9)..(16)

> : definition of what it is to be 'potentially blocking' and hence
> : subject to possible checking by the runtime.




^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~1998-11-30  0:00 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-11-09  0:00 Tasks and C/C++ code Barry L. Dorough
1998-11-09  0:00 ` Mats Weber
1998-11-10  0:00 ` dennison
1998-11-11  0:00   ` dbotton
1998-11-11  0:00     ` Barry L. Dorough
1998-11-11  0:00       ` dennison
1998-11-12  0:00       ` Jerry van Dijk
1998-11-13  0:00       ` Mats Weber
1998-11-11  0:00     ` dennison
1998-11-18  0:00     ` Samuel Tardieu
1998-11-19  0:00       ` Mats Weber
1998-11-20  0:00         ` Samuel Tardieu
1998-11-23  0:00           ` Mats Weber
1998-11-23  0:00             ` Tom Moran
1998-11-24  0:00               ` Blocking protected ops (was: Tasks and C/C++ code) Mats Weber
1998-11-24  0:00                 ` Robert I. Eachus
1998-11-25  0:00                   ` Mats Weber
1998-11-25  0:00                     ` Robert I. Eachus
1998-11-26  0:00                       ` Simon Wright
1998-11-27  0:00                         ` David Botton
1998-11-27  0:00                           ` Mats Weber
1998-11-27  0:00                           ` Tom Moran
1998-11-27  0:00                             ` Jerry van Dijk
1998-11-28  0:00                               ` Tom Moran
1998-11-29  0:00                         ` Tucker Taft
1998-11-30  0:00                           ` Simon Wright
1998-11-25  0:00                     ` Jean-Pierre Rosen
1998-11-27  0:00                       ` Mats Weber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox