[comp.lang.ada] Interpretation of LRM 13.10.1

F.Zwarts@KVI.NL ("Fred Zwarts, KVI, Groningen, NL.") (02/23/90)

Hello all,

I am rather new to Ada and I am not quite sure that this is the right place to
ask, but I do not know a better place.

I am uncertain about the interpretation of LRM 13.10.1(8) on the
UNCHECKED_DEALLOCATION procedure, where I read:

"If X designates a task object, the call FREE(X) has no effect on the task
...".

My question is: What means "no effect"?
Suppose X designates a terminated task, see LRM 9.4(6-10).
Can FREE(X) be used to reclaim memory held by such a terminated task, like a
task control block? Does the LRM allow such an interpretation?

If this interpretation is not allowed, I can imagin a case in which one runs
out of memory because of a large amount of terminated tasks. If always at least
one such task is running, it is not possible to leave the block in which the
declaration of X's type was elaborated LRM 9.4(6), which could otherwise be a
way to reclaim memory.

Fred Zwarts                             E-mail:         INFOADA@KVI.nl
Kernfysisch Versneller Instituut
9747 AA  Groningen
The Netherlands

madmats%elcit.epfl.ch@vma.cc.cmu.edu (Mats Weber) (02/27/90)

>I am rather new to Ada and I am not quite sure that this is the right place to
>ask, but I do not know a better place.

It is the right place to ask.

>I am uncertain about the interpretation of LRM 13.10.1(8) on the
>UNCHECKED_DEALLOCATION procedure, where I read:

>"If X designates a task object, the call FREE(X) has no effect on the task
>...".

>My question is: What means "no effect"?
>Suppose X designates a terminated task, see LRM 9.4(6-10).
>Can FREE(X) be used to reclaim memory held by such a terminated task, like a
>task control block? Does the LRM allow such an interpretation?

The LRM says nothing about the deallocation of the working storage (stack space,

etc.) of tasks. Most implementations I know of reclaim that storage when the
block that declares the corresponding task type is left, but this behaviour is
not required by the LRM.
"no effect" means that calling Free(X) does not affect the execution of the
designated task, in particular, the designated task does not stop and must still

terminate before its master can be exited. Free(X) simply makes the designated
task inaccessible.

>If this interpretation is not allowed, I can imagin a case in which one runs
>out of memory because of a large amount of terminated tasks. If always at least

>one such task is running, it is not possible to leave the block in which the
>declaration of X's type was elaborated LRM 9.4(6), which could otherwise be a
>way to reclaim memory.

You are right. Most implementations do not reclaim the stack storage of
terminated tasks. A workaround is to put these unused tasks into a pool and
reuse them, allocating new tasks only when the pool is empty.

Mats Weber
Swiss Federal Institute of Technology
EPFL DI LGL
1015 Lausanne
Switzerland

E-mail : madmats@elcit.epfl.ch
phone  : +41 21 693 52 92
fax    : +41 21 693 22 20

NCOHEN@IBM.COM ("Norman H. Cohen") (02/27/90)

13.10.1(8) is one of the most often misinterpreted paragraphs in the RM.
(Fortunately, it's a note, and therefore not officially part of the
language definition.  LRM 2.7(1) states, "Furthermore, comments do not
influence the effect of a program; their sole purpose is the
enlightenment of the human reader."  John Goodenough once quipped that
the LRM Note paragraphs do not influence the definition of the language;
their sole purpose is to confuse the reader.)

There are two sources of confusion:

1. Informally, we often use the word "task" to mean a task unit or a
   task object.  However, in the (usually) precise language of the LRM,
   a "task" in Ada is neither an object nor a program unit, but a process
   (a thread of control).  A TASK OBJECT "designates" some task.
   (See 9(2) and 9.2(2).)

2. The word "designates" also has another technical meaning in the LRM:
   An access value "designates" the object it points to (see 3.8(1)).
   Unfortunately, the word "designates" is used in both senses in the
   first sentence of 13.10.1(8).

Now lets look at the first sentence of 13.10.1(8):

   If X designates a task object, the call FREE(X) has no effect on
   the task designated by the task object.

(Here X is an access value and FREE is an instance of
UNCHECKED_DEALLOCATION.)  An informal paraphrase is:

   If X points to a task object, the call FREE(X) has no effect on
   the thread of control corresponding to that task object.

Thus, for example, you can't abort a task by attempting to deallocate it.

When an instance of UNCHECKED_DEALLOCATION is applied to a task object
designating a terminated task, a good compiler will reclaim the storage
occupied by the task object.  Not all compilers are good.

Norman H. Cohen

jcallen@Encore.COM (Jerry Callen) (02/27/90)

In article <foo> F.Zwarts@KVI.NL ("Fred Zwarts, KVI, Groningen, NL.") writes:

>I am uncertain about the interpretation of LRM 13.10.1(8) on the
>UNCHECKED_DEALLOCATION procedure, where I read:
>
>"If X designates a task object, the call FREE(X) has no effect on the task
>...".
>
>My question is: What means "no effect"?
>Suppose X designates a terminated task, see LRM 9.4(6-10).
>Can FREE(X) be used to reclaim memory held by such a terminated task, like a
>task control block? Does the LRM allow such an interpretation?

The "no effect" statement means that freeing a task object won't do
something unpleasant to it (like free its stacks/control blocks out from
under it).

