home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / s-secsta.adb < prev    next >
Text File  |  2000-07-19  |  13KB  |  370 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --               S Y S T E M . S E C O N D A R Y _ S T A C K                --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.45 $
  10. --                                                                          --
  11. --          Copyright (C) 1992-1999 Free Software Foundation, Inc.          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. with System.Soft_Links;
  37. with System.Parameters;
  38. with Unchecked_Conversion;
  39. with Unchecked_Deallocation;
  40.  
  41. package body System.Secondary_Stack is
  42.  
  43.    package SSL renames System.Soft_Links;
  44.  
  45.    use type SSE.Storage_Offset;
  46.    use type System.Parameters.Size_Type;
  47.  
  48.    SS_Ratio_Dynamic : constant Boolean :=
  49.                         Parameters.Sec_Stack_Ratio = Parameters.Dynamic;
  50.  
  51.    --                                      +------------------+
  52.    --                                      |       Next       |
  53.    --                                      +------------------+
  54.    --                                      |                  | Last (200)
  55.    --                                      |                  |
  56.    --                                      |                  |
  57.    --                                      |                  |
  58.    --                                      |                  |
  59.    --                                      |                  |
  60.    --                                      |                  | First (101)
  61.    --                                      +------------------+
  62.    --                         +----------> |          |       |
  63.    --                         |            +----------+-------+
  64.    --                         |                    |  |
  65.    --                         |                    ^  V
  66.    --                         |                    |  |
  67.    --                         |            +-------+----------+
  68.    --                         |            |       |          |
  69.    --                         |            +------------------+
  70.    --                         |            |                  | Last (100)
  71.    --                         |            |         C        |
  72.    --                         |            |         H        |
  73.    --    +-----------------+  |  +-------->|         U        |
  74.    --    |  Current_Chunk -|--+  |         |         N        |
  75.    --    +-----------------+     |         |         K        |
  76.    --    |       Top      -|-----+         |                  | First (1)
  77.    --    +-----------------+               +------------------+
  78.    --    | Default_Size    |               |       Prev       |
  79.    --    +-----------------+               +------------------+
  80.    --
  81.    --
  82.    type Memory is array (Mark_Id range <>) of SSE.Storage_Element;
  83.  
  84.    type Chunk_Id (First, Last : Mark_Id);
  85.    type Chunk_Ptr is access all Chunk_Id;
  86.  
  87.    type Chunk_Id (First, Last : Mark_Id) is record
  88.       Prev, Next : Chunk_Ptr;
  89.       Mem        : Memory (First .. Last);
  90.    end record;
  91.  
  92.    type Stack_Id is record
  93.       Top           : Mark_Id;
  94.       Default_Size  : SSE.Storage_Count;
  95.       Current_Chunk : Chunk_Ptr;
  96.    end record;
  97.  
  98.    type Fixed_Stack_Id is record
  99.       Top  : Mark_Id;
  100.       Last : Mark_Id;
  101.       Mem  : Memory (1 .. Mark_Id'Last);
  102.    end record;
  103.  
  104.    type Stack_Ptr is access Stack_Id;
  105.    type Fixed_Stack_Ptr is access Fixed_Stack_Id;
  106.  
  107.    function From_Addr is new Unchecked_Conversion (Address, Stack_Ptr);
  108.    function To_Addr   is new Unchecked_Conversion (Stack_Ptr, System.Address);
  109.    function To_Stack  is new Unchecked_Conversion (Fixed_Stack_Ptr, Stack_Ptr);
  110.    function To_Fixed  is new Unchecked_Conversion (Stack_Ptr, Fixed_Stack_Ptr);
  111.  
  112.    procedure Free is new Unchecked_Deallocation (Chunk_Id, Chunk_Ptr);
  113.  
  114.    --------------
  115.    -- Allocate --
  116.    --------------
  117.  
  118.    procedure SS_Allocate
  119.      (Address      : out System.Address;
  120.       Storage_Size : SSE.Storage_Count)
  121.    is
  122.       Stack        : constant Stack_Ptr :=
  123.                        From_Addr (SSL.Get_Sec_Stack_Addr.all);
  124.       Fixed_Stack  : Fixed_Stack_Ptr;
  125.       Chunk        : Chunk_Ptr;
  126.       Max_Align    : constant Mark_Id := Mark_Id (Standard'Maximum_Alignment);
  127.       Max_Size     : constant Mark_Id :=
  128.                        ((Mark_Id (Storage_Size) + Max_Align - 1) / Max_Align)
  129.                          * Max_Align;
  130.  
  131.       Count_Unreleased_Chunks : Natural;
  132.       To_Be_Released_Chunk    : Chunk_Ptr;
  133.  
  134.    begin
  135.       --  If the secondary stack is fixed in the primary stack, then the
  136.       --  handling becomes simple
  137.  
  138.       if not SS_Ratio_Dynamic then
  139.          Fixed_Stack := To_Fixed (Stack);
  140.  
  141.          if Fixed_Stack.Top + Max_Size > Fixed_Stack.Last then
  142.             raise Storage_Error;
  143.          end if;
  144.  
  145.          Address := Fixed_Stack.Mem (Fixed_Stack.Top)'Address;
  146.          Fixed_Stack.Top := Fixed_Stack.Top + Mark_Id (Max_Size);
  147.          return;
  148.       end if;
  149.  
  150.       Chunk := Stack.Current_Chunk;
  151.  
  152.       --  The Current_Chunk may not be the good one if a lot of release
  153.       --  operations have taken place. So go down the stack if necessary
  154.  
  155.       while  Chunk.First > Stack.Top loop
  156.          Chunk := Chunk.Prev;
  157.       end loop;
  158.  
  159.       --  Find out if the available memory in the current chunk is sufficient.
  160.       --  if not, go to the next one and eventally create the necessary room
  161.  
  162.       Count_Unreleased_Chunks := 0;
  163.  
  164.       while Chunk.Last - Stack.Top + 1 < Max_Size loop
  165.          if Chunk.Next /= null then
  166.  
  167.             --  Release unused non-first empty chunk
  168.  
  169.             if Chunk.Prev /= null and then Chunk.First = Stack.Top then
  170.                To_Be_Released_Chunk := Chunk;
  171.                Chunk := Chunk.Prev;
  172.                Chunk.Next := To_Be_Released_Chunk.Next;
  173.                To_Be_Released_Chunk.Next.Prev := Chunk;
  174.                Free (To_Be_Released_Chunk);
  175.             end if;
  176.  
  177.          --  Create new chunk of the default size unless it is not sufficient
  178.  
  179.          elsif SSE.Storage_Count (Max_Size) <= Stack.Default_Size then
  180.             Chunk.Next := new Chunk_Id (
  181.               First => Chunk.Last + 1,
  182.               Last  => Chunk.Last + Mark_Id (Stack.Default_Size));
  183.  
  184.             Chunk.Next.Prev := Chunk;
  185.  
  186.          else
  187.             Chunk.Next := new Chunk_Id (
  188.               First => Chunk.Last + 1,
  189.               Last  => Chunk.Last + Max_Size);
  190.  
  191.             Chunk.Next.Prev := Chunk;
  192.          end if;
  193.  
  194.          Chunk     := Chunk.Next;
  195.          Stack.Top := Chunk.First;
  196.       end loop;
  197.  
  198.       --  Resulting address is the address pointed by Stack.Top
  199.  
  200.       Address      := Chunk.Mem (Stack.Top)'Address;
  201.       Stack.Top    := Stack.Top + Mark_Id (Max_Size);
  202.       Stack.Current_Chunk := Chunk;
  203.    end SS_Allocate;
  204.  
  205.    -------------
  206.    -- SS_Init --
  207.    -------------
  208.  
  209.    procedure SS_Init
  210.      (Stk  : in out System.Address;
  211.       Size : Natural := Default_Secondary_Stack_Size)
  212.    is
  213.       Stack : Stack_Ptr;
  214.       Fixed_Stack : Fixed_Stack_Ptr;
  215.  
  216.    begin
  217.       if not SS_Ratio_Dynamic then
  218.          Fixed_Stack      := To_Fixed (From_Addr (Stk));
  219.          Fixed_Stack.Top  := Fixed_Stack.Mem'First;
  220.  
  221.          if Size < 2 * Mark_Id'Max_Size_In_Storage_Elements then
  222.             Fixed_Stack.Last := 0;
  223.          else
  224.             Fixed_Stack.Last := Mark_Id (Size) -
  225.               2 * Mark_Id'Max_Size_In_Storage_Elements;
  226.          end if;
  227.  
  228.          return;
  229.       end if;
  230.  
  231.       Stack               := new Stack_Id;
  232.       Stack.Current_Chunk := new Chunk_Id (1, Mark_Id (Size));
  233.       Stack.Top           := 1;
  234.       Stack.Default_Size  := SSE.Storage_Count (Size);
  235.  
  236.       Stk := To_Addr (Stack);
  237.    end SS_Init;
  238.  
  239.    -------------
  240.    -- SS_Free --
  241.    -------------
  242.  
  243.    procedure SS_Free (Stk : in out System.Address) is
  244.       Stack : Stack_Ptr;
  245.       Chunk : Chunk_Ptr;
  246.  
  247.       procedure Free is new Unchecked_Deallocation (Stack_Id, Stack_Ptr);
  248.  
  249.    begin
  250.       if not SS_Ratio_Dynamic then
  251.          return;
  252.       end if;
  253.  
  254.       Stack := From_Addr (Stk);
  255.       Chunk := Stack.Current_Chunk;
  256.  
  257.       while Chunk.Prev /= null loop
  258.          Chunk := Chunk.Prev;
  259.       end loop;
  260.  
  261.       while Chunk.Next /= null loop
  262.          Chunk := Chunk.Next;
  263.          Free (Chunk.Prev);
  264.       end loop;
  265.  
  266.       Free (Chunk);
  267.       Free (Stack);
  268.       Stk := Null_Address;
  269.    end SS_Free;
  270.  
  271.    -------------
  272.    -- SS_Mark --
  273.    -------------
  274.  
  275.    function SS_Mark return Mark_Id is
  276.    begin
  277.       return From_Addr (SSL.Get_Sec_Stack_Addr.all).Top;
  278.    end SS_Mark;
  279.  
  280.    ----------------
  281.    -- SS_Release --
  282.    ----------------
  283.  
  284.    procedure SS_Release (M : Mark_Id) is
  285.    begin
  286.       From_Addr (SSL.Get_Sec_Stack_Addr.all).Top := M;
  287.    end SS_Release;
  288.  
  289.    -------------
  290.    -- SS_Info --
  291.    -------------
  292.  
  293.    procedure SS_Info is
  294.       Stack       : constant Stack_Ptr :=
  295.                       From_Addr (SSL.Get_Sec_Stack_Addr.all);
  296.       Fixed_Stack : Fixed_Stack_Ptr;
  297.       Nb_Chunks   : Integer            := 1;
  298.       Chunk       : Chunk_Ptr          := Stack.Current_Chunk;
  299.  
  300.    begin
  301.       Put_Line ("Secondary Stack information:");
  302.  
  303.       if not SS_Ratio_Dynamic then
  304.          Fixed_Stack := To_Fixed (Stack);
  305.          Put_Line (
  306.            "  Total size              : "
  307.            & Mark_Id'Image (Fixed_Stack.Last)
  308.            & " bytes");
  309.          Put_Line (
  310.            "  Current allocated space : "
  311.            & Mark_Id'Image (Fixed_Stack.Top - 1)
  312.            & " bytes");
  313.          return;
  314.       end if;
  315.  
  316.       while Chunk.Prev /= null loop
  317.          Chunk := Chunk.Prev;
  318.       end loop;
  319.  
  320.       while Chunk.Next /= null loop
  321.          Nb_Chunks := Nb_Chunks + 1;
  322.          Chunk := Chunk.Next;
  323.       end loop;
  324.  
  325.       --  Current Chunk information
  326.  
  327.       Put_Line (
  328.         "  Total size              : "
  329.         & Mark_Id'Image (Chunk.Last)
  330.         & " bytes");
  331.       Put_Line (
  332.         "  Current allocated space : "
  333.         & Mark_Id'Image (Stack.Top - 1)
  334.         & " bytes");
  335.  
  336.       Put_Line (
  337.         "  Number of Chunks       : "
  338.         & Integer'Image (Nb_Chunks));
  339.  
  340.       Put_Line (
  341.         "  Default size of Chunks : "
  342.         & SSE.Storage_Count'Image (Stack.Default_Size));
  343.    end SS_Info;
  344.  
  345.    --  Allocate a secondary stack for the main program to use.
  346.    --  We make sure that the stack has maximum alignment. Some systems require
  347.    --  this (e.g. Sun), and in any case it is a good idea for efficiency.
  348.  
  349.    Stack : aliased Stack_Id;
  350.    for Stack'Alignment use Standard'Maximum_Alignment;
  351.  
  352.    Chunk : aliased Chunk_Id (1, Default_Secondary_Stack_Size);
  353.    for Chunk'Alignment use Standard'Maximum_Alignment;
  354.  
  355.    Chunk_Address : System.Address;
  356.  
  357. begin
  358.    if SS_Ratio_Dynamic then
  359.       Stack.Top           := 1;
  360.       Stack.Current_Chunk := Chunk'Access;
  361.       Stack.Default_Size  := Default_Secondary_Stack_Size;
  362.       System.Soft_Links.Set_Sec_Stack_Addr_NT (Stack'Address);
  363.  
  364.    else
  365.       Chunk_Address := Chunk'Address;
  366.       SS_Init (Chunk_Address, Default_Secondary_Stack_Size);
  367.       System.Soft_Links.Set_Sec_Stack_Addr_NT (Chunk_Address);
  368.    end if;
  369. end System.Secondary_Stack;
  370.