Version 1.4 of ai05s/ai05-0189-1.txt

Unformatted version of ai05s/ai05-0189-1.txt version 1.4
Other versions for file ai05s/ai05-0189-1.txt

!standard D.7 (19.1/2)          10-06-07 AI05-0189-1/02
!standard H.4(23.3/2)
!class amendment 09-11-03
!status work item 09-11-03
!status received 09-11-03
!priority Low
!difficulty Easy
!subject Restriction No_Allocators_After_Elaboration
!summary
Provide a restriction that disallows use of allocators after library unit elaboration is complete.
!problem
It is quite common that a resource-constrained long-lived application wants to avoid any heap allocation after library unit elaboration is complete, to ensure that there is no heap growth during the ongoing execution of the program.
!proposal
(see summary)
!wording
Add after D.7(19.1/2):
No_Allocators_After_Elaboration
Specifies that the only allocators that may be evaluated during the execution of the partition are during the elaboration of the library_items of the partition, prior to the invocation of any main subprogram. An allocator shall not occur after the begin of a task body nor in the main subprogram. If an implementation chooses to detect a violation of this restriction at run-time, Storage_Error should be raised; otherwise the behavior is implementation defined.
Revise H.4(23.3/2) as follows:
* the following restrictions defined in D.7: No_Task_Hierarchy, No_Abort_Statement, No_Implicit_Heap_Allocation {, No_Allocators_After_Elaboration}; and
!discussion
We considered restricting allocators to the environment task, but felt it was important to allow non-environment tasks to perform allocators during their activation. Note that allowing non-environment tasks to perform allocators means that synchronization is still required during heap allocation.
We do not require this restriction to be entirely enforced prior to execution. We perhaps could do so, but to do it completely could require significant static analysis.
!examples
** TBD **
!ACATS test
ACATS B and C tests are needed.
!appendix

From: Tucker Taft
Sent: Friday, June 12, 2009  6:23 AM

This is an official request from Ada Switzerland for a restriction that
disallows allocation after library-unit elaboration is complete.

[Editor's note: Not sure when Tucker becaome Swiss! I presume he meant to
say that he is relaying an official request from Ada Switzerland, or some
such thing.]

****************************************************************

From: Jean-Pierre Rosen
Sent: Friday, June 12, 2009  12:05 PM

No_Local_Allocator seems to come close...

****************************************************************

From: Tucker Taft
Sent: Friday, June 12, 2009  3:44 PM

True, but it is too limiting.  It means that you can't use allocators in
subprograms, even if they are called only during library-unit elaboration.
That pretty much defeats any kind of abstraction.

Many embedded systems have the model of allowing dynamic allocation during
start up, but not thereafter. Ada really ought to support that. What I would
imagine is a restriction that disallows use of a default storage pool after
elaboration is complete, while allowing user-defined storage pools to check
in the Allocate procedure against some global flag that indicates whether
library-level elaboration is complete.

****************************************************************

From: Tullio Vardanega
Sent: Saturday, June 13, 2009  3:05 AM

Something along the line of Tucker's outline would be very useful indeed.
At present we often find ourselves in the need of cheating ourselves and
the compiler by removing pragma Restrictions to permit the elaboration code
to use dynamic memory allocation, but in that manner we lose the ability to
enforce the restriction for the code executed after elaboration.

****************************************************************

From: Tucker Taft
Sent: Monday, June 7, 2010  10:53 AM

Here is a minor update to the AI on the
restriction No_Allocators_After_Elaboration. [This is version /02 of the AI - Editor.]
Note that the minutes implied that library-level tasks weren't certain to be
activated until the "begin" of the main subprogram.  Actually, they must be
activated before the main subprogram is invoked at all. (See 10.2(20-21) which
indicates that the call on the main subprogram follows the "begin" of the
conceptual environment task body.)

****************************************************************

From: Steve Baird
Sent: Monday, June 7, 2010  1:32 PM

> An allocator shall not occur after the begin of a task body nor in the main subprogram.

This is fundamentally a rule about a runtime check and the (not particularly
common) statically detectable cases listed above don't seem to me to be worth
special treatment.

> If an implementation chooses to detect a violation of this restriction
> at run-time, Storage_Error should be raised;

Why is this optional? Do you think that the performance advantage of this
approach outweighs the portability costs?

****************************************************************

From: Steve Baird
Sent: Monday, June 7, 2010  1:47 PM

> Why is this optional? Do you think that the performance advantage of
> this approach outweighs the portability costs?

It's a significant overhead to require the testing of a global variable on every
single allocation, so it seems reasonable not to require it. I suppose we could
associate a check name with it, so that the check could be specifically
suppressed?

****************************************************************

From: Tucker Taft
Sent: Monday, June 7, 2010  1:52 PM

>> An allocator shall not occur after the begin of a task body nor in
>> the main subprogram.
>
> This is fundamentally a rule about a runtime check and the (not
> particularly common) statically detectable cases listed above don't
> seem to me to be worth special treatment.

The straw vote was 5-3-3 to keep a static check on task bodies.  So that's why
it is there.

>> If an implementation chooses to detect a violation of this
>> restriction at run-time, Storage_Error should be raised;
>
> Why is this optional? Do you think that the performance advantage of
> this approach outweighs the portability costs?

This is the standard way that restrictions are worded.
See, e.g., D.7(20) on Max_Storage_At_Blocking.

****************************************************************

From: Steve Baird
Sent: Monday, June 7, 2010  2:05 PM

> The straw vote was 5-3-3 to keep a static check on task bodies.  So
> that's why it is there.
>

Fine.

> This is the standard way that restrictions are worded.
> See, e.g., D.7(20) on Max_Storage_At_Blocking.

That's a bad example because the meaning of what is being checked there is very
implementation dependent.

Since Max_Asynchronous_Select_Nesting has the same sort of wording, however, I
do see your point.

****************************************************************

From: Jean-Pierre Rosen
Sent: Monday, June 7, 2010  2:42 PM

>> Why is this optional? Do you think that the performance advantage of
>> this approach outweighs the portability costs?
>
> It's a significant overhead to require the testing of a global
> variable on every single allocation, so it seems reasonable not to
> require it. I suppose we could associate a check name with it, so that
> the check could be specifically suppressed?

What good is there in putting a restriction if it not checked neither at
compile-time nor at run-time?

I'd rather require a run-time check, and allow the compiler to reject the
restriction if it is not supported.

****************************************************************

From: Tucker Taft
Sent: Monday, June 7, 2010  2:54 PM

As I told Steve, this is merely a question of consistency with other
restrictions. Exactly how restrictions are enforced has pretty much always been
to some degree implementation defined.

****************************************************************

Questions? Ask the ACAA Technical Agent