* Pragma SHARED, tasks and shared variables
@ 1988-07-28 1:03 "Vladimir Ivanovic, x3-7786"
1988-07-28 16:33 ` Jonathan P. Biggar
0 siblings, 1 reply; 3+ messages in thread
From: "Vladimir Ivanovic, x3-7786" @ 1988-07-28 1:03 UTC (permalink / raw)
Can anyone answer the following question:
If I specify that every read or update to an variable whose type is an
access type is a synchronization point for that variable by using the
pragma SHARED and naming that variable [LRM 9.11(7)], can I be assured
that the object designated by that variable will never be a local
copy of that object?
My intent is to get around the restrictions imposed by LRM 9.11(3)
and 9.11(8) by having shared data structures whose types are not
restricted to scalar and access types.
My motivation is performance. I cannot afford the CPU strokes that
encapsulating the data structures in a task and performing rendezvous
with that task to access the data would cost. (And I cannot afford a
faster CPU...)
I realize that my particular implementation (VAX Ada v1.4) allows
the use of pragma VOLATILE which is the same as pragma SHARED without
the words "and whose type is a scalar or access type", essentially
giving me what I want, but pragma VOLATILE is not portable across
implementations.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Pragma SHARED, tasks and shared variables
1988-07-28 1:03 Pragma SHARED, tasks and shared variables "Vladimir Ivanovic, x3-7786"
@ 1988-07-28 16:33 ` Jonathan P. Biggar
0 siblings, 0 replies; 3+ messages in thread
From: Jonathan P. Biggar @ 1988-07-28 16:33 UTC (permalink / raw)
In article <8807280055.AA27279@ajpo.sei.cmu.edu> IVANOVIC%VAXR@CIRCUS.LLNL.GOV ("Vladimir Ivanovic, x3-7786") writes:
> I realize that my particular implementation (VAX Ada v1.4) allows
> the use of pragma VOLATILE which is the same as pragma SHARED without
> the words "and whose type is a scalar or access type", essentially
> giving me what I want, but pragma VOLATILE is not portable across
> implementations.
However, pragma SHARED is not portable across implementations either. You
cannot predict what any given implementation is going to consider a "scalar"
type that can be accessed atomically. Implementations that support SHARED
probably will not allow you to use it on a variable that is not scalar or
access anyway.
Try and look at your system again and see if you can change the way you
allocate tasks in order to reduce the severity of your problem. For example,
if you need to access the data structure several times in a short period,
consider using a task that just acts as a semaphore, allowing another
task to seize the resource, access the data structure directly, and then
release the resource.
Jon Biggar
jonab@cam.unisys.com
^ permalink raw reply [flat|nested] 3+ messages in thread
* Pragma SHARED, tasks and shared variables
@ 1988-07-28 14:12 Norman Cohen
0 siblings, 0 replies; 3+ messages in thread
From: Norman Cohen @ 1988-07-28 14:12 UTC (permalink / raw)
Ref: INFO-ADA Volume 88 Issue 177 (Thu, Jul 28, 1988) Item #4
Vladimir Ivanovic asks:
>> If I specify that every read or update to an variable whose type is an
>> access type is a synchronization point for that variable by using the
>> pragma SHARED and naming that variable [LRM 9.11(7)], can I be assured
>> that the object designated by that variable will never be a local
>> copy of that object?
First let me rephrase the question, since the notion of a single access
value designating one variable (a shared variable) at one time and
another variable (a local copy) at another time doesn't make sense. The
real question is whether, between synchronization points, a local copy
can be used IN PLACE OF the variable designated by an access value.
The first sentence of 9.11(2) informally defines a shared variable as a
variable "accessible" by more than one task. Thus, if more than one task
executes some task body in the scope of an access type, all variables in
the collection associated with the access type are shared variables.
Therefore, an optimizing compiler may assume, when compiling one task
that uses a designated variable, that no other task updates the same
designated variable between synchronization points. Consider, for
example, the following code:
TYPE Reading_Type IS DELTA ... RANGE ...;
TYPE Reading_Pointer_Type IS ACCESS Reading_Type;
Reading_Pointer : Reading_Pointer_Type;
Shutdown_Requested : Boolean;
Polling_Interval : CONSTANT Duration := ...;
Next_Polling_Time : Calendar.Time :=
Calendar.Clock + Polling_Interval;
PRAGMA Shared(Reading_Pointer);
PRAGMA Shared(Shutdown_Requested);
...
WHILE NOT Shutdown_Requested LOOP
Poll_Device(Reading_Pointer.ALL);
DELAY Next_Polling_Time - Calendar.Clock;
Next_Polling_Time := Next_Polling_Time + Polling_Interval;
END LOOP;
Evaluation of the name Reading_Pointer.ALL examines the variable
Reading_Pointer, so the Shared pragma makes that name a synchronization
point for the variable Reading_Pointer, but NOT for the variable
Reading_Pointer.ALL. The notion of a synchronization point for a
particular variable (as opposed to for a task) is introduced in 9.11(9):
The pragma SHARED can be used to specify that every read or
update of a variable is a synchronization point for that
variable; that is, the above assumptions always hold for the
given variable (but not necessarily for other variables).
Therefore, the loop above could be optimized, in accordance with 9.11, to
the following:
<register X> := Reading_Pointer.ALL;
WHILE NOT Shutdown_Requested LOOP
Poll_Device( <register X> );
DELAY Next_Polling_Time - Calendar.Clock;
Next_Polling_Time := Next_Polling_Time + Polling_Interval;
END LOOP;
Reading_Pointer.ALL := <register X>;
Of course this optimization is illegitimate, even from a single-task
point of view, if some other access-type variable contains the same
access value as Reading_Pointer, and other statements refer to the
variable designated by that other access-type variable. Thus, as a
practical matter, the optimization can PROBABLY be defeated as follows:
PROCEDURE Make_Value_Unknown(Pointer: OUT Reading_Pointer_Type)
IS SEPARATE;
Dummy_Pointer : Reading_Pointer_Type; -- type of Reading_Pointer
...
Make_Value_Unknown(Dummy_Pointer);
WHILE NOT Shutdown_Requested LOOP
Poll_Device(Reading_Pointer.ALL);
Dummy_Pointer.ALL := Dummy_Pointer.ALL + Dummy_Pointer.ALL;
DELAY Next_Polling_Time - Calendar.Clock;
Next_Polling_Time := Next_Polling_Time + Polling_Interval;
END LOOP;
...
SEPARATE(...)
PROCEDURE Make_Value_Unknown(Pointer: OUT Reading_Pointer_Type) IS
BEGIN
Pointer := NEW Reading_Type'(0.0);
-- Repeated addition of zero won't overflow
END Make_Value_Unknown;
Unless the optimizing compiler performs cross-compilation-unit
optimizations at link time, or unless it actually compares pointer values
before the loop, it will not be able to determine whether
Dummy_Pointer = Reading_Pointer inside the loop. Thus, aside from any
considerations about what other tasks are doing, the compiler will be
unable to make a local copy of Reading_Pointer.ALL.
Of course this solution is less than satisfying. It is tricky and
obscure, it depends on certain assumptions about the behavior of the
optimizing compiler, and it requires useless code to be added to the loop
to reference Dummy_Pointer.ALL. I would much have preferred language
rules that permitted optimizations with surprising consequences (both the
kind permitted by LRM 9.11 and the kind permitted by LRM 11.6) only in
the presence of a pragma explicitly requesting such optimizations.
Norman Cohen
IBM Research
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~1988-07-28 16:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1988-07-28 1:03 Pragma SHARED, tasks and shared variables "Vladimir Ivanovic, x3-7786"
1988-07-28 16:33 ` Jonathan P. Biggar
-- strict thread matches above, loose matches on Subject: below --
1988-07-28 14:12 Norman Cohen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox