summaryrefslogtreecommitdiff
path: root/gcc/ada/s-stposu.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/s-stposu.adb')
-rw-r--r--gcc/ada/s-stposu.adb209
1 files changed, 195 insertions, 14 deletions
diff --git a/gcc/ada/s-stposu.adb b/gcc/ada/s-stposu.adb
index bf3a87e662f..0cdc90b7084 100644
--- a/gcc/ada/s-stposu.adb
+++ b/gcc/ada/s-stposu.adb
@@ -31,8 +31,9 @@
with Ada.Exceptions; use Ada.Exceptions;
with Ada.Unchecked_Deallocation;
-
+with System.Address_Image;
with System.Finalization_Masters; use System.Finalization_Masters;
+with System.IO; use System.IO;
with System.Soft_Links; use System.Soft_Links;
with System.Storage_Elements; use System.Storage_Elements;
@@ -248,21 +249,39 @@ package body System.Storage_Pools.Subpools is
-- +- Header_And_Padding --+
N_Ptr := Address_To_FM_Node_Ptr
- (N_Addr + Header_And_Padding - Header_Offset);
+ (N_Addr + Header_And_Padding - Header_Offset);
-- Prepend the allocated object to the finalization master
Attach (N_Ptr, Master.Objects'Unchecked_Access);
- if Master.Finalize_Address = null then
- Master.Finalize_Address := Fin_Address;
- end if;
-
-- Move the address from the hidden list header to the start of the
-- object. This operation effectively hides the list header.
Addr := N_Addr + Header_And_Padding;
+ -- Subpool allocations use heterogeneous masters to manage various
+ -- controlled objects. Associate a Finalize_Address with the object.
+ -- This relation pair is deleted when the object is deallocated or
+ -- when the associated master is finalized.
+
+ if Is_Subpool_Allocation then
+ pragma Assert (not Master.Is_Homogeneous);
+
+ Set_Finalize_Address (Addr, Fin_Address);
+
+ -- Normal allocations chain objects on homogeneous collections
+
+ else
+ pragma Assert (Master.Is_Homogeneous);
+
+ if Master.Finalize_Address = null then
+ Master.Finalize_Address := Fin_Address;
+ end if;
+ end if;
+
+ -- Non-controlled allocation
+
else
Addr := N_Addr;
end if;
@@ -315,6 +334,14 @@ package body System.Storage_Pools.Subpools is
if Is_Controlled then
+ -- Destroy the relation pair object - Finalize_Address since it is no
+ -- longer needed. If the object was chained on a homogeneous master,
+ -- this call does nothing. This is unconditional destruction since we
+ -- do not want to drag in additional data to determine the master
+ -- kind.
+
+ Delete_Finalize_Address (Addr);
+
-- Account for possible padding space before the header due to a
-- larger alignment.
@@ -382,6 +409,8 @@ package body System.Storage_Pools.Subpools is
N.Prev.Next := N.Next;
N.Next.Prev := N.Prev;
+ N.Prev := null;
+ N.Next := null;
Unlock_Task.all;
@@ -405,9 +434,22 @@ package body System.Storage_Pools.Subpools is
procedure Finalize_Pool (Pool : in out Root_Storage_Pool_With_Subpools) is
Curr_Ptr : SP_Node_Ptr;
Ex_Occur : Exception_Occurrence;
- Next_Ptr : SP_Node_Ptr;
Raised : Boolean := False;
+ function Is_Empty_List (L : not null SP_Node_Ptr) return Boolean;
+ -- Determine whether a list contains only one element, the dummy head
+
+ -------------------
+ -- Is_Empty_List --
+ -------------------
+
+ function Is_Empty_List (L : not null SP_Node_Ptr) return Boolean is
+ begin
+ return L.Next = L and then L.Prev = L;
+ end Is_Empty_List;
+
+ -- Start of processing for Finalize_Pool
+
begin
-- It is possible for multiple tasks to cause the finalization of a
-- common pool. Allow only one task to finalize the contents.
@@ -423,11 +465,8 @@ package body System.Storage_Pools.Subpools is
Pool.Finalization_Started := True;
- -- Skip the dummy head
-
- Curr_Ptr := Pool.Subpools.Next;
- while Curr_Ptr /= Pool.Subpools'Unchecked_Access loop
- Next_Ptr := Curr_Ptr.Next;
+ while not Is_Empty_List (Pool.Subpools'Unchecked_Access) loop
+ Curr_Ptr := Pool.Subpools.Next;
-- Perform the following actions:
@@ -446,8 +485,6 @@ package body System.Storage_Pools.Subpools is
Save_Occurrence (Ex_Occur, Fin_Occur);
end if;
end;
-
- Curr_Ptr := Next_Ptr;
end loop;
-- If the finalization of a particular master failed, reraise the
@@ -537,6 +574,150 @@ package body System.Storage_Pools.Subpools is
return Subpool.Owner;
end Pool_Of_Subpool;
+ ----------------
+ -- Print_Pool --
+ ----------------
+
+ procedure Print_Pool (Pool : Root_Storage_Pool_With_Subpools) is
+ Head : constant SP_Node_Ptr := Pool.Subpools'Unrestricted_Access;
+ Head_Seen : Boolean := False;
+ SP_Ptr : SP_Node_Ptr;
+
+ begin
+ -- Output the contents of the pool
+
+ -- Pool : 0x123456789
+ -- Subpools : 0x123456789
+ -- Fin_Start : TRUE <or> FALSE
+ -- Controller: OK <or> NOK
+
+ Put ("Pool : ");
+ Put_Line (Address_Image (Pool'Address));
+
+ Put ("Subpools : ");
+ Put_Line (Address_Image (Pool.Subpools'Address));
+
+ Put ("Fin_Start : ");
+ Put_Line (Pool.Finalization_Started'Img);
+
+ Put ("Controlled: ");
+ if Pool.Controller.Enclosing_Pool = Pool'Unrestricted_Access then
+ Put_Line ("OK");
+ else
+ Put_Line ("NOK (ERROR)");
+ end if;
+
+ SP_Ptr := Head;
+ while SP_Ptr /= null loop -- Should never be null
+ Put_Line ("V");
+
+ -- We see the head initially; we want to exit when we see the head a
+ -- second time.
+
+ if SP_Ptr = Head then
+ exit when Head_Seen;
+
+ Head_Seen := True;
+ end if;
+
+ -- The current element is null. This should never happend since the
+ -- list is circular.
+
+ if SP_Ptr.Prev = null then
+ Put_Line ("null (ERROR)");
+
+ -- The current element points back to the correct element
+
+ elsif SP_Ptr.Prev.Next = SP_Ptr then
+ Put_Line ("^");
+
+ -- The current element points to an erroneous element
+
+ else
+ Put_Line ("? (ERROR)");
+ end if;
+
+ -- Output the contents of the node
+
+ Put ("|Header: ");
+ Put (Address_Image (SP_Ptr.all'Address));
+ if SP_Ptr = Head then
+ Put_Line (" (dummy head)");
+ else
+ Put_Line ("");
+ end if;
+
+ Put ("| Prev: ");
+
+ if SP_Ptr.Prev = null then
+ Put_Line ("null");
+ else
+ Put_Line (Address_Image (SP_Ptr.Prev.all'Address));
+ end if;
+
+ Put ("| Next: ");
+
+ if SP_Ptr.Next = null then
+ Put_Line ("null");
+ else
+ Put_Line (Address_Image (SP_Ptr.Next.all'Address));
+ end if;
+
+ Put ("| Subp: ");
+
+ if SP_Ptr.Subpool = null then
+ Put_Line ("null");
+ else
+ Put_Line (Address_Image (SP_Ptr.Subpool.all'Address));
+ end if;
+
+ SP_Ptr := SP_Ptr.Next;
+ end loop;
+ end Print_Pool;
+
+ -------------------
+ -- Print_Subpool --
+ -------------------
+
+ procedure Print_Subpool (Subpool : Subpool_Handle) is
+ begin
+ if Subpool = null then
+ Put_Line ("null");
+ return;
+ end if;
+
+ -- Output the contents of a subpool
+
+ -- Owner : 0x123456789
+ -- Master: 0x123456789
+ -- Node : 0x123456789
+
+ Put ("Owner : ");
+ if Subpool.Owner = null then
+ Put_Line ("null");
+ else
+ Put_Line (Address_Image (Subpool.Owner'Address));
+ end if;
+
+ Put ("Master: ");
+ Put_Line (Address_Image (Subpool.Master'Address));
+
+ Put ("Node : ");
+ if Subpool.Node = null then
+ Put ("null");
+
+ if Subpool.Owner = null then
+ Put_Line (" OK");
+ else
+ Put_Line (" (ERROR)");
+ end if;
+ else
+ Put_Line (Address_Image (Subpool.Node'Address));
+ end if;
+
+ Print_Master (Subpool.Master);
+ end Print_Subpool;
+
-------------------------
-- Set_Pool_Of_Subpool --
-------------------------