Go Back   Rhinocerus > Newsgroup > Newsgroup comp.lang.* 1 > Newsgroup comp.lang.ada

Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old 10-05-2005, 03:22 PM
REH
Guest
 
Posts: n/a
Default volatile vs aliased

I'm converting some code written for Gnat to compile with Apex. The
software has bindings to C functions (OS calls). Some of these take
System.Address as parameters. Apex complains about the variables used
in these calls (via 'Address) because they not volatile or aliased (or
imported, exported, etc.). My question is: which should I use? Is
there any difference whether a variable is volatile or aliased?

I am assuming the compiler is concerned about the variable possibly
being changed in the call (which, of course, is true). Is there a way
to satisfy the compiler without stopping optimizations of the variable
after the call, or do I need to use a second variable to do this?

Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #2 (permalink)  
Old 10-05-2005, 06:22 PM
Ludovic Brenta
Guest
 
Posts: n/a
Default Re: volatile vs aliased

"REH" <spamjunk@stny.rr.com> writes:
> I'm converting some code written for Gnat to compile with Apex. The
> software has bindings to C functions (OS calls). Some of these take
> System.Address as parameters. Apex complains about the variables used
> in these calls (via 'Address) because they not volatile or aliased (or
> imported, exported, etc.). My question is: which should I use? Is
> there any difference whether a variable is volatile or aliased?
>
> I am assuming the compiler is concerned about the variable possibly
> being changed in the call (which, of course, is true). Is there a way
> to satisfy the compiler without stopping optimizations of the variable
> after the call, or do I need to use a second variable to do this?


I like this warning given by Apex; I think it would be nice if GNAT
would also warn in this situation.

pragma Volatile (Variable) says the compiler must not optimise away
any reads or writes to that variable, and that it may not add extra
reads or writes beyond those you explicitly request in your program
text. You want to use that for hardware registers, where a "read"
operation may have a side effect such as changing the device's state.

Whenever you access a variable through an address value, the variable
is aliased, so you should say that explicitly. Otherwise, the
compiler may be tempted to place the variable in a processor register,
which has no address.

In addition, pragma Import (Ada, Variable) says that the compiler may
not insert default initialisations for that variable, or assume
anything about the value of the variable, before you write to it. But
the compiler may do optimisations, because it is allowed to assume
that no side effects occur when you read from or write to the variable
(that is, side effects not explicitly requested from the program
text). In your situation, it seems that you want something like this
(which, incidentally, I use very often):

type T is ...;

procedure Read_Variable (At_Address : in System.Address;
Into : out T) is
V : aliased T;
-- suppress default initialisation, I know what I'm doing.
pragma Import (Ada, V);
for V'Address use At_Address;
begin
-- perform my own explicit validation of the variable, perhaps
-- using 'Valid; then, copy into Into:
Into := V;
end Read_Variable;

--
Ludovic Brenta.
Reply With Quote
  #3 (permalink)  
Old 10-05-2005, 06:39 PM
REH
Guest
 
Posts: n/a
Default Re: volatile vs aliased


Ludovic Brenta wrote:
> I like this warning given by Apex; I think it would be nice if GNAT
> would also warn in this situation.
>
> pragma Volatile (Variable) says the compiler must not optimise away
> any reads or writes to that variable, and that it may not add extra
> reads or writes beyond those you explicitly request in your program
> text. You want to use that for hardware registers, where a "read"
> operation may have a side effect such as changing the device's state.
>
> Whenever you access a variable through an address value, the variable
> is aliased, so you should say that explicitly. Otherwise, the
> compiler may be tempted to place the variable in a processor register,
> which has no address.
>
> In addition, pragma Import (Ada, Variable) says that the compiler may
> not insert default initialisations for that variable, or assume
> anything about the value of the variable, before you write to it. But
> the compiler may do optimisations, because it is allowed to assume
> that no side effects occur when you read from or write to the variable
> (that is, side effects not explicitly requested from the program
> text). In your situation, it seems that you want something like this
> (which, incidentally, I use very often):
>
> type T is ...;
>
> procedure Read_Variable (At_Address : in System.Address;
> Into : out T) is
> V : aliased T;
> -- suppress default initialisation, I know what I'm doing.
> pragma Import (Ada, V);
> for V'Address use At_Address;
> begin
> -- perform my own explicit validation of the variable, perhaps
> -- using 'Valid; then, copy into Into:
> Into := V;
> end Read_Variable;
>
> --
> Ludovic Brenta.


