* Deallocation of T'STORAGE_SIZE for a terminated task
@ 1988-09-21 13:36 Frank Prindle
0 siblings, 0 replies; 2+ messages in thread
From: Frank Prindle @ 1988-09-21 13:36 UTC (permalink / raw)
Given:
1. An allocator may be used with a task type to dynamically activate a task as
a consequence of 9.3(6). The run-time system reserves <task_type>'STORAGE_SIZE
storage units for use by this activation as stated in 13.7.2(14).
2. The task thus activated may eventually become completed and terminate as a
consequence of 9.4(5,6).
3. The task object allocated is considered inaccessible once the task has
terminated as a consequence of 4.8(7).
4. An implementation may (but need not) reclaim the storage reserved for the
task object once it has terminated, as stated in 4.8(7).
5. Automatic deallocation, when available, may be selectively inhibited via
pragma CONTROLLED as a consequence of 4.8(10).
6. Explicit deallocation of storage reserved for a dynamically allocated object
is provided by instantiation of UNCHECKED_DEALLOCATION, as stated in 4.8(12).
7. An instantiation of UNCHECKED_DEALLOCATION for a task object is guaranteed
to have ***NO*** effect on the task designated by the task object by
13.10.1(8)!
Then:
If an implementation does not provide for automatic storage deallocation, what
mechanism allows the repeated execution of dynamically activated tasks without
eventual consumption of the entire heap (or that partition reserved for
task objects) and the subsequent irrecoverable STORAGE_ERROR?
Notice that everything made sense up through point 6 above. The
implication was that one could not rely on an implementation to reclaim
dynamically allocated storage at the appropriate time, and should always
explicitly deallocate every object explicitly allocated (once it has been
determined that the object is no longer required). It is further implied
that a simple test of the 'TERMINATED attribute of the task object would
suffice to determine when a task object (i.e. the stack for use by a task
activation) is no longer required. The killer is 7 above. When 13.10.1(8)
says "no effect on the task", does this imply that the storage is not to be
deallocated? But that is the very job intended to be performed by this
generic library procedure, as stated in 4.8(12)!
I think we need a clarification of 13.10.1(8) here, because at least one
implementation has taken it to mean that the storage cannot be deallocated.
Therefore, dynamic activation of transient tasks (i.e. tasks which will
eventually terminate on their own) appears to be a lost cause.
It is quite possible that yet another section of the LRM clarifies this
question, but the index leads me only in an endless circle of the paragraphs
cited above. Any pointers would be warmly welcomed.
Sincerely,
Frank Prindle
Prindle@NADC.arpa
^ permalink raw reply [flat|nested] 2+ messages in thread
* Deallocation of T'STORAGE_SIZE for a terminated task
@ 1988-09-22 13:21 Norman Cohen
0 siblings, 0 replies; 2+ messages in thread
From: Norman Cohen @ 1988-09-22 13:21 UTC (permalink / raw)
Ref: INFO-ADA Digest Volume 88 Issue 200 (Thu, Sep 22, 1988) Item #2
Consider the following program:
PROCEDURE Main IS
TYPE Work_Item_Type IS ...;
TASK TYPE Work_Processor_Type IS
ENTRY Assign_Work (Work: IN Work_Item_Type);
END Work_Processor_Type;
TYPE Work_Processor_Pointer_Type IS ACCESS Work_Processor_Type;
Work_Item : Work_Item_Type;
New_Work_Processor : Work_Processor_Pointer_Type;
PROCEDURE Deallocate_Work_Processor IS
NEW Unchecked_Deallocation
(Work_Processor_Type, Work_Processor_Pointer_Type);
TASK BODY Work_Processor_Type IS SEPARATE;
PROCEDURE Wait_For_Work (Work_Item: OUT Work_Item_Type);
BEGIN
LOOP
Wait_For_Work (Work_Item);
New_Work_Processor := NEW Work_Processor_Type;
New_Work_Processor.Assign_Work (Work_Item);
Deallocate_Work_Processor (New_Work_Processor);
END LOOP;
END Main;
Work processors are assigned as work items arrive. Several work
processors may be active simultaneously, asynchronously processing their
assigned work items. The intent of the last statement in the loop is
to deallocate storage for each work-processor task when it completes its
work, so that the storage may be used for other work processors.
If the task allocated in the third statement of the loop completes its
work and terminates before the main program advances to the fourth
statement in the loop, we would expect the storage for the task object
to be reclaimed as for an allocated object of any other type. However,
if (as is likely) the task is still active when the fourth statement of
the loop is reached, the call on Deallocate_Work_Processor
has no effect on the task. (In particular, the task is not aborted so
that storage for the task object can be reclaimed.) That is the point of
Reference Manual paragraph 3.10.1(8) (which is a note, not a rule).
There are several options available to the friendly designer of a run-
time system, and several recourses available to the user whose run-time-
system designer was not inclined to be friendly.
First, we must distinguish between two kinds of storage associated with
tasks, the task control block (data maintained by the run-time system
for such purposes as task scheduling and task communication) and the
task stack (used for application data local to the task body or local to
subprograms invoked by the task). A typical implementation has a task
object corresponding to a task control block and a representation clause
for T'Storage_Size, where T is a task type, determining the size of the
stack allocated when a task of the type is activated.
Options available to the friendly designer of a run-time system include:
- Deallocating the task stack (Work_Procesor_Type'Storage_Size bytes)
immediately upon task termination, even if the task control block
(Work_Processor_Type'Size bits) must remain in existence for such
purposes as evaluating the 'Terminated attribute or raising
Tasking_Error in any other task that calls an entry of the terminated
task.
- Implementing a task object as a pointer to a task control block, but
representing the task object of a terminated task by a null pointer and
deallocating storage for the task control block itself as soon as the
task has terminated.
- Automatically reclaiming storage for allocated task objects as soon as
the task has terminated, provided that the task object is no longer
accessible by access values. (This is a restricted form of incremental
garbage collection in which reference counts can be used.)
- Having instances of Unchecked_Deallocation set a "deallocation pending"
flag in the task control block if the task objects for which
deallocation was requested designate still-active tasks. Upon
termination, the task control block would be deallocated if its
"deallocation pending" flag were set.
Options available to the user of a run-time system whose designer was not
inclined to be friendly include the following:
- Introduce another task, of low-priority, to explicitly manage
allocation and deallocation of task objects. Thus the assignment
New_Work_Processor := NEW Work_Processor_Type;
in the program above would be replaced by an entry call on this new
task:
Work_Processor_Manager.Get_New_Task (New_Work_Processor);
The low-priority task would maintain a list of currently allocated
tasks and periodically query the 'Terminated attribute of tasks on the
list, deallocating a task object and removing the pointer to that
object from the list whenever the designated task is found to be
terminated.
- If there is a known maximum on the number of work processors that will
be active simultaneously, declare an array of that many
Work_Processor_Type objects. Add an entry, called once at program
start-up, to tell a Work_Processor_Type task its index within this
array. Declare a list of indices of currently idle tasks, initialized
to a list containing every task index. Modify the Work_Processor_Type
task body so that, rather than terminating when it is done with its
work, it adds its index to the list of indices of idle tasks and loops
back to its Assign_Work entry to wait for more work. The assignment
statement allocating a new task would be replaced by a statement
removing the first idle-task index from the list, then calling the
Assign_Work entry of the corresponding array element.
Norman Cohen
IBM Research
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~1988-09-22 13:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1988-09-21 13:36 Deallocation of T'STORAGE_SIZE for a terminated task Frank Prindle
-- strict thread matches above, loose matches on Subject: below --
1988-09-22 13:21 Norman Cohen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox