[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Tue, 15 May 2012 09:29:46 +0000 (11:29 +0200)
committerArnaud Charlet <charlet@gcc.gnu.org>
Tue, 15 May 2012 09:29:46 +0000 (11:29 +0200)
2012-05-15  Robert Dewar  <dewar@adacore.com>

* g-comlin.adb, g-comlin.ads: Minor reformatting.

2012-05-15  Vincent Pucci  <pucci@adacore.com>

* aspects.adb, aspects.adb: Reordering of the Aspect_Idi list. New
aspect Aspect_Lock_Free.
* einfo.adb, einfo.ads: New flag Uses_Lock_Free (flag 188).
(Set_Uses_Lock_Free): New routine.
(Uses_Lock_Free): New routine.
* exp_ch7.adb (Is_Simple_Protected_Type): Return False for
lock-free implementation.
* exp_ch9.adb (Allows_Lock_Free_Implementation): Moved to Sem_Ch9.
(Build_Lock_Free_Unprotected_Subprogram_Body): Protected
procedure uses __sync_synchronise. Check both Object_Size
and Value_Size.
(Expand_N_Protected_Body): Lock_Free_Active
renames Lock_Free_On.
(Expand_N_Protected_Type_Declaration):
_Object field removed for lock-free implementation.
(Install_Private_Data_Declarations): Protection object removed
for lock-free implementation.
(Make_Initialize_Protection):
Protection object initialization removed for lock-free implementation.
* rtsfind.ads: RE_Atomic_Synchronize and RE_Relaxed added.
* sem_ch13.adb (Analyze_Aspect_Specifications): Aspect_Lock_Free
analysis added.
* sem_ch9.adb (Allows_Lock_Free_Implementation): New routine.
(Analyze_Protected_Body): Allows_Lock_Free_Implementation call added.
(Analyze_Protected_Type_Declaration):
Allows_Lock_Free_Implementation call added.
(Analyze_Single_Protected_Declaration): Second analysis of
aspects removed.
* s-atopri.ads: Header added.
(Atomic_Synchronize): New routine.

2012-05-15  Robert Dewar  <dewar@adacore.com>

* exp_ch7.ads: Add comment.

From-SVN: r187505

16 files changed:
gcc/ada/ChangeLog
gcc/ada/aspects.adb
gcc/ada/aspects.ads
gcc/ada/einfo.adb
gcc/ada/einfo.ads
gcc/ada/exp_ch7.adb
gcc/ada/exp_ch7.ads
gcc/ada/exp_ch9.adb
gcc/ada/g-comlin.adb
gcc/ada/g-comlin.ads
gcc/ada/rtsfind.ads
gcc/ada/s-atopri.ads
gcc/ada/sem_ch13.adb
gcc/ada/sem_ch9.adb
gcc/ada/sem_ch9.ads
gcc/ada/snames.ads-tmpl

index e1c40a9..9f31c75 100644 (file)
@@ -1,3 +1,44 @@
+2012-05-15  Robert Dewar  <dewar@adacore.com>
+
+       * g-comlin.adb, g-comlin.ads: Minor reformatting.
+
+2012-05-15  Vincent Pucci  <pucci@adacore.com>
+
+       * aspects.adb, aspects.adb: Reordering of the Aspect_Idi list. New
+       aspect Aspect_Lock_Free.
+       * einfo.adb, einfo.ads: New flag Uses_Lock_Free (flag 188).
+       (Set_Uses_Lock_Free): New routine.
+       (Uses_Lock_Free): New routine.
+       * exp_ch7.adb (Is_Simple_Protected_Type): Return False for
+       lock-free implementation.
+       * exp_ch9.adb (Allows_Lock_Free_Implementation): Moved to Sem_Ch9.
+       (Build_Lock_Free_Unprotected_Subprogram_Body): Protected
+       procedure uses __sync_synchronise. Check both Object_Size
+       and Value_Size.
+       (Expand_N_Protected_Body): Lock_Free_Active
+       renames Lock_Free_On.
+       (Expand_N_Protected_Type_Declaration):
+       _Object field removed for lock-free implementation.
+       (Install_Private_Data_Declarations): Protection object removed
+       for lock-free implementation.
+       (Make_Initialize_Protection):
+       Protection object initialization removed for lock-free implementation.
+       * rtsfind.ads: RE_Atomic_Synchronize and RE_Relaxed added.
+       * sem_ch13.adb (Analyze_Aspect_Specifications): Aspect_Lock_Free
+       analysis added.
+       * sem_ch9.adb (Allows_Lock_Free_Implementation): New routine.
+       (Analyze_Protected_Body): Allows_Lock_Free_Implementation call added.
+       (Analyze_Protected_Type_Declaration):
+       Allows_Lock_Free_Implementation call added.
+       (Analyze_Single_Protected_Declaration): Second analysis of
+       aspects removed.
+       * s-atopri.ads: Header added.
+       (Atomic_Synchronize): New routine.
+
+2012-05-15  Robert Dewar  <dewar@adacore.com>
+
+       * exp_ch7.ads: Add comment.
+
 2012-05-15  Hristian Kirtchev  <kirtchev@adacore.com>
 
        * a-calend.adb (Day_Of_Week): The routine once again treats
index b155a08..86e7091 100644 (file)
@@ -242,11 +242,13 @@ package body Aspects is
     Aspect_Ada_2012                     => Aspect_Ada_2005,
     Aspect_Address                      => Aspect_Address,
     Aspect_Alignment                    => Aspect_Alignment,
+    Aspect_All_Calls_Remote             => Aspect_All_Calls_Remote,
     Aspect_Asynchronous                 => Aspect_Asynchronous,
     Aspect_Atomic                       => Aspect_Atomic,
     Aspect_Atomic_Components            => Aspect_Atomic_Components,
     Aspect_Attach_Handler               => Aspect_Attach_Handler,
     Aspect_Bit_Order                    => Aspect_Bit_Order,
+    Aspect_Compiler_Unit                => Aspect_Compiler_Unit,
     Aspect_Component_Size               => Aspect_Component_Size,
     Aspect_Constant_Indexing            => Aspect_Constant_Indexing,
     Aspect_Contract_Case                => Aspect_Contract_Case,
@@ -259,6 +261,7 @@ package body Aspects is
     Aspect_Discard_Names                => Aspect_Discard_Names,
     Aspect_Dispatching_Domain           => Aspect_Dispatching_Domain,
     Aspect_Dynamic_Predicate            => Aspect_Predicate,
+    Aspect_Elaborate_Body               => Aspect_Elaborate_Body,
     Aspect_External_Tag                 => Aspect_External_Tag,
     Aspect_Favor_Top_Level              => Aspect_Favor_Top_Level,
     Aspect_Implicit_Dereference         => Aspect_Implicit_Dereference,
@@ -266,24 +269,12 @@ package body Aspects is
     Aspect_Independent_Components       => Aspect_Independent_Components,
     Aspect_Inline                       => Aspect_Inline,
     Aspect_Inline_Always                => Aspect_Inline,
+    Aspect_Input                        => Aspect_Input,
     Aspect_Interrupt_Handler            => Aspect_Interrupt_Handler,
     Aspect_Interrupt_Priority           => Aspect_Interrupt_Priority,
-    Aspect_Iterator_Element             => Aspect_Iterator_Element,
-    Aspect_All_Calls_Remote             => Aspect_All_Calls_Remote,
-    Aspect_Compiler_Unit                => Aspect_Compiler_Unit,
-    Aspect_Elaborate_Body               => Aspect_Elaborate_Body,
-    Aspect_Preelaborate                 => Aspect_Preelaborate,
-    Aspect_Preelaborate_05              => Aspect_Preelaborate_05,
-    Aspect_Pure                         => Aspect_Pure,
-    Aspect_Pure_05                      => Aspect_Pure_05,
-    Aspect_Pure_12                      => Aspect_Pure_12,
-    Aspect_Remote_Call_Interface        => Aspect_Remote_Call_Interface,
-    Aspect_Remote_Types                 => Aspect_Remote_Types,
-    Aspect_Scalar_Storage_Order         => Aspect_Scalar_Storage_Order,
-    Aspect_Shared_Passive               => Aspect_Shared_Passive,
-    Aspect_Universal_Data               => Aspect_Universal_Data,
-    Aspect_Input                        => Aspect_Input,
     Aspect_Invariant                    => Aspect_Invariant,
+    Aspect_Iterator_Element             => Aspect_Iterator_Element,
+    Aspect_Lock_Free                    => Aspect_Lock_Free,
     Aspect_Machine_Radix                => Aspect_Machine_Radix,
     Aspect_No_Return                    => Aspect_No_Return,
     Aspect_Object_Size                  => Aspect_Object_Size,
@@ -295,12 +286,21 @@ package body Aspects is
     Aspect_Pre                          => Aspect_Pre,
     Aspect_Precondition                 => Aspect_Pre,
     Aspect_Predicate                    => Aspect_Predicate,
+    Aspect_Preelaborate                 => Aspect_Preelaborate,
+    Aspect_Preelaborate_05              => Aspect_Preelaborate_05,
     Aspect_Preelaborable_Initialization => Aspect_Preelaborable_Initialization,
     Aspect_Priority                     => Aspect_Priority,
+    Aspect_Pure                         => Aspect_Pure,
+    Aspect_Pure_05                      => Aspect_Pure_05,
+    Aspect_Pure_12                      => Aspect_Pure_12,
     Aspect_Pure_Function                => Aspect_Pure_Function,
     Aspect_Remote_Access_Type           => Aspect_Remote_Access_Type,
+    Aspect_Remote_Call_Interface        => Aspect_Remote_Call_Interface,
+    Aspect_Remote_Types                 => Aspect_Remote_Types,
     Aspect_Read                         => Aspect_Read,
+    Aspect_Scalar_Storage_Order         => Aspect_Scalar_Storage_Order,
     Aspect_Shared                       => Aspect_Atomic,
+    Aspect_Shared_Passive               => Aspect_Shared_Passive,
     Aspect_Simple_Storage_Pool          => Aspect_Simple_Storage_Pool,
     Aspect_Simple_Storage_Pool_Type     => Aspect_Simple_Storage_Pool_Type,
     Aspect_Size                         => Aspect_Size,
@@ -316,6 +316,7 @@ package body Aspects is
     Aspect_Type_Invariant               => Aspect_Invariant,
     Aspect_Unchecked_Union              => Aspect_Unchecked_Union,
     Aspect_Universal_Aliasing           => Aspect_Universal_Aliasing,
+    Aspect_Universal_Data               => Aspect_Universal_Data,
     Aspect_Unmodified                   => Aspect_Unmodified,
     Aspect_Unreferenced                 => Aspect_Unreferenced,
     Aspect_Unreferenced_Objects         => Aspect_Unreferenced_Objects,
index 781651f..523412b 100644 (file)
@@ -142,7 +142,12 @@ package Aspects is
       Aspect_Unreferenced,                  -- GNAT
       Aspect_Unreferenced_Objects,          -- GNAT
       Aspect_Volatile,
-      Aspect_Volatile_Components);
+      Aspect_Volatile_Components,
+
+      --  Aspects that have a static boolean value but don't correspond to
+      --  pragmas
+
+      Aspect_Lock_Free);
 
    --  The following array indicates aspects that accept 'Class
 
@@ -182,6 +187,7 @@ package Aspects is
                              Aspect_Dimension_System         => True,
                              Aspect_Favor_Top_Level          => True,
                              Aspect_Inline_Always            => True,
+                             Aspect_Lock_Free                => True,
                              Aspect_Object_Size              => True,
                              Aspect_Persistent_BSS           => True,
                              Aspect_Predicate                => True,
@@ -352,6 +358,7 @@ package Aspects is
      Aspect_Interrupt_Priority           => Name_Interrupt_Priority,
      Aspect_Invariant                    => Name_Invariant,
      Aspect_Iterator_Element             => Name_Iterator_Element,
+     Aspect_Lock_Free                    => Name_Lock_Free,
      Aspect_Machine_Radix                => Name_Machine_Radix,
      Aspect_No_Return                    => Name_No_Return,
      Aspect_Object_Size                  => Name_Object_Size,
index 0f597a1..b7ffe58 100644 (file)
@@ -452,6 +452,7 @@ package body Einfo is
    --    Is_Ada_2005_Only                Flag185
    --    Is_Interface                    Flag186
    --    Has_Constrained_Partial_View    Flag187
+   --    Uses_Lock_Free                  Flag188
    --    Is_Pure_Unit_Access_Type        Flag189
    --    Has_Specified_Stream_Input      Flag190
 
@@ -525,7 +526,6 @@ package body Einfo is
    --    Has_Anonymous_Master            Flag253
    --    Is_Implementation_Defined       Flag254
 
-   --    (unused)                        Flag188
    --    (unused)                        Flag201
 
    -----------------------
@@ -2794,6 +2794,12 @@ package body Einfo is
       return Flag222 (Id);
    end Used_As_Generic_Actual;
 
+   function Uses_Lock_Free (Id : E) return B is
+   begin
+      pragma Assert (Is_Protected_Type (Id));
+      return Flag188 (Id);
+   end Uses_Lock_Free;
+
    function Uses_Sec_Stack (Id : E) return B is
    begin
       return Flag95 (Id);
@@ -5358,16 +5364,22 @@ package body Einfo is
       Set_Node16 (Id, V);
    end Set_Unset_Reference;
 
-   procedure Set_Uses_Sec_Stack (Id : E; V : B := True) is
-   begin
-      Set_Flag95 (Id, V);
-   end Set_Uses_Sec_Stack;
-
    procedure Set_Used_As_Generic_Actual (Id : E; V : B := True) is
    begin
       Set_Flag222 (Id, V);
    end Set_Used_As_Generic_Actual;
 
+   procedure Set_Uses_Lock_Free (Id : E; V : B := True) is
+   begin
+      pragma Assert (Ekind (Id) = E_Protected_Type);
+      Set_Flag188 (Id, V);
+   end Set_Uses_Lock_Free;
+
+   procedure Set_Uses_Sec_Stack (Id : E; V : B := True) is
+   begin
+      Set_Flag95 (Id, V);
+   end Set_Uses_Sec_Stack;
+
    procedure Set_Warnings_Off (Id : E; V : B := True) is
    begin
       Set_Flag96 (Id, V);
index d07be81..01037a5 100644 (file)
@@ -3878,6 +3878,12 @@ package Einfo is
 --       Present in all entities, set if the entity is used as an argument to
 --       a generic instantiation. Used to tune certain warning messages.
 
+--    Uses_Lock_Free (Flag188)
+--       Present in protected type entities. Set to True when the Lock Free
+--       implementation is used for the protected type. This implemenatation is
+--       based on atomic transactions and doesn't require anymore the use of
+--       Protection object (see System.Tasking.Protected_Objects).
+
 --    Uses_Sec_Stack (Flag95)
 --       Present in scope entities (blocks,functions, procedures, tasks,
 --       entries). Set to True when secondary stack is used in this scope and
@@ -5601,6 +5607,7 @@ package Einfo is
    --    Stored_Constraint                   (Elist23)
    --    Has_Interrupt_Handler               (synth)
    --    Sec_Stack_Needed_For_Return         (Flag167)  ???
+   --    Uses_Lock_Free                      (Flag188)
    --    Uses_Sec_Stack                      (Flag95)   ???
    --    Has_Entries                         (synth)
    --    Number_Entries                      (synth)
@@ -6405,6 +6412,7 @@ package Einfo is
    function Universal_Aliasing                  (Id : E) return B;
    function Unset_Reference                     (Id : E) return N;
    function Used_As_Generic_Actual              (Id : E) return B;
+   function Uses_Lock_Free                      (Id : E) return B;
    function Uses_Sec_Stack                      (Id : E) return B;
    function Vax_Float                           (Id : E) return B;
    function Warnings_Off                        (Id : E) return B;
@@ -7001,6 +7009,7 @@ package Einfo is
    procedure Set_Universal_Aliasing              (Id : E; V : B := True);
    procedure Set_Unset_Reference                 (Id : E; V : N);
    procedure Set_Used_As_Generic_Actual          (Id : E; V : B := True);
+   procedure Set_Uses_Lock_Free                  (Id : E; V : B := True);
    procedure Set_Uses_Sec_Stack                  (Id : E; V : B := True);
    procedure Set_Warnings_Off                    (Id : E; V : B := True);
    procedure Set_Warnings_Off_Used               (Id : E; V : B := True);
@@ -7746,6 +7755,7 @@ package Einfo is
    pragma Inline (Universal_Aliasing);
    pragma Inline (Unset_Reference);
    pragma Inline (Used_As_Generic_Actual);
+   pragma Inline (Uses_Lock_Free);
    pragma Inline (Uses_Sec_Stack);
    pragma Inline (Warnings_Off);
    pragma Inline (Warnings_Off_Used);
@@ -8148,6 +8158,7 @@ package Einfo is
    pragma Inline (Set_Universal_Aliasing);
    pragma Inline (Set_Unset_Reference);
    pragma Inline (Set_Used_As_Generic_Actual);
+   pragma Inline (Set_Uses_Lock_Free);
    pragma Inline (Set_Uses_Sec_Stack);
    pragma Inline (Set_Warnings_Off);
    pragma Inline (Set_Warnings_Off_Used);
index dfd0a06..238469c 100644 (file)
@@ -4602,6 +4602,7 @@ package body Exp_Ch7 is
    begin
       return
         Is_Protected_Type (T)
+          and then not Uses_Lock_Free (T)
           and then not Has_Entries (T)
           and then Is_RTE (Find_Protection_Type (T), RE_Protection);
    end Is_Simple_Protected_Type;
index 8ea7191..244936c 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT 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- --
@@ -272,6 +272,8 @@ package Exp_Ch7 is
    function Is_Simple_Protected_Type (T : Entity_Id) return Boolean;
    --  Determine whether T denotes a protected type without entires whose
    --  _object field is of type System.Tasking.Protected_Objects.Protection.
+   --  Something wrong here, implementation was changed to test Lock_Free
+   --  but this spec does not mention that ???
 
    --------------------------------
    -- Transient Scope Management --
index 9d21af2..1f9f458 100644 (file)
@@ -25,7 +25,6 @@
 
 with Atree;    use Atree;
 with Checks;   use Checks;
-with Debug;    use Debug;
 with Einfo;    use Einfo;
 with Elists;   use Elists;
 with Errout;   use Errout;
@@ -52,6 +51,7 @@ with Sem;      use Sem;
 with Sem_Aux;  use Sem_Aux;
 with Sem_Ch6;  use Sem_Ch6;
 with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch9;  use Sem_Ch9;
 with Sem_Ch11; use Sem_Ch11;
 with Sem_Elab; use Sem_Elab;
 with Sem_Eval; use Sem_Eval;
@@ -61,7 +61,6 @@ with Sinfo;    use Sinfo;
 with Snames;   use Snames;
 with Stand;    use Stand;
 with Stringt;  use Stringt;
-with Table;
 with Targparm; use Targparm;
 with Tbuild;   use Tbuild;
 with Uintp;    use Uintp;
@@ -77,37 +76,6 @@ package body Exp_Ch9 is
 
    Entry_Family_Bound : constant Int := 2**16;
 
-   ------------------------------
-   -- Lock Free Data Structure --
-   ------------------------------
-
-   --  A lock-free subprogram is a protected routine which references a unique
-   --  protected scalar component and does not contain statements that cause
-   --  side effects. Due to this restricted behavior, all references to shared
-   --  data from within the subprogram can be synchronized through the use of
-   --  atomic operations rather than relying on locks.
-
-   type Lock_Free_Subprogram is record
-      Sub_Body : Node_Id;
-      --  Reference to the body of a protected subprogram which meets the lock-
-      --  free requirements.
-
-      Comp_Id : Entity_Id;
-      --  Reference to the scalar component referenced from within Sub_Body
-   end record;
-
-   --  This table establishes a relation between a protected subprogram body
-   --  and a unique component it references. The table is used when building
-   --  the lock-free versions of a protected subprogram body.
-
-   package Lock_Free_Subprogram_Table is new Table.Table (
-     Table_Component_Type => Lock_Free_Subprogram,
-     Table_Index_Type     => Nat,
-     Table_Low_Bound      => 1,
-     Table_Initial        => 5,
-     Table_Increment      => 5,
-     Table_Name           => "Lock_Free_Subprogram_Table");
-
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -142,20 +110,6 @@ package body Exp_Ch9 is
    --    Decls is the list of declarations to be enhanced.
    --    Ent is the entity for the original entry body.
 
-   function Allows_Lock_Free_Implementation (N : Node_Id) return Boolean;
-   --  Given a protected body N, return True if N satisfies the following list
-   --  of lock-free restrictions:
-   --
-   --    1) Protected type
-   --         May not contain entries
-   --         May contain only scalar components
-   --         Component types must support atomic compare and exchange
-   --
-   --    2) Protected subprograms
-   --         May not have side effects
-   --         May not contain loop statements or procedure calls
-   --         Function calls and attribute references must be static
-
    function Build_Accept_Body (Astat : Node_Id) return Node_Id;
    --  Transform accept statement into a block with added exception handler.
    --  Used both for simple accept statements and for accept alternatives in
@@ -828,220 +782,6 @@ package body Exp_Ch9 is
       Prepend_To (Decls, Decl);
    end Add_Object_Pointer;
 