VERY helpful! Thank you so much.

I'm dealing with a situation where I have to do symbol table lookups
from the OS which return an address to procedure or function. This is
done in several places in the code. The reason is I have to support
different hardware dynamically. For example, if I am on board A, I
call Foo. The comparible subprogram on B is Bar. So, I cannot just
make pragma exports for them both as one will be undefined. Anyways,
to make it easier, I wanted to make a generic which just returned an
access type without having to do the pragma Import and for X'address in
every case. Then calling the subprogram is simple. My first pass is:

generic
type Data_Type is private;
type Data_Ptr is access all Data_Type;
function Address_To_Access(Addr : System.Address) return Data_Ptr;

function Address_To_Access(Addr : System.Address) return Data_Ptr is
begin
if Addr = System.Null_Address then
return null;
else
declare
Data: aliased Data_Type;
for Data'Address use Addr;
begin
return Data'Unchecked_Access;
end;
end if;
end Address_To_Access;


Two questions:
1) Is this even a smart thing to do?
2) How would I define a generic like the above for an subprogram with
an unknown signature?

Thanks again for the help.

REH

Reply With Quote
  #4 (permalink)  
Old 10-05-2005, 07:46 PM
Ludovic Brenta
Guest
 
Posts: n/a
Default Re: volatile vs aliased

"REH" <spamjunk@stny.rr.com> writes:
> VERY helpful! Thank you so much.
>
> I'm dealing with a situation where I have to do symbol table lookups
> from the OS which return an address to procedure or function. This is
> done in several places in the code. The reason is I have to support
> different hardware dynamically. For example, if I am on board A, I
> call Foo. The comparible subprogram on B is Bar. So, I cannot just
> make pragma exports for them both as one will be undefined. Anyways,
> to make it easier, I wanted to make a generic which just returned an
> access type without having to do the pragma Import and for X'address in
> every case. Then calling the subprogram is simple. My first pass is:
>
> generic
> type Data_Type is private;
> type Data_Ptr is access all Data_Type;
> function Address_To_Access(Addr : System.Address) return Data_Ptr;
>
> function Address_To_Access(Addr : System.Address) return Data_Ptr is
> begin
> if Addr = System.Null_Address then
> return null;
> else
> declare
> Data: aliased Data_Type;
> for Data'Address use Addr;
> begin
> return Data'Unchecked_Access;
> end;
> end if;
> end Address_To_Access;
>
>
> Two questions:
> 1) Is this even a smart thing to do?


Why do you have to use a generic? Why not just:

procedure Call_Procedure (At_Address : in System.Address) is
procedure Proc;
for Proc'Address use At_Address;
begin
Proc;
end Call_Procedure;

The above effectively converts from an address to an
access-to-procedure, and calls the procedure. If what you want is
convert from an address to an access-to-data, you should probably use
Ada.Address_To_Access_Conversions.

> 2) How would I define a generic like the above for an subprogram with
> an unknown signature?


I don't know how you could call a procedure with unknown parameters.
Or perhaps you mean with one known parameter which is the address of
a record containing arbitrary parameters?

generic
type Parameter_Type is limited private; -- [1]
procedure Call_Procedure (At_Address : in System.Address;
Params : in Parameter_Type);

