diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-15 16:19:40 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-15 16:19:40 +0000 |
commit | 499f3d24605eba5c1be61b4cb04e01008554361a (patch) | |
tree | f3daea4db10883323aa8c12fd8894fd4fa00c5f3 /gcc/ada/a-tasatt.adb | |
parent | 68fa183e21f353a336f5d6343ce64b57179e7df1 (diff) | |
download | gcc-499f3d24605eba5c1be61b4cb04e01008554361a.tar.gz |
2005-03-08 Robert Dewar <dewar@adacore.com>
* s-bitops.adb, s-bitops.ads,
s-taprop-os2.adb, s-intman-vms.ads, s-intman-vxworks.ads,
s-taprop-vxworks.adb, a-caldel.ads, a-calend.adb, a-tasatt.adb,
tbuild.ads, s-finimp.adb, s-imgwch.adb, s-intman.ads, s-intman.ads,
s-memory.adb, s-soflin.ads, s-taasde.ads, s-taprob.adb, s-taprop.ads,
s-taprop.ads, s-tasini.adb, s-tasini.ads, s-tasini.ads, s-tasini.ads,
s-taskin.ads, s-tasren.adb, s-tassta.adb, s-tassta.ads, s-tassta.ads,
s-tasuti.ads, s-tataat.ads, s-tataat.ads, s-tataat.ads, s-tataat.ads,
s-tpoben.adb, s-tpoben.adb, s-tpobop.ads: Update comments. Minor
reformatting.
2005-03-08 Eric Botcazou <ebotcazou@adacore.com>
* utils2.c (build_binary_op): Fix typo.
2005-03-08 Doug Rupp <rupp@adacore.com>
* s-crtl.ads (popen,pclose): New imports.
2005-03-08 Cyrille Comar <comar@adacore.com>
* comperr.adb (Compiler_Abort): remove references to obsolete
procedures in the bug boxes for various GNAT builds.
2005-03-08 Vincent Celier <celier@adacore.com>
* snames.ads, snames.adb: Save as Unix text file, not as DOS text file
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96512 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/a-tasatt.adb')
-rw-r--r-- | gcc/ada/a-tasatt.adb | 363 |
1 files changed, 179 insertions, 184 deletions
diff --git a/gcc/ada/a-tasatt.adb b/gcc/ada/a-tasatt.adb index 35801e2896e..0fc74d5231f 100644 --- a/gcc/ada/a-tasatt.adb +++ b/gcc/ada/a-tasatt.adb @@ -7,7 +7,7 @@ -- B o d y -- -- -- -- Copyright (C) 1991-1994, Florida State University -- --- Copyright (C) 1995-2004, Ada Core Technologies -- +-- Copyright (C) 1995-2005, Ada Core Technologies -- -- -- -- GNARL is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -32,174 +32,171 @@ -- -- ------------------------------------------------------------------------------ --- The following notes are provided in case someone decides the --- implementation of this package is too complicated, or too slow. --- Please read this before making any "simplifications". +-- The following notes are provided in case someone decides the implementation +-- of this package is too complicated, or too slow. Please read this before +-- making any "simplifications". --- Correct implementation of this package is more difficult than one --- might expect. After considering (and coding) several alternatives, --- we settled on the present compromise. Things we do not like about --- this implementation include: +-- Correct implementation of this package is more difficult than one might +-- expect. After considering (and coding) several alternatives, we settled on +-- the present compromise. Things we do not like about this implementation +-- include: --- - It is vulnerable to bad Task_Id values, to the extent of --- possibly trashing memory and crashing the runtime system. +-- - It is vulnerable to bad Task_Id values, to the extent of possibly +-- trashing memory and crashing the runtime system. --- - It requires dynamic storage allocation for each new attribute value, --- except for types that happen to be the same size as System.Address, --- or shorter. +-- - It requires dynamic storage allocation for each new attribute value, +-- except for types that happen to be the same size as System.Address, or +-- shorter. -- - Instantiations at other than the library level rely on being able to -- do down-level calls to a procedure declared in the generic package body. -- This makes it potentially vulnerable to compiler changes. --- The main implementation issue here is that the connection from --- task to attribute is a potential source of dangling references. +-- The main implementation issue here is that the connection from task to +-- attribute is a potential source of dangling references. -- When a task goes away, we want to be able to recover all the storage -- associated with its attributes. The Ada mechanism for this is --- finalization, via controlled attribute types. For this reason, --- the ARM requires finalization of attribute values when the --- associated task terminates. +-- finalization, via controlled attribute types. For this reason, the ARM +-- requires finalization of attribute values when the associated task +-- terminates. --- This finalization must be triggered by the tasking runtime system, --- during termination of the task. Given the active set of instantiations --- of Ada.Task_Attributes is dynamic, the number and types of attributes +-- This finalization must be triggered by the tasking runtime system, during +-- termination of the task. Given the active set of instantiations of +-- Ada.Task_Attributes is dynamic, the number and types of attributes -- belonging to a task will not be known until the task actually terminates. -- Some of these types may be controlled and some may not. The RTS must find -- some way to determine which of these attributes need finalization, and -- invoke the appropriate finalization on them. --- One way this might be done is to create a special finalization chain --- for each task, similar to the finalization chain that is used for --- controlled objects within the task. This would differ from the usual --- finalization chain in that it would not have a LIFO structure, since --- attributes may be added to a task at any time during its lifetime. --- This might be the right way to go for the longer term, but at present --- this approach is not open, since GNAT does not provide such special --- finalization support. +-- One way this might be done is to create a special finalization chain for +-- each task, similar to the finalization chain that is used for controlled +-- objects within the task. This would differ from the usual finalization +-- chain in that it would not have a LIFO structure, since attributes may be +-- added to a task at any time during its lifetime. This might be the right +-- way to go for the longer term, but at present this approach is not open, +-- since GNAT does not provide such special finalization support. --- Lacking special compiler support, the RTS is limited to the --- normal ways an application invokes finalization, i.e. +-- Lacking special compiler support, the RTS is limited to the normal ways an +-- application invokes finalization, i.e. --- a) Explicit call to the procedure Finalize, if we know the type --- has this operation defined on it. This is not sufficient, since --- we have no way of determining whether a given generic formal --- Attribute type is controlled, and no visibility of the associated --- Finalize procedure, in the generic body. +-- a) Explicit call to the procedure Finalize, if we know the type has this +-- operation defined on it. This is not sufficient, since we have no way +-- of determining whether a given generic formal Attribute type is +-- controlled, and no visibility of the associated Finalize procedure, in +-- the generic body. --- b) Leaving the scope of a local object of a controlled type. --- This does not help, since the lifetime of an instantiation of --- Ada.Task_Attributes does not correspond to the lifetimes of the --- various tasks which may have that attribute. +-- b) Leaving the scope of a local object of a controlled type. This does not +-- help, since the lifetime of an instantiation of Ada.Task_Attributes +-- does not correspond to the lifetimes of the various tasks which may +-- have that attribute. --- c) Assignment of another value to the object. This would not help, --- since we then have to finalize the new value of the object. +-- c) Assignment of another value to the object. This would not help, since +-- we then have to finalize the new value of the object. --- d) Unchecked deallocation of an object of a controlled type. --- This seems to be the only mechanism available to the runtime --- system for finalization of task attributes. +-- d) Unchecked deallocation of an object of a controlled type. This seems to +-- be the only mechanism available to the runtime system for finalization +-- of task attributes. --- We considered two ways of using unchecked deallocation, both based --- on a linked list of that would hang from the task control block. +-- We considered two ways of using unchecked deallocation, both based on a +-- linked list of that would hang from the task control block. -- In the first approach the objects on the attribute list are all derived -- from one controlled type, say T, and are linked using an access type to --- T'Class. The runtime system has an Unchecked_Deallocation for T'Class --- with access type T'Class, and uses this to deallocate and finalize all --- the items in the list. The limitation of this approach is that each +-- T'Class. The runtime system has an Unchecked_Deallocation for T'Class with +-- access type T'Class, and uses this to deallocate and finalize all the +-- items in the list. The limitation of this approach is that each -- instantiation of the package Ada.Task_Attributes derives a new record --- extension of T, and since T is controlled (RM 3.9.1 (3)), instantiation --- is only allowed at the library level. - --- In the second approach the objects on the attribute list are of --- unrelated but structurally similar types. Unchecked conversion is --- used to circument Ada type checking. Each attribute-storage node --- contains not only the attribute value and a link for chaining, but --- also a pointer to a descriptor for the corresponding instantiation --- of Task_Attributes. The instantiation-descriptor contains a --- pointer to a procedure that can do the correct deallocation and --- finalization for that type of attribute. On task termination, the --- runtime system uses the pointer to call the appropriate deallocator. - --- While this gets around the limitation that instantations be at --- the library level, it relies on an implementation feature that --- may not always be safe, i.e. that it is safe to call the --- Deallocate procedure for an instantiation of Ada.Task_Attributes --- that no longer exists. In general, it seems this might result in --- dangling references. - --- Another problem with instantiations deeper than the library level --- is that there is risk of storage leakage, or dangling references --- to reused storage. That is, if an instantiation of Ada.Task_Attributes --- is made within a procedure, what happens to the storage allocated for --- attributes, when the procedure call returns? Apparently (RM 7.6.1 (4)) --- any such objects must be finalized, since they will no longer be --- accessible, and in general one would expect that the storage they occupy --- would be recovered for later reuse. (If not, we would have a case of --- storage leakage.) Assuming the storage is recovered and later reused, --- we have potentially dangerous dangling references. When the procedure --- containing the instantiation of Ada.Task_Attributes returns, there --- may still be unterminated tasks with associated attribute values for --- that instantiation. When such tasks eventually terminate, the RTS --- will attempt to call the Deallocate procedure on them. If the --- corresponding storage has already been deallocated, when the master --- of the access type was left, we have a potential disaster. This --- disaster is compounded since the pointer to Deallocate is probably --- through a "trampoline" which will also have been destroyed. - --- For this reason, we arrange to remove all dangling references --- before leaving the scope of an instantiation. This is ugly, since --- it requires traversing the list of all tasks, but it is no more ugly --- than a similar traversal that we must do at the point of instantiation --- in order to initialize the attributes of all tasks. At least we only --- need to do these traversals if the type is controlled. - --- We chose to defer allocation of storage for attributes until the --- Reference function is called or the attribute is first set to a value --- different from the default initial one. This allows a potential --- savings in allocation, for attributes that are not used by all tasks. +-- extension of T, and since T is controlled (RM 3.9.1 (3)), instantiation is +-- only allowed at the library level. + +-- In the second approach the objects on the attribute list are of unrelated +-- but structurally similar types. Unchecked conversion is used to circument +-- Ada type checking. Each attribute-storage node contains not only the +-- attribute value and a link for chaining, but also a pointer to descriptor +-- for the corresponding instantiation of Task_Attributes. The instantiation +-- descriptor contains pointer to a procedure that can do the correct +-- deallocation and finalization for that type of attribute. On task +-- termination, the runtime system uses the pointer to call the appropriate +-- deallocator. + +-- While this gets around the limitation that instantations be at the library +-- level, it relies on an implementation feature that may not always be safe, +-- i.e. that it is safe to call the Deallocate procedure for an instantiation +-- of Ada.Task_Attributes that no longer exists. In general, it seems this +-- might result in dangling references. + +-- Another problem with instantiations deeper than the library level is that +-- there is risk of storage leakage, or dangling references to reused +-- storage. That is, if an instantiation of Ada.Task_Attributes is made +-- within a procedure, what happens to the storage allocated for attributes, +-- when the procedure call returns? Apparently (RM 7.6.1 (4)) any such +-- objects must be finalized, since they will no longer be accessible, and in +-- general one would expect that the storage they occupy would be recovered +-- for later reuse. (If not, we would have a case of storage leakage.) +-- Assuming the storage is recovered and later reused, we have potentially +-- dangerous dangling references. When the procedure containing the +-- instantiation of Ada.Task_Attributes returns, there may still be +-- unterminated tasks with associated attribute values for that instantiation. +-- When such tasks eventually terminate, the RTS will attempt to call the +-- Deallocate procedure on them. If the corresponding storage has already +-- been deallocated, when the master of the access type was left, we have a +-- potential disaster. This disaster is compounded since the pointer to +-- Deallocate is probably through a "trampoline" which will also have been +-- destroyed. + +-- For this reason, we arrange to remove all dangling references before +-- leaving the scope of an instantiation. This is ugly, since it requires +-- traversing the list of all tasks, but it is no more ugly than a similar +-- traversal that we must do at the point of instantiation in order to +-- initialize the attributes of all tasks. At least we only need to do these +-- traversals if the type is controlled. + +-- We chose to defer allocation of storage for attributes until the Reference +-- function is called or the attribute is first set to a value different from +-- the default initial one. This allows a potential savings in allocation, +-- for attributes that are not used by all tasks. -- For efficiency, we reserve space in the TCB for a fixed number of --- direct-access attributes. These are required to be of a size that --- fits in the space of an object of type System.Address. Because --- we must use unchecked bitwise copy operations on these values, they --- cannot be of a controlled type, but that is covered automatically --- since controlled objects are too large to fit in the spaces. +-- direct-access attributes. These are required to be of a size that fits in +-- the space of an object of type System.Address. Because we must use +-- unchecked bitwise copy operations on these values, they cannot be of a +-- controlled type, but that is covered automatically since controlled +-- objects are too large to fit in the spaces. -- We originally deferred the initialization of these direct-access --- attributes, just as we do for the indirect-access attributes, and --- used a per-task bit vector to keep track of which attributes were --- currently defined for that task. We found that the overhead of --- maintaining this bit-vector seriously slowed down access to the --- attributes, and made the fetch operation non-atomic, so that even --- to read an attribute value required locking the TCB. Therefore, --- we now initialize such attributes for all existing tasks at the time --- of the attribute instantiation, and initialize existing attributes --- for each new task at the time it is created. +-- attributes, just as we do for the indirect-access attributes, and used a +-- per-task bit vector to keep track of which attributes were currently +-- defined for that task. We found that the overhead of maintaining this +-- bit-vector seriously slowed down access to the attributes, and made the +-- fetch operation non-atomic, so that even to read an attribute value +-- required locking the TCB. Therefore, we now initialize such attributes for +-- all existing tasks at the time of the attribute instantiation, and +-- initialize existing attributes for each new task at the time it is +-- created. -- The latter initialization requires a list of all the instantiation --- descriptors. Updates to this list, as well as the bit-vector that --- is used to reserve slots for attributes in the TCB, require mutual --- exclusion. That is provided by the Lock/Unlock_RTS. - --- One special problem that added complexity to the design is that --- the per-task list of indirect attributes contains objects of --- different types. We use unchecked pointer conversion to link --- these nodes together and access them, but the records may not have --- identical internal structure. Initially, we thought it would be --- enough to allocate all the common components of the records at the --- front of each record, so that their positions would correspond. --- Unfortunately, GNAT adds "dope" information at the front of a record, --- if the record contains any controlled-type components. +-- descriptors. Updates to this list, as well as the bit-vector that is used +-- to reserve slots for attributes in the TCB, require mutual exclusion. That +-- is provided by the Lock/Unlock_RTS. + +-- One special problem that added complexity to the design is that the +-- per-task list of indirect attributes contains objects of different types. +-- We use unchecked pointer conversion to link these nodes together and +-- access them, but the records may not have identical internal structure. +-- Initially, we thought it would be enough to allocate all the common +-- components of the records at the front of each record, so that their +-- positions would correspond. Unfortunately, GNAT adds "dope" information at +-- the front of a record, if the record contains any controlled-type +-- components. -- --- This means that the offset of the fields we use to link the nodes is --- at different positions on nodes of different types. To get around this, --- each attribute storage record consists of a core node and wrapper. --- The core nodes are all of the same type, and it is these that are --- linked together and generally "seen" by the RTS. Each core node --- contains a pointer to its own wrapper, which is a record that contains --- the core node along with an attribute value, approximately --- as follows: +-- This means that the offset of the fields we use to link the nodes is at +-- different positions on nodes of different types. To get around this, each +-- attribute storage record consists of a core node and wrapper. The core +-- nodes are all of the same type, and it is these that are linked together +-- and generally "seen" by the RTS. Each core node contains a pointer to its +-- own wrapper, which is a record that contains the core node along with an +-- attribute value, approximately as follows: -- type Node; -- type Node_Access is access all Node; @@ -211,51 +208,50 @@ -- Wrapper : Access_Wrapper; -- end record; -- type Wrapper is record --- Noed : aliased Node; --- Value : aliased Attribute; -- the generic formal type +-- Dummy_Node : aliased Node; +-- Value : aliased Attribute; -- the generic formal type -- end record; --- Another interesting problem is with the initialization of --- the instantiation descriptors. Originally, we did this all via --- the Initialize procedure of the descriptor type and code in the --- package body. It turned out that the Initialize procedure needed --- quite a bit of information, including the size of the attribute --- type, the initial value of the attribute (if it fits in the TCB), --- and a pointer to the deallocator procedure. These needed to be --- "passed" in via access discriminants. GNAT was having trouble --- with access discriminants, so all this work was moved to the --- package body. +-- Another interesting problem is with the initialization of the +-- instantiation descriptors. Originally, we did this all via the Initialize +-- procedure of the descriptor type and code in the package body. It turned +-- out that the Initialize procedure needed quite a bit of information, +-- including the size of the attribute type, the initial value of the +-- attribute (if it fits in the TCB), and a pointer to the deallocator +-- procedure. These needed to be "passed" in via access discriminants. GNAT +-- was having trouble with access discriminants, so all this work was moved +-- to the package body. with Ada.Task_Identification; --- used for Task_Id +-- Used for Task_Id -- Null_Task_Id -- Current_Task with System.Error_Reporting; --- used for Shutdown; +-- Used for Shutdown; with System.Storage_Elements; --- used for Integer_Address +-- Used for Integer_Address with System.Task_Primitives.Operations; --- used for Write_Lock +-- Used for Write_Lock -- Unlock -- Lock/Unlock_RTS with System.Tasking; --- used for Access_Address +-- Used for Access_Address -- Task_Id -- Direct_Index_Vector -- Direct_Index with System.Tasking.Initialization; --- used for Defer_Abortion +-- Used for Defer_Abortion -- Undefer_Abortion -- Initialize_Attributes_Link -- Finalize_Attributes_Link with System.Tasking.Task_Attributes; --- used for Access_Node +-- Used for Access_Node -- Access_Dummy_Wrapper -- Deallocator -- Instance @@ -263,13 +259,13 @@ with System.Tasking.Task_Attributes; -- Access_Instance with Ada.Exceptions; --- used for Raise_Exception +-- Used for Raise_Exception with Unchecked_Conversion; with Unchecked_Deallocation; pragma Elaborate_All (System.Tasking.Task_Attributes); --- to ensure the initialization of object Local (below) will work +-- To ensure the initialization of object Local (below) will work package body Ada.Task_Attributes is @@ -295,11 +291,10 @@ package body Ada.Task_Attributes is pragma Warnings (Off); -- We turn warnings off for the following declarations of the - -- To_Attribute_Handle conversions, since these are used only - -- for small attributes where we know that there are no problems - -- with alignment, but the compiler will generate warnings for - -- the occurrences in the large attribute case, even though - -- they will not actually be used. + -- To_Attribute_Handle conversions, since these are used only for small + -- attributes where we know that there are no problems with alignment, but + -- the compiler will generate warnings for the occurrences in the large + -- attribute case, even though they will not actually be used. function To_Attribute_Handle is new Unchecked_Conversion (System.Address, Attribute_Handle); @@ -327,10 +322,10 @@ package body Ada.Task_Attributes is (Access_Dummy_Wrapper, Access_Wrapper); pragma Warnings (On); -- To fetch pointer to actual wrapper of attribute node. We turn off - -- warnings since this may generate an alignment warning. The warning - -- can be ignored since Dummy_Wrapper is only a non-generic standin - -- for the real wrapper type (we never actually allocate objects of - -- type Dummy_Wrapper). + -- warnings since this may generate an alignment warning. The warning can + -- be ignored since Dummy_Wrapper is only a non-generic standin for the + -- real wrapper type (we never actually allocate objects of type + -- Dummy_Wrapper). function To_Access_Dummy_Wrapper is new Unchecked_Conversion (Access_Wrapper, Access_Dummy_Wrapper); @@ -364,7 +359,7 @@ package body Ada.Task_Attributes is -- Initialized in package body type Wrapper is record - Noed : aliased Node; + Dummy_Node : aliased Node; Value : aliased Attribute := Initial_Value; -- The generic formal type, may be controlled @@ -450,7 +445,7 @@ package body Ada.Task_Attributes is ((null, Local'Unchecked_Access, null), Initial_Value); POP.Lock_RTS; - P := W.Noed'Unchecked_Access; + P := W.Dummy_Node'Unchecked_Access; P.Wrapper := To_Access_Dummy_Wrapper (W); P.Next := To_Access_Node (TT.Indirect_Attributes); TT.Indirect_Attributes := To_Access_Address (P); @@ -605,14 +600,14 @@ package body Ada.Task_Attributes is P := P.Next; end loop; - -- Unlock RTS here to follow the lock ordering rule that - -- prevent us from using new (i.e the Global_Lock) while - -- holding any other lock. + -- Unlock RTS here to follow the lock ordering rule that prevent us + -- from using new (i.e the Global_Lock) while holding any other + -- lock. POP.Unlock_RTS; W := new Wrapper'((null, Local'Unchecked_Access, null), Val); POP.Lock_RTS; - P := W.Noed'Unchecked_Access; + P := W.Dummy_Node'Unchecked_Access; P.Wrapper := To_Access_Dummy_Wrapper (W); P.Next := To_Access_Node (TT.Indirect_Attributes); TT.Indirect_Attributes := To_Access_Address (P); @@ -661,9 +656,9 @@ package body Ada.Task_Attributes is if Local.Index /= 0 then -- Get value of attribute. Warnings off, because for large - -- attributes, this code can generate alignment warnings. - -- But of course large attributes are never directly addressed - -- so in fact we will never execute the code in this case. + -- attributes, this code can generate alignment warnings. But of + -- course large attributes are never directly addressed so in fact + -- we will never execute the code in this case. pragma Warnings (Off); return To_Attribute_Handle @@ -734,13 +729,13 @@ begin POP.Lock_RTS; - -- Add this instantiation to the list of all instantiations. + -- Add this instantiation to the list of all instantiations Local.Next := System.Tasking.Task_Attributes.All_Attributes; System.Tasking.Task_Attributes.All_Attributes := Local'Unchecked_Access; - -- Try to find space for the attribute in the TCB. + -- Try to find space for the attribute in the TCB Local.Index := 0; Two_To_J := 1; @@ -754,9 +749,9 @@ begin In_Use := In_Use or Two_To_J; Local.Index := J; - -- This unchecked conversions can give a warning when the - -- the alignment is incorrect, but it will not be used in - -- such a case anyway, so the warning can be safely ignored. + -- This unchecked conversions can give a warning when the the + -- alignment is incorrect, but it will not be used in such a + -- case anyway, so the warning can be safely ignored. pragma Warnings (Off); To_Attribute_Handle (Local.Initial_Value'Access).all := @@ -773,13 +768,13 @@ begin -- Attribute goes directly in the TCB if Local.Index /= 0 then - -- Replace stub for initialization routine - -- that is called at task creation. + -- Replace stub for initialization routine that is called at task + -- creation. Initialization.Initialize_Attributes_Link := System.Tasking.Task_Attributes.Initialize_Attributes'Access; - -- Initialize the attribute, for all tasks. + -- Initialize the attribute, for all tasks declare C : System.Tasking.Task_Id := System.Tasking.All_Tasks_List; @@ -795,8 +790,8 @@ begin -- Attribute goes into a node onto a linked list else - -- Replace stub for finalization routine - -- that is called at task termination. + -- Replace stub for finalization routine that is called at task + -- termination. Initialization.Finalize_Attributes_Link := System.Tasking.Task_Attributes.Finalize_Attributes'Access; |