This patch exports Make_Independent from GNAT.Threads. No simple test available.
Tested on x86_64-pc-linux-gnu, committed on trunk 2017-11-09 Bob Duff <d...@adacore.com> * libgnarl/g-thread.ads, libgnarl/g-thread.adb: (Make_Independent): Export this so users can use it without importing System.Tasking.Utilities. * libgnarl/s-tassta.adb (Vulnerable_Complete_Task): Relax assertion that fails when Make_Independent is called on a user task. * libgnarl/s-taskin.ads (Master_Of_Task): Avoid unusual capitalization style ((style) bad casing of "Master_of_Task").
Index: libgnat/g-altive.ads =================================================================== --- libgnat/g-altive.ads (revision 254579) +++ libgnat/g-altive.ads (revision 254580) @@ -668,18 +668,18 @@ -- type of A. The quad-word operations are only implemented by one -- Altivec primitive operation. That means that, if QW_Operation is a -- quad-word operation, we should have: --- QW_Operation (To_Type_of_A (B)) = QW_Operation (A) +-- QW_Operation (To_Type_Of_A (B)) = QW_Operation (A) -- That is true iff: --- To_Quad_Word (To_Type_of_A (B)) = To_Quad_Word (A) +-- To_Quad_Word (To_Type_Of_A (B)) = To_Quad_Word (A) -- As To_Quad_Word is a bijection. we have: --- To_Type_of_A (B) = A +-- To_Type_Of_A (B) = A -- resp. any combination of A, B, C: --- To_Type_of_A (C) = A --- To_Type_of_B (A) = B --- To_Type_of_C (B) = C +-- To_Type_Of_A (C) = A +-- To_Type_Of_B (A) = B +-- To_Type_Of_C (B) = C -- ... -- Making sure that the properties described above are verified by the Index: libgnat/s-spsufi.adb =================================================================== --- libgnat/s-spsufi.adb (revision 254579) +++ libgnat/s-spsufi.adb (revision 254580) @@ -71,9 +71,9 @@ -- requires that "The subpool no longer belongs to any pool" BEFORE -- calling Deallocate_Subpool. The actual dispatching call required is: -- - -- Deallocate_Subpool(Pool_of_Subpool(Subpool).all, Subpool); + -- Deallocate_Subpool(Pool_Of_Subpool(Subpool).all, Subpool); -- - -- but that can't be taken literally, because Pool_of_Subpool will + -- but that can't be taken literally, because Pool_Of_Subpool will -- return null. declare Index: libgnarl/s-tassta.adb =================================================================== --- libgnarl/s-tassta.adb (revision 254579) +++ libgnarl/s-tassta.adb (revision 254580) @@ -151,7 +151,7 @@ -- duplicate master ids. For example, suppose we have three nested -- task bodies T1,T2,T3. And suppose T1 also calls P which calls Q (and -- both P and Q are task masters). Q will have the same master id as - -- Master_of_Task of T3. Previous versions of this would abort T3 when + -- Master_Of_Task of T3. Previous versions of this would abort T3 when -- Q calls Complete_Master, which was completely wrong. begin @@ -160,7 +160,7 @@ P := C.Common.Parent; if P = Self_ID then - if C.Master_of_Task = Self_ID.Master_Within then + if C.Master_Of_Task = Self_ID.Master_Within then pragma Debug (Debug.Trace (Self_ID, "Aborting", 'X', C)); Utilities.Abort_One_Task (Self_ID, C); @@ -304,7 +304,7 @@ P.Alive_Count := P.Alive_Count + 1; if P.Common.State = Master_Completion_Sleep and then - C.Master_of_Task = P.Master_Within + C.Master_Of_Task = P.Master_Within then pragma Assert (Self_ID /= P); P.Common.Wait_Count := P.Common.Wait_Count + 1; @@ -498,7 +498,7 @@ -- has already awaited its dependent tasks. This raises Program_Error, -- by 4.8(10.3/2). See AI-280. Ignore this check for foreign threads. - if Self_ID.Master_of_Task /= Foreign_Task_Level + if Self_ID.Master_Of_Task /= Foreign_Task_Level and then Master > Self_ID.Master_Within then raise Program_Error with @@ -559,10 +559,10 @@ P := Self_ID; - if P.Master_of_Task <= Independent_Task_Level then + if P.Master_Of_Task <= Independent_Task_Level then P := Environment_Task; else - while P /= null and then P.Master_of_Task >= Master loop + while P /= null and then P.Master_Of_Task >= Master loop P := P.Common.Parent; end loop; end if; @@ -621,13 +621,13 @@ -- a regular library level task, otherwise the run-time will get -- confused when waiting for these tasks to terminate. - T.Master_of_Task := Library_Task_Level; + T.Master_Of_Task := Library_Task_Level; else - T.Master_of_Task := Master; + T.Master_Of_Task := Master; end if; - T.Master_Within := T.Master_of_Task + 1; + T.Master_Within := T.Master_Of_Task + 1; for L in T.Entry_Calls'Range loop T.Entry_Calls (L).Self := T; @@ -710,7 +710,7 @@ pragma Debug (Debug.Trace - (Self_ID, "Created task in " & T.Master_of_Task'Img, 'C', T)); + (Self_ID, "Created task in " & T.Master_Of_Task'Img, 'C', T)); end Create_Task; -------------------- @@ -988,11 +988,11 @@ Initialization.Defer_Abort_Nestable (Self_ID); - -- Loop through the From chain, changing their Master_of_Task fields, + -- Loop through the From chain, changing their Master_Of_Task fields, -- and to find the end of the chain. loop - C.Master_of_Task := New_Master; + C.Master_Of_Task := New_Master; exit when C.Common.Activation_Link = null; C := C.Common.Activation_Link; end loop; @@ -1094,7 +1094,7 @@ pragma Assert (Self_ID.Deferral_Level = 1); Debug.Master_Hook - (Self_ID, Self_ID.Common.Parent, Self_ID.Master_of_Task); + (Self_ID, Self_ID.Common.Parent, Self_ID.Master_Of_Task); if Use_Alternate_Stack then Self_ID.Common.Task_Alternate_Stack := Task_Alternate_Stack'Address; @@ -1307,7 +1307,7 @@ -- environment task), because they are implementation artifacts that -- should be invisible to Ada programs. - elsif Self_ID.Master_of_Task /= Independent_Task_Level then + elsif Self_ID.Master_Of_Task /= Independent_Task_Level then -- Look for a fall-back handler following the master relationship -- for the task. As specified in ARM C.7.3 par. 9/2, "the fall-back @@ -1377,7 +1377,7 @@ procedure Terminate_Task (Self_ID : Task_Id) is Environment_Task : constant Task_Id := STPO.Environment_Task; - Master_of_Task : Integer; + Master_Of_Task : Integer; Deallocate : Boolean; begin @@ -1397,12 +1397,12 @@ Lock_RTS; end if; - Master_of_Task := Self_ID.Master_of_Task; + Master_Of_Task := Self_ID.Master_Of_Task; -- Check if the current task is an independent task If so, decrement -- the Independent_Task_Count value. - if Master_of_Task = Independent_Task_Level then + if Master_Of_Task = Independent_Task_Level then if Single_Lock then Utilities.Independent_Task_Count := Utilities.Independent_Task_Count - 1; @@ -1439,7 +1439,7 @@ Free_Task (Self_ID); end if; - if Master_of_Task > 0 then + if Master_Of_Task > 0 then STPO.Exit_Task; end if; end Terminate_Task; @@ -1606,11 +1606,11 @@ C := All_Tasks_List; while C /= null loop - if C.Common.Activator = Self_ID and then C.Master_of_Task = CM then + if C.Common.Activator = Self_ID and then C.Master_Of_Task = CM then return False; end if; - if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then + if C.Common.Parent = Self_ID and then C.Master_Of_Task = CM then Write_Lock (C); if C.Common.State = Unactivated then @@ -1662,9 +1662,9 @@ -- Terminate unactivated (never-to-be activated) tasks - if C.Common.Activator = Self_ID and then C.Master_of_Task = CM then + if C.Common.Activator = Self_ID and then C.Master_Of_Task = CM then - -- Usually, C.Common.Activator = Self_ID implies C.Master_of_Task + -- Usually, C.Common.Activator = Self_ID implies C.Master_Of_Task -- = CM. The only case where C is pending activation by this -- task, but the master of C is not CM is in Ada 2005, when C is -- part of a return object of a build-in-place function. @@ -1681,7 +1681,7 @@ -- Count it if directly dependent on this master - if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then + if C.Common.Parent = Self_ID and then C.Master_Of_Task = CM then Write_Lock (C); if C.Awake_Count /= 0 then @@ -1781,7 +1781,7 @@ C := All_Tasks_List; while C /= null loop - if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then + if C.Common.Parent = Self_ID and then C.Master_Of_Task = CM then Write_Lock (C); pragma Assert (C.Awake_Count = 0); @@ -1840,7 +1840,7 @@ -- while the task calls Free_Task itself, in Terminate_Task. if C.Common.Parent = Self_ID - and then C.Master_of_Task >= CM + and then C.Master_Of_Task >= CM and then not C.Free_On_Termination then if P /= null then @@ -1912,7 +1912,7 @@ if (T.Common.Parent /= null and then T.Common.Parent.Common.Parent /= null) - or else T.Master_of_Task > Library_Task_Level + or else T.Master_Of_Task > Library_Task_Level then Initialization.Task_Lock (Self_ID); @@ -1977,7 +1977,7 @@ pragma Assert (Self_ID = Self); pragma Assert (Self_ID.Master_Within in - Self_ID.Master_of_Task + 1 .. Self_ID.Master_of_Task + 3); + Self_ID.Master_Of_Task .. Self_ID.Master_Of_Task + 3); pragma Assert (Self_ID.Common.Wait_Count = 0); pragma Assert (Self_ID.Open_Accepts = null); pragma Assert (Self_ID.ATC_Nesting_Level = 1); @@ -2007,10 +2007,10 @@ Unlock_RTS; end if; - -- If Self_ID.Master_Within = Self_ID.Master_of_Task + 2 we may have + -- If Self_ID.Master_Within = Self_ID.Master_Of_Task + 2 we may have -- dependent tasks for which we need to wait. Otherwise we just exit. - if Self_ID.Master_Within = Self_ID.Master_of_Task + 2 then + if Self_ID.Master_Within = Self_ID.Master_Of_Task + 2 then Vulnerable_Complete_Master (Self_ID); end if; end Vulnerable_Complete_Task; Index: libgnarl/s-tassta.ads =================================================================== --- libgnarl/s-tassta.ads (revision 254579) +++ libgnarl/s-tassta.ads (revision 254580) @@ -285,7 +285,7 @@ (From, To : Activation_Chain_Access; New_Master : Master_ID); -- Compiler interface only. Do not call from within the RTS. - -- Move all tasks on From list to To list, and change their Master_of_Task + -- Move all tasks on From list to To list, and change their Master_Of_Task -- to be New_Master. This is used to implement build-in-place function -- returns. Tasks that are part of the return object are initially placed -- on an activation chain local to the return statement, and their master Index: libgnarl/s-tasren.adb =================================================================== --- libgnarl/s-tasren.adb (revision 254579) +++ libgnarl/s-tasren.adb (revision 254580) @@ -1138,7 +1138,7 @@ Parent.Awake_Count := Parent.Awake_Count + 1; if Parent.Common.State = Master_Completion_Sleep - and then Acceptor.Master_of_Task = Parent.Master_Within + and then Acceptor.Master_Of_Task = Parent.Master_Within then Parent.Common.Wait_Count := Parent.Common.Wait_Count + 1; Index: libgnarl/s-tasuti.adb =================================================================== --- libgnarl/s-tasuti.adb (revision 254579) +++ libgnarl/s-tasuti.adb (revision 254580) @@ -258,7 +258,7 @@ pragma Assert (Parent = Environment_Task); - Self_Id.Master_of_Task := Independent_Task_Level; + Self_Id.Master_Of_Task := Independent_Task_Level; -- Update Independent_Task_Count that is needed for the GLADE -- termination rule. See also pending update in @@ -396,7 +396,7 @@ end loop; if P.Common.State = Master_Phase_2_Sleep - and then C.Master_of_Task = P.Master_Within + and then C.Master_Of_Task = P.Master_Within then pragma Assert (P.Common.Wait_Count > 0); P.Common.Wait_Count := P.Common.Wait_Count - 1; @@ -462,7 +462,7 @@ -- P has non-passive dependents if P.Common.State = Master_Completion_Sleep - and then C.Master_of_Task = P.Master_Within + and then C.Master_Of_Task = P.Master_Within then pragma Debug (Debug.Trace Index: libgnarl/s-tporft.adb =================================================================== --- libgnarl/s-tporft.adb (revision 254579) +++ libgnarl/s-tporft.adb (revision 254580) @@ -70,8 +70,8 @@ Unlock_RTS; pragma Assert (Succeeded); - Self_Id.Master_of_Task := 0; - Self_Id.Master_Within := Self_Id.Master_of_Task + 1; + Self_Id.Master_Of_Task := 0; + Self_Id.Master_Within := Self_Id.Master_Of_Task + 1; for L in Self_Id.Entry_Calls'Range loop Self_Id.Entry_Calls (L).Self := Self_Id; Index: libgnarl/s-tasuti.ads =================================================================== --- libgnarl/s-tasuti.ads (revision 254579) +++ libgnarl/s-tasuti.ads (revision 254580) @@ -54,9 +54,9 @@ -- -- This is a dangerous operation, and should never be used on nested tasks -- or tasks that depend on any objects that might be finalized earlier than - -- the termination of the environment task. It is for internal use by the - -- GNARL, to prevent such internal server tasks from preventing a partition - -- from terminating. + -- the termination of the environment task. It is primarily for internal + -- use by the GNARL, to prevent such internal server tasks from preventing + -- a partition from terminating. -- -- Also note that the run time assumes that the parent of an independent -- task is the environment task. If this is not the case, Make_Independent Index: libgnarl/g-thread.adb =================================================================== --- libgnarl/g-thread.adb (revision 254579) +++ libgnarl/g-thread.adb (revision 254580) @@ -33,6 +33,7 @@ with System.Task_Primitives.Operations; with System.Tasking; with System.Tasking.Stages; use System.Tasking.Stages; +with System.Tasking.Utilities; with System.OS_Interface; use System.OS_Interface; with System.Soft_Links; use System.Soft_Links; with Ada.Unchecked_Conversion; @@ -172,6 +173,15 @@ Thr.all := Task_Primitives.Operations.Get_Thread_Id (To_Id (Id)); end Get_Thread; + ---------------------- + -- Make_Independent -- + ---------------------- + + function Make_Independent return Boolean is + begin + return System.Tasking.Utilities.Make_Independent; + end Make_Independent; + ---------------- -- To_Task_Id -- ---------------- Index: libgnarl/s-taskin.ads =================================================================== --- libgnarl/s-taskin.ads (revision 254579) +++ libgnarl/s-taskin.ads (revision 254580) @@ -982,7 +982,7 @@ -- updated it itself using information from a suspended Caller, or -- after Caller has updated it and awakened Self. - Master_of_Task : Master_Level; + Master_Of_Task : Master_Level; -- The task executing the master of this task, and the ID of this task's -- master (unique only among masters currently active within Parent). -- Index: libgnarl/g-thread.ads =================================================================== --- libgnarl/g-thread.ads (revision 254579) +++ libgnarl/g-thread.ads (revision 254580) @@ -146,4 +146,15 @@ -- Given a low level Id, as returned by Create_Thread, return a Task_Id, -- so that operations in Ada.Task_Identification can be used. + function Make_Independent return Boolean; + -- If a procedure loads a shared library containing tasks, and that + -- procedure is considered to be a master by the compiler (because it + -- contains tasks or class-wide objects that might contain tasks), + -- then the tasks in the shared library need to call Make_Independent + -- because otherwise they will depend on the procedure that loaded the + -- shared library. + -- + -- See System.Tasking.Utilities.Make_Independent in s-tasuti.ads for + -- further documentation. + end GNAT.Threads; Index: libgnarl/s-tasini.adb =================================================================== --- libgnarl/s-tasini.adb (revision 254579) +++ libgnarl/s-tasini.adb (revision 254580) @@ -325,8 +325,8 @@ -- of the environment task. Self_Id := Environment_Task; - Self_Id.Master_of_Task := Environment_Task_Level; - Self_Id.Master_Within := Self_Id.Master_of_Task + 1; + Self_Id.Master_Of_Task := Environment_Task_Level; + Self_Id.Master_Within := Self_Id.Master_Of_Task + 1; for L in Self_Id.Entry_Calls'Range loop Self_Id.Entry_Calls (L).Self := Self_Id; Index: exp_util.adb =================================================================== --- exp_util.adb (revision 254579) +++ exp_util.adb (revision 254580) @@ -4991,7 +4991,7 @@ -- is transformed into - -- Val : Constrained_Subtype_of_T := Maybe_Modified_Expr; + -- Val : Constrained_Subtype_Of_T := Maybe_Modified_Expr; -- -- Here are the main cases : --