-   -------------------------------------
-   -- Allows_Lock_Free_Implementation --
-   -------------------------------------
-
-   function Allows_Lock_Free_Implementation (N : Node_Id) return Boolean is
-      Spec       : constant Entity_Id := Corresponding_Spec (N);
-      Prot_Def   : constant Node_Id   := Protected_Definition (Parent (Spec));
-      Priv_Decls : constant List_Id   := Private_Declarations (Prot_Def);
-
-      function Satisfies_Lock_Free_Requirements
-        (Sub_Body : Node_Id) return Boolean;
-      --  Return True if protected subprogram body Sub_Body satisfies all
-      --  requirements of a lock-free implementation.
-
-      --------------------------------------
-      -- Satisfies_Lock_Free_Requirements --
-      --------------------------------------
-
-      function Satisfies_Lock_Free_Requirements
-        (Sub_Body : Node_Id) return Boolean
-      is
-         Comp : Entity_Id := Empty;
-         --  Track the current component which the body references
-
-         function Check_Node (N : Node_Id) return Traverse_Result;
-         --  Check that node N meets the lock free restrictions
-
-         ----------------
-         -- Check_Node --
-         ----------------
-
-         function Check_Node (N : Node_Id) return Traverse_Result is
-         begin
-            --  Function calls and attribute references must be static
-            --  ??? what about side-effects
-
-            if Nkind_In (N, N_Attribute_Reference, N_Function_Call)
-              and then not Is_Static_Expression (N)
-            then
-               return Abandon;
-
-            --  Loop statements and procedure calls are prohibited
-
-            elsif Nkind_In (N, N_Loop_Statement,
-                               N_Procedure_Call_Statement)
-            then
-               return Abandon;
-
-            --  References
-
-            elsif Nkind (N) = N_Identifier
-              and then Present (Entity (N))
-            then
-               declare
-                  Id     : constant Entity_Id := Entity (N);
-                  Sub_Id : constant Entity_Id := Corresponding_Spec (Sub_Body);
-
-               begin
-                  --  Prohibit references to non-constant entities outside the
-                  --  protected subprogram scope.
-
-                  if Ekind (Id) in Assignable_Kind
-                    and then not Scope_Within_Or_Same (Scope (Id), Sub_Id)
-                    and then not Scope_Within_Or_Same (Scope (Id),
-                                   Protected_Body_Subprogram (Sub_Id))
-                  then
-                     return Abandon;
-
-                  --  A protected subprogram may reference only one component
-                  --  of the protected type.
-
-                  elsif Ekind_In (Id, E_Constant, E_Variable)
-                    and then Present (Prival_Link (Id))
-                  then
-                     declare
-                        Comp_Decl : constant Node_Id :=
-                                      Parent (Prival_Link (Id));
-                     begin
-                        if Nkind (Comp_Decl) = N_Component_Declaration
-                          and then Is_List_Member (Comp_Decl)
-                          and then List_Containing (Comp_Decl) = Priv_Decls
-                        then
-                           if No (Comp) then
-                              Comp := Prival_Link (Id);
-
-                           --  Check if another protected component has already
-                           --  been accessed by the subprogram body.
-
-                           elsif Comp /= Prival_Link (Id) then
-                              return Abandon;
-                           end if;
-                        end if;
-                     end;
-                  end if;
-               end;
-            end if;
-
-            return OK;
-         end Check_Node;
-
-         function Check_All_Nodes is new Traverse_Func (Check_Node);
-
-      --  Start of processing for Satisfies_Lock_Free_Requirements
-
-      begin
-         if Check_All_Nodes (Sub_Body) = OK then
-
-            --  Establish a relation between the subprogram body and the unique
-            --  protected component it references.
-
-            if Present (Comp) then
-               Lock_Free_Subprogram_Table.Append
-                 (Lock_Free_Subprogram'(Sub_Body, Comp));
-            end if;
-
-            return True;
-         else
-            return False;
-         end if;
-      end Satisfies_Lock_Free_Requirements;
-
-      --  Local variables
-
-      Decls     : constant List_Id   := Declarations (N);
-      Vis_Decls : constant List_Id   := Visible_Declarations (Prot_Def);
-
-      Comp_Id       : Entity_Id;
-      Comp_Size     : Int;
-      Comp_Type     : Entity_Id;
-      Decl          : Node_Id;
-      Has_Component : Boolean := False;
-
-   --  Start of processing for Allows_Lock_Free_Implementation
-
-   begin
-      --  The lock-free implementation is currently enabled through a debug
-      --  flag.
-
-      if not Debug_Flag_9 then
-         return False;
-      end if;
-
-      --  Examine the visible declarations. Entries and entry families are not
-      --  allowed by the lock-free restrictions.
-
-      Decl := First (Vis_Decls);
-      while Present (Decl) loop
-         if Nkind (Decl) = N_Entry_Declaration then
-            return False;
-         end if;
-
-         Next (Decl);
-      end loop;
-
-      --  Examine the private declarations
-
-      Decl := First (Priv_Decls);
-      while Present (Decl) loop
-
-         --  The protected type must define at least one scalar component
-
-         if Nkind (Decl) = N_Component_Declaration then
-            Has_Component := True;
-
-            Comp_Id   := Defining_Identifier (Decl);
-            Comp_Type := Etype (Comp_Id);
-
-            if not Is_Scalar_Type (Comp_Type) then
-               return False;
-            end if;
-
-            Comp_Size := UI_To_Int (Esize (Base_Type (Comp_Type)));
-
-            --  Check that the size of the component is 8, 16, 32 or 64 bits
-
-            case Comp_Size is
-               when 8 | 16 | 32 | 64 =>
-                  null;
-               when others           =>
-                  return False;
-            end case;
-
-         --  Entries and entry families are not allowed
-
-         elsif Nkind (Decl) = N_Entry_Declaration then
-            return False;
-         end if;
-
-         Next (Decl);
-      end loop;
-
-      --  At least one scalar component must be present
-
-      if not Has_Component then
-         return False;
-      end if;
-
-      --  Ensure that all protected subprograms meet the restrictions of the
-      --  lock-free implementation.
-
-      Decl := First (Decls);
-      while Present (Decl) loop
-         if Nkind (Decl) = N_Subprogram_Body
-           and then not Satisfies_Lock_Free_Requirements (Decl)
-         then
-            return False;
-         end if;
-
-         Next (Decl);
-      end loop;
-
-      return True;
-   end Allows_Lock_Free_Implementation;
-
    -----------------------
    -- Build_Accept_Body --
    -----------------------
@@ -3228,7 +2968,8 @@ package body Exp_Ch9 is
    --    begin
    --       loop
    --          declare
-   --             Saved_Comp   : constant ... := Atomic_Load (Comp'Address);
+   --             Saved_Comp   : constant ... :=
+   --                              Atomic_Load (Comp'Address, Relaxed);
    --             Current_Comp : ... := Saved_Comp;
    --          begin
    --             <original statements>
@@ -3496,19 +3237,33 @@ package body Exp_Ch9 is
 
       if Present (Comp) then
          declare
-            Comp_Typ     : constant Entity_Id := Etype (Comp);
-            Typ_Size     : constant Int       := UI_To_Int (Esize (Comp_Typ));
+            Comp_Type    : constant Entity_Id := Etype (Comp);
             Block_Decls  : List_Id;
             Compare      : Entity_Id;
             Current_Comp : Entity_Id;
             Decl         : Node_Id;
             Label        : Node_Id;
             Load         : Entity_Id;
+            Load_Params  : List_Id;
             Saved_Comp   : Entity_Id;
             Stmt         : Node_Id;
+            Typ_Size     : Int;
             Unsigned     : Entity_Id;
 
          begin
+            --  Get the type size
+
+            if Known_Esize (Comp_Type) then
+               Typ_Size := UI_To_Int (Esize (Comp_Type));
+
+            --  If the Esize (Object_Size) is unknown at compile-time, look at
+            --  the RM_Size (Value_Size) since it may have been set by an
+            --  explicit representation clause.
+
+            else
+               Typ_Size := UI_To_Int (RM_Size (Comp_Type));
+            end if;
+
             --  Retrieve all relevant atomic routines and types
 
             case Typ_Size is
@@ -3537,26 +3292,43 @@ package body Exp_Ch9 is
             end case;
 
             --  Generate:
-            --    Saved_Comp : constant Comp_Typ :=
-            --                   Comp_Typ (Atomic_Load (Comp'Address));
+            --    For functions:
+
+            --       Saved_Comp : constant Comp_Type :=
+            --                      Comp_Type (Atomic_Load (Comp'Address));
+
+            --    For procedures:
+
+            --       Saved_Comp : constant Comp_Type :=
+            --                      Comp_Type (Atomic_Load (Comp'Address),
+            --                                             Relaxed);
 
             Saved_Comp :=
               Make_Defining_Identifier (Loc,
                 New_External_Name (Chars (Comp), Suffix => "_saved"));
 
+            Load_Params := New_List (
+              Make_Attribute_Reference (Loc,
+                Prefix         => New_Reference_To (Comp, Loc),
+                Attribute_Name => Name_Address));
+
+            --  For protected procedures, set the memory model to be relaxed
+
+            if Is_Procedure then
+               Append_To (Load_Params,
+                 New_Reference_To (RTE (RE_Relaxed), Loc));
+            end if;
+
             Decl :=
               Make_Object_Declaration (Loc,
                 Defining_Identifier => Saved_Comp,
                 Constant_Present    => True,
-                Object_Definition   => New_Reference_To (Comp_Typ, Loc),
+                Object_Definition   => New_Reference_To (Comp_Type, Loc),
                 Expression          =>
-                  Unchecked_Convert_To (Comp_Typ,
+                  Unchecked_Convert_To (Comp_Type,
                     Make_Function_Call (Loc,
                       Name                   => New_Reference_To (Load, Loc),
-                      Parameter_Associations => New_List (
-                        Make_Attribute_Reference (Loc,
-                          Prefix         => New_Reference_To (Comp, Loc),
-                          Attribute_Name => Name_Address)))));
+                      Parameter_Associations => Load_Params)));
 
             --  Protected procedures
 
@@ -3564,7 +3336,7 @@ package body Exp_Ch9 is
                Block_Decls := New_List (Decl);
 
                --  Generate:
-               --    Current_Comp : Comp_Typ := Saved_Comp;
+               --    Current_Comp : Comp_Type := Saved_Comp;
 
                Current_Comp :=
                  Make_Defining_Identifier (Loc,
@@ -3573,7 +3345,7 @@ package body Exp_Ch9 is
                Append_To (Block_Decls,
                  Make_Object_Declaration (Loc,
                    Defining_Identifier => Current_Comp,
-                   Object_Definition   => New_Reference_To (Comp_Typ, Loc),
+                   Object_Definition   => New_Reference_To (Comp_Type, Loc),
                    Expression          => New_Reference_To (Saved_Comp, Loc)));
 
             --  Protected function
@@ -3645,6 +3417,9 @@ package body Exp_Ch9 is
 
             if Is_Procedure then
                Stmts := New_List (
+                Make_Procedure_Call_Statement (Loc,
+                    Name =>
+                      New_Reference_To (RTE (RE_Atomic_Synchronize), Loc)),
                  Make_Loop_Statement (Loc,
                    Statements => New_List (
                      Make_Block_Statement (Loc,
@@ -8423,7 +8198,7 @@ package body Exp_Ch9 is
       Loc          : constant Source_Ptr := Sloc (N);
       Pid          : constant Entity_Id  := Corresponding_Spec (N);
 
-      Lock_Free_On : constant Boolean := Allows_Lock_Free_Implementation (N);
+      Lock_Free_Active : constant Boolean := Uses_Lock_Free (Pid);
       --  This flag indicates whether the lock free implementation is active
 
       Current_Node : Node_Id;
@@ -8554,7 +8329,7 @@ package body Exp_Ch9 is
                if not Is_Eliminated (Defining_Entity (Op_Body))
                  and then not Is_Eliminated (Corresponding_Spec (Op_Body))
                then
-                  if Lock_Free_On then
+                  if Lock_Free_Active then
                      New_Op_Body :=
                        Build_Lock_Free_Unprotected_Subprogram_Body
                          (Op_Body, Pid);
@@ -8581,7 +8356,7 @@ package body Exp_Ch9 is
                   --  declaration in the protected body itself.
 
                   if Present (Corresponding_Spec (Op_Body)) then
-                     if Lock_Free_On then
+                     if Lock_Free_Active then
                         New_Op_Body :=
                           Build_Lock_Free_Protected_Subprogram_Body
                             (Op_Body, Pid, Specification (New_Op_Body));
@@ -8765,10 +8540,13 @@ package body Exp_Ch9 is
    --  the specs refer to this type.
 
    procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
-      Loc      : constant Source_Ptr := Sloc (N);
-      Prot_Typ : constant Entity_Id  := Defining_Identifier (N);
+      Loc              : constant Source_Ptr := Sloc (N);
+      Prot_Typ         : constant Entity_Id  := Defining_Identifier (N);
+
+      Lock_Free_Active : constant Boolean := Uses_Lock_Free (Prot_Typ);
+      --  This flag indicates whether the lock free implementation is active
 
-      Pdef : constant Node_Id := Protected_Definition (N);
+      Pdef             : constant Node_Id := Protected_Definition (N);
       --  This contains two lists; one for visible and one for private decls
 
       Rec_Decl     : Node_Id;
@@ -8926,108 +8704,6 @@ package body Exp_Ch9 is
 
       Collect_Entry_Families (Loc, Cdecls, Current_Node, Prot_Typ);
 
-      --  Prepend the _Object field with the right type to the component list.
-      --  We need to compute the number of entries, and in some cases the
-      --  number of Attach_Handler pragmas.
-
-      declare
-         Ritem              : Node_Id;
-         Num_Attach_Handler : Int := 0;
-         Protection_Subtype : Node_Id;
-         Entry_Count_Expr   : constant Node_Id :=
-                                Build_Entry_Count_Expression
-                                  (Prot_Typ, Cdecls, Loc);
-
-      begin
-         --  Could this be simplified using Corresponding_Runtime_Package???
-
-         if Has_Attach_Handler (Prot_Typ) then
-            Ritem := First_Rep_Item (Prot_Typ);
-            while Present (Ritem) loop
-               if Nkind (Ritem) = N_Pragma
-                 and then Pragma_Name (Ritem) = Name_Attach_Handler
-               then
-                  Num_Attach_Handler := Num_Attach_Handler + 1;
-               end if;
-
-               Next_Rep_Item (Ritem);
-            end loop;
-
-            if Restricted_Profile then
-               if Has_Entries (Prot_Typ) then
-                  Protection_Subtype :=
-                    New_Reference_To (RTE (RE_Protection_Entry), Loc);
-               else
-                  Protection_Subtype :=
-                    New_Reference_To (RTE (RE_Protection), Loc);
-               end if;
-            else
-               Protection_Subtype :=
-                 Make_Subtype_Indication
-                   (Sloc => Loc,
-                    Subtype_Mark =>
-                      New_Reference_To
-                        (RTE (RE_Static_Interrupt_Protection), Loc),
-                    Constraint =>
-                      Make_Index_Or_Discriminant_Constraint (
-                        Sloc => Loc,
-                        Constraints => New_List (
-                          Entry_Count_Expr,
-                          Make_Integer_Literal (Loc, Num_Attach_Handler))));
-            end if;
-
-         elsif Has_Interrupt_Handler (Prot_Typ)
-           and then not Restriction_Active (No_Dynamic_Attachment)
-         then
-            Protection_Subtype :=
-               Make_Subtype_Indication (
-                 Sloc => Loc,
-                 Subtype_Mark => New_Reference_To
-                   (RTE (RE_Dynamic_Interrupt_Protection), Loc),
-                 Constraint =>
-                   Make_Index_Or_Discriminant_Constraint (
-                     Sloc => Loc,
-                     Constraints => New_List (Entry_Count_Expr)));
-
-         --  Type has explicit entries or generated primitive entry wrappers
-
-         elsif Has_Entries (Prot_Typ)
-           or else (Ada_Version >= Ada_2005
-                      and then Present (Interface_List (N)))
-         then
-            case Corresponding_Runtime_Package (Prot_Typ) is
-               when System_Tasking_Protected_Objects_Entries =>
-                  Protection_Subtype :=
-                     Make_Subtype_Indication (Loc,
-                       Subtype_Mark =>
-                         New_Reference_To (RTE (RE_Protection_Entries), Loc),
-                       Constraint =>
-                         Make_Index_Or_Discriminant_Constraint (
-                           Sloc => Loc,
-                           Constraints => New_List (Entry_Count_Expr)));
-
-               when System_Tasking_Protected_Objects_Single_Entry =>
-                  Protection_Subtype :=
-                    New_Reference_To (RTE (RE_Protection_Entry), Loc);
-
-               when others =>
-                  raise Program_Error;
-            end case;
-
-         else
-            Protection_Subtype := New_Reference_To (RTE (RE_Protection), Loc);
-         end if;
-
-         Object_Comp :=
-           Make_Component_Declaration (Loc,
-             Defining_Identifier =>
-               Make_Defining_Identifier (Loc, Name_uObject),
-             Component_Definition =>
-               Make_Component_Definition (Loc,
-                 Aliased_Present    => True,
-                 Subtype_Indication => Protection_Subtype));
-      end;
-
       pragma Assert (Present (Pdef));
 
       --  Add private field components
@@ -9144,10 +8820,117 @@ package body Exp_Ch9 is
          end loop;
       end if;
 
-      --  Put the _Object component after the private component so that it
-      --  be finalized early as required by 9.4 (20)
+      --  Except for the lock-free implementation, prepend the _Object field
+      --  with the right type to the component list. We need to compute the
+      --  number of entries, and in some cases the number of Attach_Handler
+      --  pragmas.
+
+      if not Lock_Free_Active then
+         declare
+            Ritem              : Node_Id;
+            Num_Attach_Handler : Int := 0;
+            Protection_Subtype : Node_Id;
+            Entry_Count_Expr   : constant Node_Id :=
+                                   Build_Entry_Count_Expression
+                                     (Prot_Typ, Cdecls, Loc);
+
+         begin
+            --  Could this be simplified using Corresponding_Runtime_Package???
+
+            if Has_Attach_Handler (Prot_Typ) then
+               Ritem := First_Rep_Item (Prot_Typ);
+               while Present (Ritem) loop
+                  if Nkind (Ritem) = N_Pragma
+                    and then Pragma_Name (Ritem) = Name_Attach_Handler
+                  then
+                     Num_Attach_Handler := Num_Attach_Handler + 1;
+                  end if;
+
+                  Next_Rep_Item (Ritem);
+               end loop;
+
+               if Restricted_Profile then
+                  if Has_Entries (Prot_Typ) then
+                     Protection_Subtype :=
+                       New_Reference_To (RTE (RE_Protection_Entry), Loc);
+                  else
+                     Protection_Subtype :=
+                       New_Reference_To (RTE (RE_Protection), Loc);
+                  end if;
+               else
+                  Protection_Subtype :=
+                    Make_Subtype_Indication
+                      (Sloc => Loc,
+                       Subtype_Mark =>
+                         New_Reference_To
+                           (RTE (RE_Static_Interrupt_Protection), Loc),
+                       Constraint =>
+                         Make_Index_Or_Discriminant_Constraint (
+                           Sloc => Loc,
+                           Constraints => New_List (
+                             Entry_Count_Expr,
+                             Make_Integer_Literal (Loc, Num_Attach_Handler))));
+               end if;
+
+            elsif Has_Interrupt_Handler (Prot_Typ)
+              and then not Restriction_Active (No_Dynamic_Attachment)
+            then
+               Protection_Subtype :=
+                  Make_Subtype_Indication (
+                    Sloc => Loc,
+                    Subtype_Mark => New_Reference_To
+                      (RTE (RE_Dynamic_Interrupt_Protection), Loc),
+                    Constraint =>
+                      Make_Index_Or_Discriminant_Constraint (
+                        Sloc => Loc,
+                        Constraints => New_List (Entry_Count_Expr)));
+
+            --  Type has explicit entries or generated primitive entry wrappers
 
-      Append_To (Cdecls, Object_Comp);
+            elsif Has_Entries (Prot_Typ)
+              or else (Ada_Version >= Ada_2005
+                         and then Present (Interface_List (N)))
+            then
+               case Corresponding_Runtime_Package (Prot_Typ) is
+                  when System_Tasking_Protected_Objects_Entries =>
+                     Protection_Subtype :=
+                        Make_Subtype_Indication (Loc,
+                          Subtype_Mark =>
+                            New_Reference_To (RTE (RE_Protection_Entries),
+                              Loc),
+                          Constraint =>
+                            Make_Index_Or_Discriminant_Constraint (
+                              Sloc => Loc,
+                              Constraints => New_List (Entry_Count_Expr)));
+
+                  when System_Tasking_Protected_Objects_Single_Entry =>
+                     Protection_Subtype :=
+                       New_Reference_To (RTE (RE_Protection_Entry), Loc);
+
+                  when others =>
+                     raise Program_Error;
+               end case;
+
+            else
+               Protection_Subtype :=
+                 New_Reference_To (RTE (RE_Protection), Loc);
+            end if;
+
+            Object_Comp :=
+              Make_Component_Declaration (Loc,
+                Defining_Identifier =>
+                  Make_Defining_Identifier (Loc, Name_uObject),
+                Component_Definition =>
+                  Make_Component_Definition (Loc,
+                    Aliased_Present    => True,
+                    Subtype_Indication => Protection_Subtype));
+         end;
+
+         --  Put the _Object component after the private component so that it
+         --  be finalized early as required by 9.4 (20)
+
+         Append_To (Cdecls, Object_Comp);
+      end if;
 
       Insert_After (Current_Node, Rec_Decl);
       Current_Node := Rec_Decl;
@@ -13149,9 +12932,12 @@ package body Exp_Ch9 is
       end if;
 
       --  Step 2: Create the Protection object and build its declaration for
-      --  any protected entry (family) of subprogram.
+      --  any protected entry (family) of subprogram. Note for the lock-free
+      --  implementation, the Protection object is not needed anymore.
 
-      if Is_Protected then
+      if Is_Protected
+        and then not Uses_Lock_Free (Conc_Typ)
+      then
          declare
             Prot_Ent : constant Entity_Id := Make_Temporary (Loc, 'R');
             Prot_Typ : RE_Id;
@@ -13612,191 +13398,200 @@ package body Exp_Ch9 is
 
       Args := New_List;
 
-      --  Object parameter. This is a pointer to the object of type
-      --  Protection used by the GNARL to control the protected object.
-
-      Append_To (Args,
-        Make_Attribute_Reference (Loc,
-          Prefix =>
-            Make_Selected_Component (Loc,
-              Prefix        => Make_Identifier (Loc, Name_uInit),
-              Selector_Name => Make_Identifier (Loc, Name_uObject)),
-          Attribute_Name => Name_Unchecked_Access));
-
-      --  Priority parameter. Set to Unspecified_Priority unless there is a
-      --  priority pragma, in which case we take the value from the pragma,
-      --  or there is an interrupt pragma and no priority pragma, and we
-      --  set the ceiling to Interrupt_Priority'Last, an implementation-
-      --  defined value, see D.3(10).
-
-      if Present (Pdef)
-        and then Has_Pragma_Priority (Pdef)
-      then
-         declare
-            Prio : constant Node_Id :=
-                     Expression
-                       (First
-                          (Pragma_Argument_Associations
-                             (Find_Task_Or_Protected_Pragma
-                                (Pdef, Name_Priority))));
-            Temp : Entity_Id;
-
-         begin
-            --  If priority is a static expression, then we can duplicate it
-            --  with no problem and simply append it to the argument list.
-
-            if Is_Static_Expression (Prio) then
-               Append_To (Args,
-                          Duplicate_Subexpr_No_Checks (Prio));
-
-            --  Otherwise, the priority may be a per-object expression, if it
-            --  depends on a discriminant of the type. In this case, create
-            --  local variable to capture the expression. Note that it is
-            --  really necessary to create this variable explicitly. It might
-            --  be thought that removing side effects would the appropriate
-            --  approach, but that could generate declarations improperly
-            --  placed in the enclosing scope.
-
-            --  Note: Use System.Any_Priority as the expected type for the
-            --  non-static priority expression, in case the expression has not
-            --  been analyzed yet (as occurs for example with pragma
-            --  Interrupt_Priority).
-
-            else
-               Temp := Make_Temporary (Loc, 'R', Prio);
-               Append_To (L,
-                  Make_Object_Declaration (Loc,
-                     Defining_Identifier => Temp,
-                     Object_Definition   =>
-                       New_Occurrence_Of (RTE (RE_Any_Priority), Loc),
-                     Expression          => Relocate_Node (Prio)));
-
-               Append_To (Args, New_Occurrence_Of (Temp, Loc));
-            end if;
-         end;
+      --  For lock-free implementation, skip initializations of the Protection
+      --  object.
 
-      --  When no priority is specified but an xx_Handler pragma is, we default
-      --  to System.Interrupts.Default_Interrupt_Priority, see D.3(10).
+      if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
+         --  Object parameter. This is a pointer to the object of type
+         --  Protection used by the GNARL to control the protected object.
 
-      elsif Has_Attach_Handler (Ptyp)
-        or else Has_Interrupt_Handler (Ptyp)
-      then
          Append_To (Args,
-           New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc));
+           Make_Attribute_Reference (Loc,
+             Prefix =>
+               Make_Selected_Component (Loc,
+                 Prefix        => Make_Identifier (Loc, Name_uInit),
+                 Selector_Name => Make_Identifier (Loc, Name_uObject)),
+             Attribute_Name => Name_Unchecked_Access));
+
+         --  Priority parameter. Set to Unspecified_Priority unless there is a
+         --  priority pragma, in which case we take the value from the pragma,
+         --  or there is an interrupt pragma and no priority pragma, and we
+         --  set the ceiling to Interrupt_Priority'Last, an implementation-
+         --  defined value, see D.3(10).
+
+         if Present (Pdef)
+           and then Has_Pragma_Priority (Pdef)
+         then
+            declare
+               Prio : constant Node_Id :=
+                        Expression
+                          (First
+                             (Pragma_Argument_Associations
+                                (Find_Task_Or_Protected_Pragma
+                                   (Pdef, Name_Priority))));
+               Temp : Entity_Id;
 
-      --  Normal case, no priority or xx_Handler specified, default priority
+            begin
+               --  If priority is a static expression, then we can duplicate it
+               --  with no problem and simply append it to the argument list.
 
-      else
-         Append_To (Args,
-           New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
-      end if;
+               if Is_Static_Expression (Prio) then
+                  Append_To (Args,
+                    Duplicate_Subexpr_No_Checks (Prio));
 
-      --  Test for Compiler_Info parameter. This parameter allows entry body
-      --  procedures and barrier functions to be called from the runtime. It
-      --  is a pointer to the record generated by the compiler to represent
-      --  the protected object.
+               --  Otherwise, the priority may be a per-object expression, if
+               --  it depends on a discriminant of the type. In this case,
+               --  create local variable to capture the expression. Note that
+               --  it is really necessary to create this variable explicitly.
+               --  It might be thought that removing side effects would the
+               --  appropriate approach, but that could generate declarations
+               --  improperly placed in the enclosing scope.
 
-      --  A protected type without entries that covers an interface and
-      --  overrides the abstract routines with protected procedures is
-      --  considered equivalent to a protected type with entries in the
-      --  context of dispatching select statements.
+               --  Note: Use System.Any_Priority as the expected type for the
+               --  non-static priority expression, in case the expression has
+               --  not been analyzed yet (as occurs for example with pragma
+               --  Interrupt_Priority).
 
-      if Has_Entry
-        or else Has_Interfaces (Protect_Rec)
-        or else
-          ((Has_Attach_Handler (Ptyp) or else Has_Interrupt_Handler (Ptyp))
-             and then not Restriction_Active (No_Dynamic_Attachment))
-      then
-         declare
-            Pkg_Id : constant RTU_Id  := Corresponding_Runtime_Package (Ptyp);
+               else
+                  Temp := Make_Temporary (Loc, 'R', Prio);
+                  Append_To (L,
+                     Make_Object_Declaration (Loc,
+                        Defining_Identifier => Temp,
+                        Object_Definition   =>
+                          New_Occurrence_Of (RTE (RE_Any_Priority), Loc),
+                        Expression          => Relocate_Node (Prio)));
+
+                  Append_To (Args, New_Occurrence_Of (Temp, Loc));
+               end if;
+            end;
 
-            Called_Subp : RE_Id;
+         --  When no priority is specified but an xx_Handler pragma is, we
+         --  default to System.Interrupts.Default_Interrupt_Priority, see
+         --  D.3(10).
 
-         begin
-            case Pkg_Id is
-               when System_Tasking_Protected_Objects_Entries =>
-                  Called_Subp := RE_Initialize_Protection_Entries;
+         elsif Has_Attach_Handler (Ptyp)
+           or else Has_Interrupt_Handler (Ptyp)
+         then
+            Append_To (Args,
+              New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc));
 
-               when System_Tasking_Protected_Objects =>
-                  Called_Subp := RE_Initialize_Protection;
+         --  Normal case, no priority or xx_Handler specified, default priority
 
-               when System_Tasking_Protected_Objects_Single_Entry =>
-                  Called_Subp := RE_Initialize_Protection_Entry;
+         else
+            Append_To (Args,
+              New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
+         end if;
 
-               when others =>
-                  raise Program_Error;
-            end case;
+         --  Test for Compiler_Info parameter. This parameter allows entry body
+         --  procedures and barrier functions to be called from the runtime. It
+         --  is a pointer to the record generated by the compiler to represent
+         --  the protected object.
+
+         --  A protected type without entries that covers an interface and
+         --  overrides the abstract routines with protected procedures is
+         --  considered equivalent to a protected type with entries in the
+         --  context of dispatching select statements.
+
+         if Has_Entry
+           or else Has_Interfaces (Protect_Rec)
+           or else
+             ((Has_Attach_Handler (Ptyp) or else Has_Interrupt_Handler (Ptyp))
+                and then not Restriction_Active (No_Dynamic_Attachment))
+         then
+            declare
+               Pkg_Id : constant RTU_Id  :=
+                          Corresponding_Runtime_Package (Ptyp);
 
-            if Has_Entry
-              or else not Restricted
-              or else Has_Interfaces (Protect_Rec)
-            then
-               Append_To (Args,
-                 Make_Attribute_Reference (Loc,
-                   Prefix         => Make_Identifier (Loc, Name_uInit),
-                   Attribute_Name => Name_Address));
-            end if;
+               Called_Subp : RE_Id;
 
-            --  Entry_Bodies parameter. This is a pointer to an array of
-            --  pointers to the entry body procedures and barrier functions of
-            --  the object. If the protected type has no entries this object
-            --  will not exist, in this case, pass a null.
+            begin
+               case Pkg_Id is
+                  when System_Tasking_Protected_Objects_Entries =>
+                     Called_Subp := RE_Initialize_Protection_Entries;
 
-            if Has_Entry then
-               P_Arr := Entry_Bodies_Array (Ptyp);
+                  when System_Tasking_Protected_Objects =>
+                     Called_Subp := RE_Initialize_Protection;
 
-               Append_To (Args,
-                 Make_Attribute_Reference (Loc,
-                   Prefix => New_Reference_To (P_Arr, Loc),
-                   Attribute_Name => Name_Unrestricted_Access));
+                  when System_Tasking_Protected_Objects_Single_Entry =>
+                     Called_Subp := RE_Initialize_Protection_Entry;
+
+                  when others =>
+                     raise Program_Error;
+               end case;
 
-               if Pkg_Id = System_Tasking_Protected_Objects_Entries then
+               if Has_Entry
+                 or else not Restricted
+                 or else Has_Interfaces (Protect_Rec)
+               then
+                  Append_To (Args,
+                    Make_Attribute_Reference (Loc,
+                      Prefix         => Make_Identifier (Loc, Name_uInit),
+                      Attribute_Name => Name_Address));
+               end if;
 
-                  --  Find index mapping function (clumsy but ok for now)
+               --  Entry_Bodies parameter. This is a pointer to an array of
+               --  pointers to the entry body procedures and barrier functions
+               --  of the object. If the protected type has no entries this
+               --  object will not exist, in this case, pass a null.
 
-                  while Ekind (P_Arr) /= E_Function loop
-                     Next_Entity (P_Arr);
-                  end loop;
+               if Has_Entry then
+                  P_Arr := Entry_Bodies_Array (Ptyp);
 
                   Append_To (Args,
                     Make_Attribute_Reference (Loc,
-                      Prefix         => New_Reference_To (P_Arr, Loc),
+                      Prefix => New_Reference_To (P_Arr, Loc),
                       Attribute_Name => Name_Unrestricted_Access));
 
-                  --  Build_Entry_Names generation flag. When set to true, the
-                  --  runtime will allocate an array to hold the string names
-                  --  of protected entries.
+                  if Pkg_Id = System_Tasking_Protected_Objects_Entries then
 
-                  if not Restricted_Profile then
-                     if Entry_Names_OK then
-                        Append_To (Args,
-                          New_Reference_To (Standard_True, Loc));
-                     else
-                        Append_To (Args,
-                          New_Reference_To (Standard_False, Loc));
+                     --  Find index mapping function (clumsy but ok for now)
+
+                     while Ekind (P_Arr) /= E_Function loop
+                        Next_Entity (P_Arr);
+                     end loop;
+
+                     Append_To (Args,
+                       Make_Attribute_Reference (Loc,
+                         Prefix         => New_Reference_To (P_Arr, Loc),
+                         Attribute_Name => Name_Unrestricted_Access));
+
+                     --  Build_Entry_Names generation flag. When set to true,
+                     --  the runtime will allocate an array to hold the string
+                     --  names of protected entries.
+
+                     if not Restricted_Profile then
+                        if Entry_Names_OK then
+                           Append_To (Args,
+                             New_Reference_To (Standard_True, Loc));
+                        else
+                           Append_To (Args,
+                             New_Reference_To (Standard_False, Loc));
+                        end if;
                      end if;
                   end if;
-               end if;
 
-            elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then
-               Append_To (Args, Make_Null (Loc));
+               elsif Pkg_Id =
+                       System_Tasking_Protected_Objects_Single_Entry
+               then
+                  Append_To (Args, Make_Null (Loc));
 
-            elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
-               Append_To (Args, Make_Null (Loc));
-               Append_To (Args, Make_Null (Loc));
-               Append_To (Args, New_Reference_To (Standard_False, Loc));
-            end if;
+               elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
+                  Append_To (Args, Make_Null (Loc));
+                  Append_To (Args, Make_Null (Loc));
+                  Append_To (Args, New_Reference_To (Standard_False, Loc));
+               end if;
 
+               Append_To (L,
+                 Make_Procedure_Call_Statement (Loc,
+                   Name => New_Reference_To (RTE (Called_Subp), Loc),
+                   Parameter_Associations => Args));
+            end;
+         else
             Append_To (L,
               Make_Procedure_Call_Statement (Loc,
-                Name => New_Reference_To (RTE (Called_Subp), Loc),
+                Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc),
                 Parameter_Associations => Args));
-         end;
-      else
-         Append_To (L,
-           Make_Procedure_Call_Statement (Loc,
-             Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc),
-             Parameter_Associations => Args));
+         end if;
       end if;
 
       if Has_Attach_Handler (Ptyp) then
@@ -13868,15 +13663,18 @@ package body Exp_Ch9 is
                    Parameter_Associations => Args));
 
             else
-               --  First, prepends the _object argument
+               if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
+                  --  First, prepends the _object argument
 
-               Prepend_To (Args,
-                 Make_Attribute_Reference (Loc,
-                   Prefix =>
-                     Make_Selected_Component (Loc,
-                       Prefix        => Make_Identifier (Loc, Name_uInit),
-                       Selector_Name => Make_Identifier (Loc, Name_uObject)),
-                   Attribute_Name => Name_Unchecked_Access));
+                  Prepend_To (Args,
+                    Make_Attribute_Reference (Loc,
+                      Prefix =>
+                        Make_Selected_Component (Loc,
+                          Prefix        => Make_Identifier (Loc, Name_uInit),
+                          Selector_Name =>
+                            Make_Identifier (Loc, Name_uObject)),
+                      Attribute_Name => Name_Unchecked_Access));
+               end if;
 
                --  Then, insert call to Install_Handlers
 
index 8615b02..723ff12 100644 (file)
@@ -1343,7 +1343,7 @@ package body GNAT.Command_Line is
    begin
       if Switch /= "" or else Long_Switch /= "" then
          Initialize_Switch_Def
-            (Def, Switch, Long_Switch, Help, Section, Argument);
+           (Def, Switch, Long_Switch, Help, Section, Argument);
          Add (Config, Def);
       end if;
    end Define_Switch;
@@ -1390,7 +1390,7 @@ package body GNAT.Command_Line is
    begin
       if Switch /= "" or else Long_Switch /= "" then
          Initialize_Switch_Def
-            (Def, Switch, Long_Switch, Help, Section, Argument);
+           (Def, Switch, Long_Switch, Help, Section, Argument);
          Def.Integer_Output  := Output.all'Unchecked_Access;
          Def.Integer_Default := Default;
          Def.Integer_Initial := Initial;
@@ -1415,7 +1415,7 @@ package body GNAT.Command_Line is
    begin
       if Switch /= "" or else Long_Switch /= "" then
          Initialize_Switch_Def
-            (Def, Switch, Long_Switch, Help, Section, Argument);
+           (Def, Switch, Long_Switch, Help, Section, Argument);
          Def.String_Output  := Output.all'Unchecked_Access;
          Add (Config, Def);
       end if;
@@ -3233,7 +3233,9 @@ package body GNAT.Command_Line is
                   end if;
                end if;
 
-            else  --  Long_Switch necessarily not null
+            --  Def.Switch is null (Long_Switch must be non-null)
+
+            else
                Decompose_Switch (Def.Long_Switch.all, P2, Last2);
                Append (Result,
                        Def.Long_Switch (Def.Long_Switch'First .. Last2));
index c3479bb..c4b290e 100644 (file)
 --     ...
 
 --  Specifying the help message is optional, but makes it easy to then call
---  the function
+--  the function:
+
 --     Display_Help (Config);
+
 --  that will display a properly formatted help message for your application,
 --  listing all possible switches. That way you have a single place in which
 --  to maintain the list of switches and their meaning, rather than maintaining
 --  both the string to pass to Getopt and a subprogram to display the help.
 --  Both will properly stay synchronized.
 
---  Once you have this Config, you just have to call
+--  Once you have this Config, you just have to call:
+
 --     Getopt (Config, Callback'Access);
+
 --  to parse the command line. The Callback will be called for each switch
 --  found on the command line (in the case of our example, that is "-gnatwu"
 --  and then "-gnatwv", not "-gnatwa" itself). This simplifies command line
 
 --     Optimization : aliased Integer;
 --     Verbose      : aliased Boolean;
---
+
 --     Define_Switch (Config, Verbose'Access,
 --                    "-v", Long_Switch => "--verbose",
 --                    Help => "Output extra verbose information");
 --     Define_Switch (Config, Optimization'Access,
 --                    "-O?", Help => "Optimization level");
---
+
 --     Getopt (Config);  --  No callback
 
 --  Since all switches are handled automatically, we don't even need to pass
 --  Some command line arguments can have parameters, which on a command line
 --  appear as a separate argument that must immediately follow the switch.
 --  Since the subprograms in this package will reorganize the switches to group
---  them, you need to indicate what is a command line
---  parameter, and what is a switch argument.
+--  them, you need to indicate what is a command line parameter, and what is a
+--  switch argument.
 
 --  This is done by passing an extra argument to Add_Switch, as in:
 
@@ -308,18 +312,18 @@ package GNAT.Command_Line is
       Stop_At_First_Non_Switch : Boolean := False;
       Section_Delimiters       : String := "");
    --  The first procedure resets the internal state of the package to prepare
-   --  to rescan the parameters. It does not need to be called before the first
-   --  use of Getopt (but it could be), but it must be called if you want to
-   --  start rescanning the command line parameters from the start. The
-   --  optional parameter Switch_Char can be used to reset the switch
+   --  to rescan the parameters. It does not need to be called before the
+   --  first use of Getopt (but it could be), but it must be called if you
+   --  want to start rescanning the command line parameters from the start.
+   --  The optional parameter Switch_Char can be used to reset the switch
    --  character, e.g. to '/' for use in DOS-like systems.
    --
-   --  The second subprogram initializes a parser that takes its arguments from
-   --  an array of strings rather than directly from the command line. In this
-   --  case, the parser is responsible for freeing the strings stored in
+   --  The second subprogram initializes a parser that takes its arguments
+   --  from an array of strings rather than directly from the command line. In
+   --  this case, the parser is responsible for freeing the strings stored in
    --  Command_Line. If you pass null to Command_Line, this will in fact create
    --  a second parser for Ada.Command_Line, which doesn't share any data with
-   --  the default parser. This parser must be free-ed.
+   --  the default parser. This parser must be free'ed.
    --
    --  The optional parameter Stop_At_First_Non_Switch indicates if Getopt is
    --  to look for switches on the whole command line, or if it has to stop as
@@ -451,9 +455,9 @@ package GNAT.Command_Line is
    --  spaces.
    --
    --    Example
-   --       Getopt ("a b", Concatenate => False)
-   --       If the command line is '-ab', exception Invalid_Switch will be
-   --       raised and Full_Switch will return "ab".
+   --      Getopt ("a b", Concatenate => False)
+   --      If the command line is '-ab', exception Invalid_Switch will be
+   --      raised and Full_Switch will return "ab".
 
    function Get_Argument
      (Do_Expansion : Boolean := False;
@@ -559,8 +563,8 @@ package GNAT.Command_Line is
    --  The section name should not include the leading '-'. So for instance in
    --  the case of gnatmake we would use:
    --
-   --      Define_Section (Config, "cargs");
-   --      Define_Section (Config, "bargs");
+   --    Define_Section (Config, "cargs");
+   --    Define_Section (Config, "bargs");
 
    procedure Define_Alias
      (Config   : in out Command_Line_Configuration;
@@ -609,9 +613,9 @@ package GNAT.Command_Line is
    --
    --  Switch and Long_Switch (when specified) are aliases and can be used
    --  interchangeably. There is no check that they both take an argument or
-   --  both take no argument.
-   --  Switch can be set to "*" to indicate that any switch is supported (in
-   --  which case Getopt will return '*', see its documentation).
+   --  both take no argument. Switch can be set to "*" to indicate that any
+   --  switch is supported (in which case Getopt will return '*', see its
+   --  documentation).
    --
    --  Help is used by the Display_Help procedure to describe the supported
    --  switches.
@@ -633,11 +637,13 @@ package GNAT.Command_Line is
    --  See Define_Switch for a description of the parameters.
    --  When the switch is found on the command line, Getopt will set
    --  Output.all to Value.
+   --
    --  Output is always initially set to "not Value", so that if the switch is
    --  not found on the command line, Output still has a valid value.
    --  The switch must not take any parameter.
-   --  Output must exist at least as long as Config, otherwise erroneous memory
-   --  access may happen.
+   --
+   --  Output must exist at least as long as Config, otherwise an erroneous
+   --  memory access may occur.
 
    procedure Define_Switch
      (Config      : in out Command_Line_Configuration;
@@ -649,14 +655,14 @@ package GNAT.Command_Line is
       Initial     : Integer := 0;
       Default     : Integer := 1;
       Argument    : String := "ARG");
-   --  See Define_Switch for a description of the parameters.
-   --  When the switch is found on the command line, Getopt will set
-   --  Output.all to the value of the switch's parameter. If the parameter is
-   --  not an integer, Invalid_Parameter is raised.
+   --  See Define_Switch for a description of the parameters. When the
+   --  switch is found on the command line, Getopt will set Output.all to the
+   --  value of the switch's parameter. If the parameter is not an integer,
+   --  Invalid_Parameter is raised.
+
    --  Output is always initialized to Initial. If the switch has an optional
    --  argument which isn't specified by the user, then Output will be set to
-   --  Default.
-   --  The switch must accept an argument.
+   --  Default. The switch must accept an argument.
 
    procedure Define_Switch
      (Config      : in out Command_Line_Configuration;
@@ -667,11 +673,10 @@ package GNAT.Command_Line is
       Section     : String := "";
       Argument    : String := "ARG");
    --  Set Output to the value of the switch's parameter when the switch is
-   --  found on the command line.
-   --  Output is always initialized to the empty string if it does not have
-   --  a value already (otherwise it is left as is so that you can specify the
-   --  default value directly in the declaration of the variable).
-   --  The switch must accept an argument.
+   --  found on the command line. Output is always initialized to the empty
+   --  string if it does not have a value already (otherwise it is left as is
+   --  so that you can specify the default value directly in the declaration
+   --  of the variable). The switch must accept an argument.
 
    procedure Set_Usage
      (Config   : in out Command_Line_Configuration;
@@ -705,15 +710,14 @@ package GNAT.Command_Line is
      (Switch    : String;
       Parameter : String;
       Section   : String);
-   --  Called when a switch is found on the command line.
-   --  [Switch] includes any leading '-' that was specified in Define_Switch.
-   --  This is slightly different from the functional version of Getopt above,
-   --  for which Full_Switch omits the first leading '-'.
+   --  Called when a switch is found on the command line. Switch includes
+   --  any leading '-' that was specified in Define_Switch. This is slightly
+   --  different from the functional version of Getopt above, for which
+   --  Full_Switch omits the first leading '-'.
 
    Exit_From_Command_Line : exception;
-   --  Emitted when the program should exit.
-   --  This is called when Getopt below has seen -h, --help or an invalid
-   --  switch.
+   --  Emitted when the program should exit. This is called when Getopt below
+   --  has seen -h, --help or an invalid switch.
 
    procedure Getopt
      (Config      : Command_Line_Configuration;
@@ -823,7 +827,7 @@ package GNAT.Command_Line is
    --  If the command line has sections (such as -bargs -cargs), then they
    --  should be listed in the Sections parameter (as "-bargs -cargs").
    --
-   --  This function can be used to reset Cmd by passing an empty string.
+   --  This function can be used to reset Cmd by passing an empty string
    --
    --  If an invalid switch is found on the command line (ie wasn't defined in
    --  the configuration via Define_Switch), and the configuration wasn't set
@@ -947,6 +951,7 @@ package GNAT.Command_Line is
    ---------------
    -- Iteration --
    ---------------
+
    --  When a command line was created with the above, you can then iterate
    --  over its contents using the following iterator.
 
@@ -992,6 +997,7 @@ package GNAT.Command_Line is
    --  create an Opt_Parser.
    --
    --  Args must be freed by the caller.
+   --
    --  Expanded has the same meaning as in Start.
 
 private
index e02f575..a01505c 100644 (file)
@@ -739,6 +739,8 @@ package Rtsfind is
      RE_Atomic_Load_16,                  -- System.Atomic_Primitives
      RE_Atomic_Load_32,                  -- System.Atomic_Primitives
      RE_Atomic_Load_64,                  -- System.Atomic_Primitives
+     RE_Atomic_Synchronize,              -- System.Atomic_Primitives
+     RE_Relaxed,                         -- System.Atomic_Primitives
      RE_Uint8,                           -- System.Atomic_Primitives
      RE_Uint16,                          -- System.Atomic_Primitives
      RE_Uint32,                          -- System.Atomic_Primitives
@@ -1960,6 +1962,8 @@ package Rtsfind is
      RE_Atomic_Load_16                   => System_Atomic_Primitives,
      RE_Atomic_Load_32                   => System_Atomic_Primitives,
      RE_Atomic_Load_64                   => System_Atomic_Primitives,
+     RE_Atomic_Synchronize               => System_Atomic_Primitives,
+     RE_Relaxed                          => System_Atomic_Primitives,
      RE_Uint8                            => System_Atomic_Primitives,
      RE_Uint16                           => System_Atomic_Primitives,
      RE_Uint32                           => System_Atomic_Primitives,
index c8c75f2..3b87eb2 100644 (file)
 --                                                                          --
 ------------------------------------------------------------------------------
 
---  ??? Need header saying what this unit is!!!
+--  This package contains atomic primitives defined from gcc built-in functions
+
+--  For now, these operations are only used by the compiler to generate the
+--  lock-free implementation of protected objects.
 
 package System.Atomic_Primitives is
    pragma Preelaborate;
@@ -119,4 +122,6 @@ package System.Atomic_Primitives is
       Model : Mem_Model := Seq_Cst) return uint64;
    pragma Import (Intrinsic, Atomic_Load_64, "__atomic_load_8");
 
+   procedure Atomic_Synchronize;
+   pragma Import (Intrinsic, Atomic_Synchronize, "__sync_synchronize");
 end System.Atomic_Primitives;
index 3c3cce2..c8b987e 100644 (file)
@@ -926,16 +926,40 @@ package body Sem_Ch13 is
                when No_Aspect =>
                   raise Program_Error;
 
-               --  Aspects taking an optional boolean argument. For all of
-               --  these we just create a matching pragma and insert it, if
-               --  the expression is missing or set to True. If the expression
-               --  is False, we can ignore the aspect with the exception that
-               --  in the case of a derived type, we must check for an illegal
-               --  attempt to cancel an inherited aspect.
+               --  Aspects taking an optional boolean argument
 
                when Boolean_Aspects =>
                   Set_Is_Boolean_Aspect (Aspect);
 
+                  --  Special treatment for Aspect_Lock_Free since it is the
+                  --  only Boolean_Aspect that doesn't correspond to a pragma.
+
+                  if A_Id = Aspect_Lock_Free then
+                     if Ekind (E) /= E_Protected_Type then
+                        Error_Msg_N
+                          ("aspect % only applies to protected objects",
+                           Aspect);
+                     end if;
+
+                     --  Set the Uses_Lock_Free flag to True if there is no
+                     --  expression or if the expression is True.
+
+                     if No (Expr)
+                       or else Is_True (Static_Boolean (Expr))
+                     then
+                        Set_Uses_Lock_Free (E);
+                     end if;
+
+                     goto Continue;
+                  end if;
+
+                  --  For all of these aspects we just create a matching pragma
+                  --  and insert it, if the expression is missing or set to
+                  --  True. If the expression is False, we can ignore the
+                  --  aspect with the exception that in the case of a derived
+                  --  type, we must check for an illegal attempt to cancel an
+                  --  inherited aspect.
+
                   if Present (Expr)
                     and then Is_False (Static_Boolean (Expr))
                   then
index 72ce1c0..a91f494 100644 (file)
 --                                                                          --
 ------------------------------------------------------------------------------
 
+with Aspects;  use Aspects;
 with Atree;    use Atree;
 with Checks;   use Checks;
+with Debug;    use Debug;
 with Einfo;    use Einfo;
 with Errout;   use Errout;
 with Exp_Ch9;  use Exp_Ch9;
 with Elists;   use Elists;
 with Freeze;   use Freeze;
+with Layout;   use Layout;
 with Lib.Xref; use Lib.Xref;
 with Namet;    use Namet;
 with Nlists;   use Nlists;
@@ -64,6 +67,29 @@ package body Sem_Ch9 is
    -- Local Subprograms --
    -----------------------
 
+   function Allows_Lock_Free_Implementation
+     (N        : Node_Id;
+      Complain : Boolean := False) return Boolean;
+   --  This dispatch routine return True if N satisfies the following list of
+   --  lock-free restrictions for protected type declaration and protected
+   --  body:
+   --
+   --    1) Protected type declaration
+   --         May not contain entries
+   --         Component types must support atomic compare and exchange
+   --
+   --    2) Protected Body
+   --         Each protected subprogram body within N must satisfy:
+   --            May reference only one protected component
+   --            May not reference non-constant entities outside the protected
+   --              subprogram scope.
+   --            May not reference non-scalar out parameters
+   --            May not contain loop statements or procedure calls
+   --            Function calls and attribute references must be static
+   --
+   --  If Complain is set to True, an error message is issued when return
+   --  False.
+
    procedure Check_Max_Entries (D : Node_Id; R : All_Parameter_Restrictions);
    --  Given either a protected definition or a task definition in D, check
    --  the corresponding restriction parameter identifier R, and if it is set,
@@ -91,6 +117,304 @@ package body Sem_Ch9 is
    --  Utility to make visible in corresponding body the entities defined in
    --  task, protected type declaration, or entry declaration.
 
+   -------------------------------------
+   -- Allows_Lock_Free_Implementation --
+   -------------------------------------
+
+   function Allows_Lock_Free_Implementation
+     (N        : Node_Id;
+      Complain : Boolean := False) return Boolean
+   is
+   begin
+      pragma Assert (Nkind_In (N,
+                               N_Protected_Type_Declaration,
+                               N_Protected_Body));
+
+      --  The lock-free implementation is currently enabled through a debug
+      --  flag. When Complain is True, an aspect Lock_Free forces the lock-free
+      --  implementation. In that case, the debug flag is not needed.
+
+      if not Complain
+        and then not Debug_Flag_9
+      then
+         return False;
+      end if;
+
+      --  Protected type declaration case
+
+      if Nkind (N) = N_Protected_Type_Declaration then
+         declare
+            Pdef       : constant Node_Id := Protected_Definition (N);
+            Priv_Decls : constant List_Id := Private_Declarations (Pdef);
+            Vis_Decls  : constant List_Id := Visible_Declarations (Pdef);
+
+            Comp_Id    : Entity_Id;
+            Comp_Size  : Int;
+            Comp_Type  : Entity_Id;
+            Decl       : Node_Id;
+
+         begin
+            --  Examine the visible declarations. Entries and entry families
+            --  are not allowed by the lock-free restrictions.
+
+            Decl := First (Vis_Decls);
+            while Present (Decl) loop
+               if Nkind (Decl) = N_Entry_Declaration then
+                  if Complain then
+                     Error_Msg_N ("entry not allowed for lock-free " &
+                                  "implementation",
+                                  Decl);
+                  end if;
+
+                  return False;
+               end if;
+
+               Next (Decl);
+            end loop;
+
+            --  Examine the private declarations
+
+            Decl := First (Priv_Decls);
+            while Present (Decl) loop
+
+               --  The protected type must define at least one scalar component
+
+               if Nkind (Decl) = N_Component_Declaration then
+                  Comp_Id       := Defining_Identifier (Decl);
+                  Comp_Type     := Etype (Comp_Id);
+
+                  --  Make sure the protected component type has size and
+                  --  alignment fields set at this point whenever this is
+                  --  possible.
+
+                  Layout_Type (Comp_Type);
+
+                  if Known_Esize (Comp_Type) then
+                     Comp_Size := UI_To_Int (Esize (Comp_Type));
+
+                  --  If the Esize (Object_Size) is unknown at compile-time,
+                  --  look at the RM_Size (Value_Size) since it may have been
+                  --  set by an explicit representation clause.
+
+                  else
+                     Comp_Size := UI_To_Int (RM_Size (Comp_Type));
+                  end if;
+
+                  --  Check that the size of the component is 8, 16, 32 or 64
+                  --  bits.
+
+                  case Comp_Size is
+                     when 8 | 16 | 32 | 64 =>
+                        null;
+                     when others           =>
+                        if Complain then
+                           Error_Msg_N ("must support atomic operations for " &
+                                        "lock-free implementation",
+                                         Decl);
+                        end if;
+
+                        return False;
+                  end case;
+
+               --  Entries and entry families are not allowed
+
+               elsif Nkind (Decl) = N_Entry_Declaration then
+                  if Complain then
+                     Error_Msg_N ("entry not allowed for lock-free " &
+                                  "implementation",
+                                  Decl);
+                  end if;
+
+                  return False;
+               end if;
+
+               Next (Decl);
+            end loop;
+         end;
+
+      --  Protected body case
+
+      else
+         declare
+            Decls         : constant List_Id   := Declarations (N);
+            Pid           : constant Entity_Id := Corresponding_Spec (N);
+            Prot_Typ_Decl : constant Node_Id   := Parent (Pid);
+            Prot_Def      : constant Node_Id   :=
+                              Protected_Definition (Prot_Typ_Decl);
+            Priv_Decls    : constant List_Id   :=
+                              Private_Declarations (Prot_Def);
+            Decl          : Node_Id;
+
+            function Satisfies_Lock_Free_Requirements
+              (Sub_Body : Node_Id) return Boolean;
+            --  Return True if protected subprogram body Sub_Body satisfies all
+            --  requirements of a lock-free implementation.
+
+            --------------------------------------
+            -- Satisfies_Lock_Free_Requirements --
+            --------------------------------------
+
+            function Satisfies_Lock_Free_Requirements
+              (Sub_Body : Node_Id) return Boolean
+            is
+               Comp : Entity_Id := Empty;
+               --  Track the current component which the body references
+
+               function Check_Node (N : Node_Id) return Traverse_Result;
+               --  Check that node N meets the lock free restrictions
+
+               ----------------
+               -- Check_Node --
+               ----------------
+
+               function Check_Node (N : Node_Id) return Traverse_Result is
+               begin
+                  --  Function calls and attribute references must be static
+
+                  if Nkind_In (N, N_Attribute_Reference, N_Function_Call)
+                    and then not Is_Static_Expression (N)
+                  then
+                     return Abandon;
+
+                  --  Loop statements and procedure calls are prohibited
+
+                  elsif Nkind_In (N, N_Loop_Statement,
+                                     N_Procedure_Call_Statement)
+                  then
+                     return Abandon;
+
+                  --  References
+
+                  elsif Nkind (N) = N_Identifier
+                    and then Present (Entity (N))
+                  then
+                     declare
+                        Id     : constant Entity_Id := Entity (N);
+                        Sub_Id : constant Entity_Id :=
+                                   Corresponding_Spec (Sub_Body);
+
+                     begin
+                        --  Prohibit references to non-constant entities
+                        --  outside the protected subprogram scope.
+
+                        if Ekind (Id) in Assignable_Kind
+                          and then not Scope_Within_Or_Same (Scope (Id),
+                                         Sub_Id)
+                          and then not Scope_Within_Or_Same (Scope (Id),
+                                         Protected_Body_Subprogram (Sub_Id))
+                        then
+                           return Abandon;
+
+                        --  Prohibit non-scalar out parameters (scalar
+                        --  parameters are passed by copy).
+
+                        elsif Ekind_In (Id, E_Out_Parameter,
+                                            E_In_Out_Parameter)
+                          and then not Is_Scalar_Type (Etype (Id))
+                          and then Scope_Within_Or_Same (Scope (Id), Sub_Id)
+                        then
+                           return Abandon;
+
+                        --  A protected subprogram may reference only one
+                        --  component of the protected type.
+
+                        elsif Ekind (Id) = E_Component then
+                           declare
+                              Comp_Decl : constant Node_Id := Parent (Id);
+                           begin
+                              if Nkind (Comp_Decl) = N_Component_Declaration
+                                and then Is_List_Member (Comp_Decl)
+                                and then List_Containing (Comp_Decl) =
+                                           Priv_Decls
+                              then
+                                 if No (Comp) then
+                                    Comp := Id;
+
+                                 --  Check if another protected component has
+                                 --  already been accessed by the subprogram
+                                 --  body.
+
+                                 elsif Comp /= Id then
+                                    return Abandon;
+                                 end if;
+                              end if;
+                           end;
+
+                        elsif Ekind_In (Id, E_Constant, E_Variable)
+                          and then Present (Prival_Link (Id))
+                        then
+                           declare
+                              Comp_Decl : constant Node_Id :=
+                                            Parent (Prival_Link (Id));
+                           begin
+                              if Nkind (Comp_Decl) = N_Component_Declaration
+                                and then Is_List_Member (Comp_Decl)
+                                and then List_Containing (Comp_Decl) =
+                                           Priv_Decls
+                              then
+                                 if No (Comp) then
+                                    Comp := Prival_Link (Id);
+
+                                 --  Check if another protected component has
+                                 --  already been accessed by the subprogram
+                                 --  body.
+
+                                 elsif Comp /= Prival_Link (Id) then
+                                    return Abandon;
+                                 end if;
+                              end if;
+                           end;
+                        end if;
+                     end;
+                  end if;
+
+                  return OK;
+               end Check_Node;
+
+               function Check_All_Nodes is new Traverse_Func (Check_Node);
+
+            --  Start of processing for Satisfies_Lock_Free_Requirements
+
+            begin
+               if Check_All_Nodes (Sub_Body) = OK then
+
+                  --  Establish a relation between the subprogram body and the
+                  --  unique protected component it references.
+
+                  if Present (Comp) then
+                     Lock_Free_Subprogram_Table.Append
+                       (Lock_Free_Subprogram'(Sub_Body, Comp));
+                  end if;
+
+                  return True;
+               else
+                  return False;
+               end if;
+            end Satisfies_Lock_Free_Requirements;
+
+         begin
+            Decl := First (Decls);
+
+            while Present (Decl) loop
+               if Nkind (Decl) = N_Subprogram_Body
+                 and then not Satisfies_Lock_Free_Requirements (Decl)
+               then
+                  if Complain then
+                     Error_Msg_N ("body prevents lock-free implementation",
+                                  Decl);
+                  end if;
+
+                  return False;
+               end if;
+
+               Next (Decl);
+            end loop;
+         end;
+      end if;
+
+      return True;
+   end Allows_Lock_Free_Implementation;
+
    -----------------------------
    -- Analyze_Abort_Statement --
    -----------------------------
@@ -1057,6 +1381,7 @@ package body Sem_Ch9 is
 
    procedure Analyze_Protected_Body (N : Node_Id) is
       Body_Id : constant Entity_Id := Defining_Identifier (N);
+      Aspect  : Node_Id;
       Last_E  : Entity_Id;
 
       Spec_Id : Entity_Id;
@@ -1130,6 +1455,42 @@ package body Sem_Ch9 is
       Check_References (Spec_Id);
       Process_End_Label (N, 't', Ref_Id);
       End_Scope;
+
+      --  Turn on/off the lock-free implementation for the protected object
+
+      --  Look for a Lock_Free aspect with a False expression that disables the
+      --  lock-free implementation.
+
+      Aspect := First (Aspect_Specifications (Parent (Spec_Id)));
+
+      while Present (Aspect) loop
+         if Get_Aspect_Id (Chars (Identifier (Aspect))) = Aspect_Lock_Free
+           and then Present (Expression (Aspect))
+           and then Entity (Expression (Aspect)) = Standard_False
+         then
+            return;
+         end if;
+
+         Next (Aspect);
+      end loop;
+
+      --  When a Lock_Free aspect forces the lock-free implementation, verify
+      --  the protected body meets all the restrictions, otherwise
+      --  Allows_Lock_Free_Implementation issues an error message.
+
+      if Uses_Lock_Free (Spec_Id) then
+         if not Allows_Lock_Free_Implementation (N, Complain => True) then
+            return;
+         end if;
+
+      --  In other cases, check both the protected declaration and body satisfy
+      --  the lock-free restrictions.
+
+      elsif Allows_Lock_Free_Implementation (Parent (Spec_Id))
+        and then Allows_Lock_Free_Implementation (N)
+      then
+         Set_Uses_Lock_Free (Spec_Id);
+      end if;
    end Analyze_Protected_Body;
 
    ----------------------------------
@@ -1347,6 +1708,16 @@ package body Sem_Ch9 is
 
       End_Scope;
 
+      --  When a Lock_Free aspect forces the lock-free implementation, check N
+      --  meets all the lock-free restrictions. Otherwise,
+      --  Allows_Lock_Free_Implementation issue an error message.
+
+      if Uses_Lock_Free (Defining_Identifier (N)) then
+         if not Allows_Lock_Free_Implementation (N, Complain => True) then
+            return;
+         end if;
+      end if;
+
       --  Case of a completion of a private declaration
 
       if T /= Def_Id
@@ -1840,10 +2211,6 @@ package body Sem_Ch9 is
       --  disastrous result.
 
       Analyze_Protected_Type_Declaration (N);
-
-      if Has_Aspects (N) then
-         Analyze_Aspect_Specifications (N, Id);
-      end if;
    end Analyze_Single_Protected_Declaration;
 
    -------------------------------------
index 34e921f..5cb7916 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2010, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT 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- --
@@ -23,6 +23,7 @@
 --                                                                          --
 ------------------------------------------------------------------------------
 
+with Table;
 with Types; use Types;
 
 package Sem_Ch9  is
@@ -52,4 +53,35 @@ package Sem_Ch9  is
    procedure Analyze_Terminate_Alternative              (N : Node_Id);
    procedure Analyze_Timed_Entry_Call                   (N : Node_Id);
    procedure Analyze_Triggering_Alternative             (N : Node_Id);
+
+   ------------------------------
+   -- Lock Free Data Structure --
+   ------------------------------
+
+   --  A lock-free subprogram is a protected routine which references a unique
+   --  protected scalar component and does not contain statements that cause
+   --  side effects. Due to this restricted behavior, all references to shared
+   --  data from within the subprogram can be synchronized through the use of
+   --  atomic operations rather than relying on locks.
+
+   type Lock_Free_Subprogram is record
+      Sub_Body : Node_Id;
+      --  Reference to the body of a protected subprogram which meets the lock-
+      --  free requirements.
+
+      Comp_Id : Entity_Id;
+      --  Reference to the scalar component referenced from within Sub_Body
+   end record;
+
+   --  This table establishes a relation between a protected subprogram body
+   --  and a unique component it references. The table is used when building
+   --  the lock-free versions of a protected subprogram body.
+
+   package Lock_Free_Subprogram_Table is new Table.Table (
+     Table_Component_Type => Lock_Free_Subprogram,
+     Table_Index_Type     => Nat,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 5,
+     Table_Increment      => 5,
+     Table_Name           => "Lock_Free_Subprogram_Table");
 end Sem_Ch9;
index b0f8736..c402967 100644 (file)
@@ -142,6 +142,7 @@ package Snames is
    Name_Dimension                      : constant Name_Id := N + $;
    Name_Dimension_System               : constant Name_Id := N + $;
    Name_Dynamic_Predicate              : constant Name_Id := N + $;
+   Name_Lock_Free                      : constant Name_Id := N + $;
    Name_Post                           : constant Name_Id := N + $;
    Name_Pre                            : constant Name_Id := N + $;
    Name_Static_Predicate               : constant Name_Id := N + $;