summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-15 09:29:46 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-15 09:29:46 +0000
commit7413d80df0db9a5082f700e04318b9d639f10b5c (patch)
tree4a1bddd2f4929ab05a86932cff22860124f1fb69
parentf74ffaae4fc78497c6bf3edb8c5ea7d3ae90d8cb (diff)
downloadgcc-7413d80df0db9a5082f700e04318b9d639f10b5c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187505 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ada/ChangeLog41
-rw-r--r--gcc/ada/aspects.adb31
-rw-r--r--gcc/ada/aspects.ads9
-rw-r--r--gcc/ada/einfo.adb24
-rw-r--r--gcc/ada/einfo.ads11
-rw-r--r--gcc/ada/exp_ch7.adb1
-rw-r--r--gcc/ada/exp_ch7.ads4
-rw-r--r--gcc/ada/exp_ch9.adb890
-rw-r--r--gcc/ada/g-comlin.adb10
-rw-r--r--gcc/ada/g-comlin.ads92
-rw-r--r--gcc/ada/rtsfind.ads4
-rw-r--r--gcc/ada/s-atopri.ads7
-rw-r--r--gcc/ada/sem_ch13.adb36
-rw-r--r--gcc/ada/sem_ch9.adb375
-rw-r--r--gcc/ada/sem_ch9.ads34
-rw-r--r--gcc/ada/snames.ads-tmpl1
16 files changed, 942 insertions, 628 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index e1c40a95843..9f31c7543f9 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -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
diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb
index b155a08714f..86e70917d16 100644
--- a/gcc/ada/aspects.adb
+++ b/gcc/ada/aspects.adb
@@ -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,
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 781651feeb9..523412bd0e8 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -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,
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index 0f597a1f941..b7ffe58fd59 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -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);
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index d07be8124cd..01037a5c005 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -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);
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index dfd0a067b15..238469ce79c 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -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;
diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads
index 8ea71916e26..244936c7e16 100644
--- a/gcc/ada/exp_ch7.ads
+++ b/gcc/ada/exp_ch7.ads
@@ -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 --
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 9d21af2accc..1f9f45890f2 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -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
diff --git a/gcc/ada/g-comlin.adb b/gcc/ada/g-comlin.adb
index 8615b024f23..723ff120ff6 100644
--- a/gcc/ada/g-comlin.adb
+++ b/gcc/ada/g-comlin.adb
@@ -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));
diff --git a/gcc/ada/g-comlin.ads b/gcc/ada/g-comlin.ads
index c3479bbfb42..c4b290e5567 100644
--- a/gcc/ada/g-comlin.ads
+++ b/gcc/ada/g-comlin.ads
@@ -181,16 +181,20 @@
-- ...
-- 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
@@ -203,13 +207,13 @@
-- 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
@@ -263,8 +267,8 @@
-- 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
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index e02f575d7d5..a01505c709c 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -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,
diff --git a/gcc/ada/s-atopri.ads b/gcc/ada/s-atopri.ads
index c8c75f2ff72..3b87eb28125 100644
--- a/gcc/ada/s-atopri.ads
+++ b/gcc/ada/s-atopri.ads
@@ -29,7 +29,10 @@
-- --
------------------------------------------------------------------------------
--- ??? 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;
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 3c3cce275e7..c8b987e93cd 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -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
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index 72ce1c0e9d1..a91f494152f 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -23,13 +23,16 @@
-- --
------------------------------------------------------------------------------
+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;
-------------------------------------
diff --git a/gcc/ada/sem_ch9.ads b/gcc/ada/sem_ch9.ads
index 34e921f69b6..5cb7916974a 100644
--- a/gcc/ada/sem_ch9.ads
+++ b/gcc/ada/sem_ch9.ads
@@ -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;
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index b0f8736ff23..c402967e733 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -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 + $;