procedure Call_Procedure (At_Address : in System.Address;
Params : in Parameter_Type) is
procedure Proc (Params : in System.Address);
for Proc'Address use At_Address;
begin
Proc (Params'Address);
end Call_Procedure;

Is this close to what you want?

[1] I think the type has to be declared limited, so that it is always
passed by reference to Call_Procedure. This guarantees that the
parameter has an address, and is not in a register. I have not
compiled or tried this code, so please take it with due care.

--
Ludovic Brenta.
Reply With Quote
  #5 (permalink)  
Old 10-05-2005, 08:02 PM
REH
Guest
 
Posts: n/a
Default Re: volatile vs aliased


Ludovic Brenta wrote:
> Why do you have to use a generic? Why not just:
>
> procedure Call_Procedure (At_Address : in System.Address) is
> procedure Proc;
> for Proc'Address use At_Address;
> begin
> Proc;
> end Call_Procedure;


I was just trying to by lazy, and not do that everytime. If I have to,
I have to.

>
> I don't know how you could call a procedure with unknown parameters.
> Or perhaps you mean with one known parameter which is the address of
> a record containing arbitrary parameters?

The caller would know. What I don't know to do (and probably can't) is
define a generic that can be instantiated using *any* access type, even
one to a subprogram.

I guess I am spending more time trying to avoid work, than just doing
it.

REH

Reply With Quote
  #6 (permalink)  
Old 10-05-2005, 08:11 PM
Ludovic Brenta
Guest
 
Posts: n/a
Default Re: volatile vs aliased

"REH" <spamjunk@stny.rr.com> writes:
> Ludovic Brenta wrote:
>> Why do you have to use a generic? Why not just:
>>
>> procedure Call_Procedure (At_Address : in System.Address) is
>> procedure Proc;
>> for Proc'Address use At_Address;
>> begin
>> Proc;
>> end Call_Procedure;

>
> I was just trying to by lazy, and not do that everytime. If I have to,
> I have to.


I don't understand. Do you mean to say that one Call_Procedure is not
sufficient? That you'd have to have many such procedures? Why?

>> I don't know how you could call a procedure with unknown parameters.
>> Or perhaps you mean with one known parameter which is the address of
>> a record containing arbitrary parameters?

> The caller would know. What I don't know to do (and probably can't) is
> define a generic that can be instantiated using *any* access type, even
> one to a subprogram.
>
> I guess I am spending more time trying to avoid work, than just doing
> it.


In my example, the Parameter_Type can contain an access-to-subprogram.
Of course, you need to instantiate the generic once per parameter
profile, and there may be many different ones, so that the generic
doesn't really save you much work.

--
Ludovic Brenta.

Reply With Quote
  #7 (permalink)  
Old 10-05-2005, 08:20 PM
REH
Guest
 
Posts: n/a
Default Re: volatile vs aliased


Ludovic Brenta wrote:
> I don't understand. Do you mean to say that one Call_Procedure is not
> sufficient? That you'd have to have many such procedures? Why?

I've not sure if you are asking if I need several procedures per
address (I do not) or why I have many address (I do). Either way, your
way is probably best: just make one wrapper procedure for each
address. I was "creating" the procedure from the address at each call
point. Sigh. Sometimes the simplest answer eludes me.

Thanks for the great advice.
REH

Reply With Quote
  #8 (permalink)  
Old 10-05-2005, 08:55 PM
Simon Wright
Guest
 
Posts: n/a
Default Re: volatile vs aliased

Ludovic Brenta <ludovic@ludovic-brenta.org> writes:

> procedure Call_Procedure (At_Address : in System.Address) is
> procedure Proc;
> for Proc'Address use At_Address;
> begin
> Proc;
> end Call_Procedure;


With GCC 4.0.0, you need to say

pragma Import (C, Proc);

as well.