You can't really reclaim ALL of the storage associated with a task until the
task's scope disappears, even in the case of a task created with an allocator;
there may be other copies of the pointer floating around, and the owners of
those copies may (erroneously) query the 'CALLABLE/'TERMINATED attributes
of the task. You could argue that, by using Unchecked_Deallocation, you are
explicitly telling the RTS that there are no dangling pointers, but I
think it's safer for the RTS to assume that there might be. Note that a
clever implementation will release nearly all of the storage associated with
a task (stacks, most control blocks, etc.) at task completion; all that really
has to hang around is a stub of the TCB that can be used to implement the
above attributes.

>If this interpretation is not allowed, I can imagin a case in which one runs
>out of memory because of a large amount of terminated tasks. If always at least
>one such task is running, it is not possible to leave the block in which the
>declaration of X's type was elaborated LRM 9.4(6), which could otherwise be a
>way to reclaim memory.

Hopefully your RTS is going to free as much storage as it can at task
completion. Trying to "help it" with Unchecked_Deallocation is probably
useless.

>Fred Zwarts                             E-mail:         INFOADA@KVI.nl
>Kernfysisch Versneller Instituut
>9747 AA  Groningen
>The Netherlands

-- Jerry Callen
   jcallen@encore.com
   (508) 460-0500

Loren@cup.portal.com (Loren Louis Hart) (02/28/90)

In his artical about LRM 13.10.1 Fred Zwarts writes:
>Hello all,

>I am rather new to Ada and I am not quite sure that this is the right place to
>ask, but I do not know a better place.

This is exactly the right place for this question.  It is much better than the
"My language is better than your language" discussion that has been apearing
in this news group lately.

>I am uncertain about the interpretation of LRM 13.10.1(8) on the
>UNCHECKED_DEALLOCATION procedure, where I read:
>
>"If X designates a task object, the call FREE(X) has no effect on the task
>...".
>
>My question is: What means "no effect"?
>Suppose X designates a terminated task, see LRM 9.4(6-10).
>Can FREE(X) be used to reclaim memory held by such a terminated task, like a
>task control block? Does the LRM allow such an interpretation?

Has no effect means exactly what it says.  The program behaves the same in all
respects if it is there or not.  It will be the same (other than maybe
efficiency) as if the compiler generated no code.  My understanding is that
a task is an object, you can deallocate objects, it is potentially confusing
and dangerious to allow someone to deallocate a task.  The choice is either to
ignore the request or generate an error; in this case they decided the 
request should be ignored.

>If this interpretation is not allowed, I can imagin a case in which one runs
>out of memory because of a large amount of terminated tasks. If always at leas
t
>one such task is running, it is not possible to leave the block in which the
>declaration of X's type was elaborated LRM 9.4(6), which could otherwise be a
>way to reclaim memory.

Most implementations (all that I know about) deallocate all of the memory
that a task uses upon termination.  The only exception is sometimes the
fairly small entry for that task that indicates if the task is running and
where to find its memory is kept around.

Loren L. Hart
loren@cup.portal.com
San Jose, California

stt@inmet.inmet.com (03/03/90)

With regard to reclaiming storage for a terminated task:

It is useful to distinguish between a "task object" and
a "task".  A "task object" designates a task.  An access type
designates a task object (or a record/array object containing
a task object).  When you perform an unchecked deallocation,
the space for the task object may be reclaimed, and it is erroneous
if some other access value is later used to try to refer
to this task object.  Therefore, it *is* legitimate for
an implementation to free *all* storage associated with a terminated
*task* when the task object is freed (Sorry not to agree with you Jerry!).

However, it is *not* legitimate to free the storage associated
with a task with live sub-tasks (i.e. "completed" but not "terminated"),
nor is it permissible to implicitly abort a non-completed
task when its task object is freed.

Using a relatively simple trick, it is actually possible to
free the space devoted to a task as soon as it terminates,
even if its task object still exists.  The trick is
to store a "generation number" within the task control block,
and bump that number when reusing the TCB for a new task.
The same generation number is stored with the task object,
and a task is considered terminated if the generation number
in its task object doesn't match the generation number in
the TCB it points at.

By the way, the ARG (Ada Rapporteur(sp?) Group) recently decided to reverse
an earlier decision, and consider a reference to a task
outside of its scope as erroneous (the dreaded task-returning function
problem).  This means that TCBs can be reclaimed when the task object's
scope is exited, at the latest.

S. Tucker Taft     stt%inmet@uunet.uu.net; uunet!inmet!stt
Intermetrics, Inc.
Cambridge, MA  02138

jbg@sei.cmu.edu (John Goodenough) (03/06/90)

In article Re: Interpretation of LRM 13.10.1 of 2 Mar 90 18:21:00 GMT
stt@inmet.inmet.com writes: 

> By the way, the ARG (Ada Rapporteur(sp?) Group) recently decided to reverse
> an earlier decision, and consider a reference to a task
> outside of its scope as erroneous (the dreaded task-returning function
> problem).

Just a reminder that the ARG does not have the last word on interpreting the
Standard.  ARG decisions are subject to review at higher approval levels and
are not definitive until approved by ISO WG9 (responsible for the ISO Ada
Standard) and the AJPO (responsible for the ANSI standard).  Although I would
not expect the decision on functions returning tasks to be reversed after
further review, ARG decisions have in the past been reversed in response to
objections.

John B. Goodenough					Goodenough@sei.cmu.edu
Chair, ARG
Software Engineering Institute				412-268-6391
-- 
John B. Goodenough					Goodenough@sei.cmu.edu
Software Engineering Institute				412-268-6391