with Ada.Text_IO; use Ada.Text_IO;With System;
procedure Acc is
procedure Call (At_Address : System.Address) is
procedure Proc;
pragma Import (C, Proc);
for Proc'Address use At_Address;
begin
Proc;
end Call;
procedure Callee is
begin
Put_Line ("hello world.");
end Callee;
begin
Call (Callee'Address);
end Acc;

Reply With Quote
  #9 (permalink)  
Old 10-05-2005, 11:38 PM
Randy Brukardt
Guest
 
Posts: n/a
Default Re: volatile vs aliased

"Ludovic Brenta" <ludovic@ludovic-brenta.org> wrote in message
news:87mzlnomca.fsf@ludovic-brenta.org...
....
> In your situation, it seems that you want something like this
> (which, incidentally, I use very often):
>
> type T is ...;
>
> procedure Read_Variable (At_Address : in System.Address;
> Into : out T) is
> V : aliased T;
> -- suppress default initialisation, I know what I'm doing.
> pragma Import (Ada, V);
> for V'Address use At_Address;
> begin
> -- perform my own explicit validation of the variable, perhaps
> -- using 'Valid; then, copy into Into:
> Into := V;
> end Read_Variable;


This seems like a good time to mention that I think the explicit use of
System.Address in Ada 95 and Ada 200Y code is usually a mistake. Since
pragma Convention can be used to ensure that general access types have the
appropriate representation, its rare that Address needs to be used for
interfacing. (There is only a handful of uses of Address in Claw, for
example.)

Moreover, when you *do* need to use it, Address_to_Access_Conversions is the
best way to convert it, not an overlay (which at best blocks optimizations
and at worst won't even work right).

type T is ...;

procedure Read_Variable (At_Address : in System.Address;
Into : out T) is
package AAC is new System.Address_to_Access_Conversions (T);
V : AAC.Object_Pointer := AAC.To_Pointer (At_Address);
begin
-- perform my own explicit validation of the pointer's contents, perhaps
-- using 'Valid; then, copy into Into:
Into := V.all;
end Read_Variable;

But it is better still to declare an appropriate type and never use Address
in the first place:

type Pointer_T is access all T;
pragma Convention (C, Pointer_T);

Address clauses should be restricted to mapping to hardware, IMHO.

Randy.



Reply With Quote
  #10 (permalink)  
Old 10-06-2005, 12:02 AM
tmoran@acm.org
Guest
 
Posts: n/a
Default Re: volatile vs aliased

> its rare that Address needs to be used for interfacing. (There is only
> a handful of uses of Address in Claw, for example.)

All in one package, where one procedure needs a System.Address parameter.
Reply With Quote
  #11 (permalink)  
Old 10-06-2005, 05:21 AM
Ludovic Brenta
Guest
 
Posts: n/a
Default Re: volatile vs aliased

"REH" <spamjunk@stny.rr.com> writes:

> Ludovic Brenta wrote:
>> I don't understand. Do you mean to say that one Call_Procedure is not
>> sufficient? That you'd have to have many such procedures? Why?

> I've not sure if you are asking if I need several procedures per
> address (I do not) or why I have many address (I do). Either way, your
> way is probably best: just make one wrapper procedure for each
> address. I was "creating" the procedure from the address at each call
> point. Sigh. Sometimes the simplest answer eludes me.


Even simpler: you need just one wrapper per parameter profile,
i.e. one wrapper for all parameterless procedures, etc.

--
Ludovic Brenta.

Reply With Quote
  #12 (permalink)  
Old 10-06-2005, 08:05 AM
Martin Krischik
Guest
 
Posts: n/a
Default Re: volatile vs aliased

Ludovic Brenta wrote:

> pragma Volatile (Variable) says the compiler must not optimise away
> any reads or writes to that variable, and that it may not add extra
> reads or writes beyond those you explicitly request in your program
> text. You want to use that for hardware registers, where a "read"
> operation may have a side effect such as changing the device's state.


Interesting! So with pragma Volatile (X) the following two statements are
not the same:

Y := X * X;
Y := X ** 2;

Good to know!

Martin

--
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com
Reply With Quote
  #13 (permalink)  
Old 10-06-2005, 08:52 AM
Dmitry A. Kazakov
Guest
 
Posts: n/a
Default Re: volatile vs aliased

On Thu, 06 Oct 2005 10:05:38 +0200, Martin Krischik wrote:

> Ludovic Brenta wrote:
>
>> pragma Volatile (Variable) says the compiler must not optimise away
>> any reads or writes to that variable, and that it may not add extra
>> reads or writes beyond those you explicitly request in your program
>> text. You want to use that for hardware registers, where a "read"
>> operation may have a side effect such as changing the device's state.

>
> Interesting! So with pragma Volatile (X) the following two statements are
> not the same:
>
> Y := X * X;
> Y := X ** 2;
>
> Good to know!


BTW, even without Volatile, they are not necessary same!

For intervals X*X /= X**2!

Example:

[-1, 2] * [-1, 2] = [-1, 4]

[-1, 2]**2 = [2, 4]

X**2 is as twice as more accurate than X*X.

To improve accuracy of * and /, arguments need to be analyzed for
dependency. X + X = 2 * X, no matter what.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Reply With Quote
  #14 (permalink)  
Old 10-06-2005, 11:36 AM
Rolf
Guest
 
Posts: n/a
Default Re: volatile vs aliased

Martin Krischik wrote:
> Ludovic Brenta wrote:
>
> > pragma Volatile (Variable) says the compiler must not optimise away
> > any reads or writes to that variable, and that it may not add extra
> > reads or writes beyond those you explicitly request in your program
> > text. You want to use that for hardware registers, where a "read"
> > operation may have a side effect such as changing the device's state.

>
> Interesting! So with pragma Volatile (X) the following two statements are
> not the same:
>
> Y := X * X;
> Y := X ** 2;


Do we have a difference to C/C++ increment operator here? consider

pragma Volatile (x);
x := x + 1; -- (1)
vs.
x++; -- (2)

In the Ada case (1) we are forced to have "read from memory",
"increment" and "write to memory" instructions, whereas in C/C++ (2)
you can get a single "increment memory" instruction (presuming the
mentioned assembler instructions exist on a given processor)

Rolf

Reply With Quote
  #15 (permalink)  
Old 10-06-2005, 01:40 PM
REH
Guest
 
Posts: n/a
Default Re: volatile vs aliased


Randy Brukardt wrote:
> This seems like a good time to mention that I think the explicit use of
> System.Address in Ada 95 and Ada 200Y code is usually a mistake. Since
> pragma Convention can be used to ensure that general access types have the
> appropriate representation, its rare that Address needs to be used for
> interfacing. (There is only a handful of uses of Address in Claw, for
> example.)
>
> Moreover, when you *do* need to use it, Address_to_Access_Conversions is the
> best way to convert it, not an overlay (which at best blocks optimizations
> and at worst won't even work right).
>
> type T is ...;
>
> procedure Read_Variable (At_Address : in System.Address;
> Into : out T) is
> package AAC is new System.Address_to_Access_Conversions (T);
> V : AAC.Object_Pointer := AAC.To_Pointer (At_Address);
> begin
> -- perform my own explicit validation of the pointer's contents, perhaps
> -- using 'Valid; then, copy into Into:
> Into := V.all;
> end Read_Variable;
>
> But it is better still to declare an appropriate type and never use Address
> in the first place:
>
> type Pointer_T is access all T;
> pragma Convention (C, Pointer_T);
>
> Address clauses should be restricted to mapping to hardware, IMHO.
>
> Randy.

Randy,
That's good stuff. Will it still apply when the address is to a
subprogram? Can Address_to_Access_Conversions be instantiated with a
subprogram? That's what I've been trying to do, but I don't know how
to make a generic that takes an access to an arbitrary subprogram type.
So, I think I am "stuck" using the for X'address specification.

Thanks,
REH

Reply With Quote
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 02:43 AM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.