comparison gcc/ada/libgnarl/s-tassta.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
4 -- -- 4 -- --
5 -- S Y S T E M . T A S K I N G . S T A G E S -- 5 -- S Y S T E M . T A S K I N G . S T A G E S --
6 -- -- 6 -- --
7 -- B o d y -- 7 -- B o d y --
8 -- -- 8 -- --
9 -- Copyright (C) 1992-2017, Free Software Foundation, Inc. -- 9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. --
10 -- -- 10 -- --
11 -- GNARL is free software; you can redistribute it and/or modify it under -- 11 -- GNARL is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- -- 12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- -- 13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
149 -- need to worry about them here. In fact, it would be wrong to abort 149 -- need to worry about them here. In fact, it would be wrong to abort
150 -- indirect dependents here, because we can't distinguish between 150 -- indirect dependents here, because we can't distinguish between
151 -- duplicate master ids. For example, suppose we have three nested 151 -- duplicate master ids. For example, suppose we have three nested
152 -- task bodies T1,T2,T3. And suppose T1 also calls P which calls Q (and 152 -- task bodies T1,T2,T3. And suppose T1 also calls P which calls Q (and
153 -- both P and Q are task masters). Q will have the same master id as 153 -- both P and Q are task masters). Q will have the same master id as
154 -- Master_of_Task of T3. Previous versions of this would abort T3 when 154 -- Master_Of_Task of T3. Previous versions of this would abort T3 when
155 -- Q calls Complete_Master, which was completely wrong. 155 -- Q calls Complete_Master, which was completely wrong.
156 156
157 begin 157 begin
158 C := All_Tasks_List; 158 C := All_Tasks_List;
159 while C /= null loop 159 while C /= null loop
160 P := C.Common.Parent; 160 P := C.Common.Parent;
161 161
162 if P = Self_ID then 162 if P = Self_ID then
163 if C.Master_of_Task = Self_ID.Master_Within then 163 if C.Master_Of_Task = Self_ID.Master_Within then
164 pragma Debug 164 pragma Debug
165 (Debug.Trace (Self_ID, "Aborting", 'X', C)); 165 (Debug.Trace (Self_ID, "Aborting", 'X', C));
166 Utilities.Abort_One_Task (Self_ID, C); 166 Utilities.Abort_One_Task (Self_ID, C);
167 C.Dependents_Aborted := True; 167 C.Dependents_Aborted := True;
168 end if; 168 end if;
302 C.Alive_Count := 1; 302 C.Alive_Count := 1;
303 P.Awake_Count := P.Awake_Count + 1; 303 P.Awake_Count := P.Awake_Count + 1;
304 P.Alive_Count := P.Alive_Count + 1; 304 P.Alive_Count := P.Alive_Count + 1;
305 305
306 if P.Common.State = Master_Completion_Sleep and then 306 if P.Common.State = Master_Completion_Sleep and then
307 C.Master_of_Task = P.Master_Within 307 C.Master_Of_Task = P.Master_Within
308 then 308 then
309 pragma Assert (Self_ID /= P); 309 pragma Assert (Self_ID /= P);
310 P.Common.Wait_Count := P.Common.Wait_Count + 1; 310 P.Common.Wait_Count := P.Common.Wait_Count + 1;
311 end if; 311 end if;
312 312
496 begin 496 begin
497 -- If Master is greater than the current master, it means that Master 497 -- If Master is greater than the current master, it means that Master
498 -- has already awaited its dependent tasks. This raises Program_Error, 498 -- has already awaited its dependent tasks. This raises Program_Error,
499 -- by 4.8(10.3/2). See AI-280. Ignore this check for foreign threads. 499 -- by 4.8(10.3/2). See AI-280. Ignore this check for foreign threads.
500 500
501 if Self_ID.Master_of_Task /= Foreign_Task_Level 501 if Self_ID.Master_Of_Task /= Foreign_Task_Level
502 and then Master > Self_ID.Master_Within 502 and then Master > Self_ID.Master_Within
503 then 503 then
504 raise Program_Error with 504 raise Program_Error with
505 "create task after awaiting termination"; 505 "create task after awaiting termination";
506 end if; 506 end if;
557 -- access type is at library level, so the parent of the Server_Task 557 -- access type is at library level, so the parent of the Server_Task
558 -- is Environment_Task. 558 -- is Environment_Task.
559 559
560 P := Self_ID; 560 P := Self_ID;
561 561
562 if P.Master_of_Task <= Independent_Task_Level then 562 if P.Master_Of_Task <= Independent_Task_Level then
563 P := Environment_Task; 563 P := Environment_Task;
564 else 564 else
565 while P /= null and then P.Master_of_Task >= Master loop 565 while P /= null and then P.Master_Of_Task >= Master loop
566 P := P.Common.Parent; 566 P := P.Common.Parent;
567 end loop; 567 end loop;
568 end if; 568 end if;
569 569
570 Initialization.Defer_Abort_Nestable (Self_ID); 570 Initialization.Defer_Abort_Nestable (Self_ID);
619 -- This should not happen, except when a foreign task creates non 619 -- This should not happen, except when a foreign task creates non
620 -- library-level Ada tasks. In this case, we pretend the master is 620 -- library-level Ada tasks. In this case, we pretend the master is
621 -- a regular library level task, otherwise the run-time will get 621 -- a regular library level task, otherwise the run-time will get
622 -- confused when waiting for these tasks to terminate. 622 -- confused when waiting for these tasks to terminate.
623 623
624 T.Master_of_Task := Library_Task_Level; 624 T.Master_Of_Task := Library_Task_Level;
625 625
626 else 626 else
627 T.Master_of_Task := Master; 627 T.Master_Of_Task := Master;
628 end if; 628 end if;
629 629
630 T.Master_Within := T.Master_of_Task + 1; 630 T.Master_Within := T.Master_Of_Task + 1;
631 631
632 for L in T.Entry_Calls'Range loop 632 for L in T.Entry_Calls'Range loop
633 T.Entry_Calls (L).Self := T; 633 T.Entry_Calls (L).Self := T;
634 T.Entry_Calls (L).Level := L; 634 T.Entry_Calls (L).Level := L;
635 end loop; 635 end loop;
653 end loop; 653 end loop;
654 654
655 T.Common.Task_Image_Len := Len; 655 T.Common.Task_Image_Len := Len;
656 end if; 656 end if;
657 657
658 -- Note: we used to have code here to initialize T.Commmon.Domain, but 658 -- Note: we used to have code here to initialize T.Common.Domain, but
659 -- that is not needed, since this is initialized in System.Tasking. 659 -- that is not needed, since this is initialized in System.Tasking.
660 660
661 Unlock (Self_ID); 661 Unlock (Self_ID);
662 Unlock_RTS; 662 Unlock_RTS;
663 663
708 Created_Task := T; 708 Created_Task := T;
709 Initialization.Undefer_Abort_Nestable (Self_ID); 709 Initialization.Undefer_Abort_Nestable (Self_ID);
710 710
711 pragma Debug 711 pragma Debug
712 (Debug.Trace 712 (Debug.Trace
713 (Self_ID, "Created task in " & T.Master_of_Task'Img, 'C', T)); 713 (Self_ID, "Created task in " & T.Master_Of_Task'Img, 'C', T));
714 end Create_Task; 714 end Create_Task;
715 715
716 -------------------- 716 --------------------
717 -- Current_Master -- 717 -- Current_Master --
718 -------------------- 718 --------------------
986 return; 986 return;
987 end if; 987 end if;
988 988
989 Initialization.Defer_Abort_Nestable (Self_ID); 989 Initialization.Defer_Abort_Nestable (Self_ID);
990 990
991 -- Loop through the From chain, changing their Master_of_Task fields, 991 -- Loop through the From chain, changing their Master_Of_Task fields,
992 -- and to find the end of the chain. 992 -- and to find the end of the chain.
993 993
994 loop 994 loop
995 C.Master_of_Task := New_Master; 995 C.Master_Of_Task := New_Master;
996 exit when C.Common.Activation_Link = null; 996 exit when C.Common.Activation_Link = null;
997 C := C.Common.Activation_Link; 997 C := C.Common.Activation_Link;
998 end loop; 998 end loop;
999 999
1000 -- Hook From in at the start of To 1000 -- Hook From in at the start of To
1092 1092
1093 begin 1093 begin
1094 pragma Assert (Self_ID.Deferral_Level = 1); 1094 pragma Assert (Self_ID.Deferral_Level = 1);
1095 1095
1096 Debug.Master_Hook 1096 Debug.Master_Hook
1097 (Self_ID, Self_ID.Common.Parent, Self_ID.Master_of_Task); 1097 (Self_ID, Self_ID.Common.Parent, Self_ID.Master_Of_Task);
1098 1098
1099 if Use_Alternate_Stack then 1099 if Use_Alternate_Stack then
1100 Self_ID.Common.Task_Alternate_Stack := Task_Alternate_Stack'Address; 1100 Self_ID.Common.Task_Alternate_Stack := Task_Alternate_Stack'Address;
1101 end if; 1101 end if;
1102 1102
1305 1305
1306 -- Independent tasks should not call the Fall_Back_Handler (of the 1306 -- Independent tasks should not call the Fall_Back_Handler (of the
1307 -- environment task), because they are implementation artifacts that 1307 -- environment task), because they are implementation artifacts that
1308 -- should be invisible to Ada programs. 1308 -- should be invisible to Ada programs.
1309 1309
1310 elsif Self_ID.Master_of_Task /= Independent_Task_Level then 1310 elsif Self_ID.Master_Of_Task /= Independent_Task_Level then
1311 1311
1312 -- Look for a fall-back handler following the master relationship 1312 -- Look for a fall-back handler following the master relationship
1313 -- for the task. As specified in ARM C.7.3 par. 9/2, "the fall-back 1313 -- for the task. As specified in ARM C.7.3 par. 9/2, "the fall-back
1314 -- handler applies only to the dependent tasks of the task". Hence, 1314 -- handler applies only to the dependent tasks of the task". Hence,
1315 -- if the terminating tasks (Self_ID) had a fall-back handler, it 1315 -- if the terminating tasks (Self_ID) had a fall-back handler, it
1375 -- the data of the new task that reused the ATCB. To solve this problem, we 1375 -- the data of the new task that reused the ATCB. To solve this problem, we
1376 -- introduced the new operation Final_Task_Unlock. 1376 -- introduced the new operation Final_Task_Unlock.
1377 1377
1378 procedure Terminate_Task (Self_ID : Task_Id) is 1378 procedure Terminate_Task (Self_ID : Task_Id) is
1379 Environment_Task : constant Task_Id := STPO.Environment_Task; 1379 Environment_Task : constant Task_Id := STPO.Environment_Task;
1380 Master_of_Task : Integer; 1380 Master_Of_Task : Integer;
1381 Deallocate : Boolean; 1381 Deallocate : Boolean;
1382 1382
1383 begin 1383 begin
1384 Debug.Task_Termination_Hook; 1384 Debug.Task_Termination_Hook;
1385 1385
1395 1395
1396 if Single_Lock then 1396 if Single_Lock then
1397 Lock_RTS; 1397 Lock_RTS;
1398 end if; 1398 end if;
1399 1399
1400 Master_of_Task := Self_ID.Master_of_Task; 1400 Master_Of_Task := Self_ID.Master_Of_Task;
1401 1401
1402 -- Check if the current task is an independent task If so, decrement 1402 -- Check if the current task is an independent task If so, decrement
1403 -- the Independent_Task_Count value. 1403 -- the Independent_Task_Count value.
1404 1404
1405 if Master_of_Task = Independent_Task_Level then 1405 if Master_Of_Task = Independent_Task_Level then
1406 if Single_Lock then 1406 if Single_Lock then
1407 Utilities.Independent_Task_Count := 1407 Utilities.Independent_Task_Count :=
1408 Utilities.Independent_Task_Count - 1; 1408 Utilities.Independent_Task_Count - 1;
1409 1409
1410 else 1410 else
1437 1437
1438 if Deallocate then 1438 if Deallocate then
1439 Free_Task (Self_ID); 1439 Free_Task (Self_ID);
1440 end if; 1440 end if;
1441 1441
1442 if Master_of_Task > 0 then 1442 if Master_Of_Task > 0 then
1443 STPO.Exit_Task; 1443 STPO.Exit_Task;
1444 end if; 1444 end if;
1445 end Terminate_Task; 1445 end Terminate_Task;
1446 1446
1447 ---------------- 1447 ----------------
1604 1604
1605 Write_Lock (Self_ID); 1605 Write_Lock (Self_ID);
1606 1606
1607 C := All_Tasks_List; 1607 C := All_Tasks_List;
1608 while C /= null loop 1608 while C /= null loop
1609 if C.Common.Activator = Self_ID and then C.Master_of_Task = CM then 1609 if C.Common.Activator = Self_ID and then C.Master_Of_Task = CM then
1610 return False; 1610 return False;
1611 end if; 1611 end if;
1612 1612
1613 if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then 1613 if C.Common.Parent = Self_ID and then C.Master_Of_Task = CM then
1614 Write_Lock (C); 1614 Write_Lock (C);
1615 1615
1616 if C.Common.State = Unactivated then 1616 if C.Common.State = Unactivated then
1617 return False; 1617 return False;
1618 end if; 1618 end if;
1660 C := All_Tasks_List; 1660 C := All_Tasks_List;
1661 while C /= null loop 1661 while C /= null loop
1662 1662
1663 -- Terminate unactivated (never-to-be activated) tasks 1663 -- Terminate unactivated (never-to-be activated) tasks
1664 1664
1665 if C.Common.Activator = Self_ID and then C.Master_of_Task = CM then 1665 if C.Common.Activator = Self_ID and then C.Master_Of_Task = CM then
1666 1666
1667 -- Usually, C.Common.Activator = Self_ID implies C.Master_of_Task 1667 -- Usually, C.Common.Activator = Self_ID implies C.Master_Of_Task
1668 -- = CM. The only case where C is pending activation by this 1668 -- = CM. The only case where C is pending activation by this
1669 -- task, but the master of C is not CM is in Ada 2005, when C is 1669 -- task, but the master of C is not CM is in Ada 2005, when C is
1670 -- part of a return object of a build-in-place function. 1670 -- part of a return object of a build-in-place function.
1671 1671
1672 pragma Assert (C.Common.State = Unactivated); 1672 pragma Assert (C.Common.State = Unactivated);
1679 Unlock (C); 1679 Unlock (C);
1680 end if; 1680 end if;
1681 1681
1682 -- Count it if directly dependent on this master 1682 -- Count it if directly dependent on this master
1683 1683
1684 if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then 1684 if C.Common.Parent = Self_ID and then C.Master_Of_Task = CM then
1685 Write_Lock (C); 1685 Write_Lock (C);
1686 1686
1687 if C.Awake_Count /= 0 then 1687 if C.Awake_Count /= 0 then
1688 Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1; 1688 Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1;
1689 end if; 1689 end if;
1779 1779
1780 Write_Lock (Self_ID); 1780 Write_Lock (Self_ID);
1781 1781
1782 C := All_Tasks_List; 1782 C := All_Tasks_List;
1783 while C /= null loop 1783 while C /= null loop
1784 if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then 1784 if C.Common.Parent = Self_ID and then C.Master_Of_Task = CM then
1785 Write_Lock (C); 1785 Write_Lock (C);
1786 1786
1787 pragma Assert (C.Awake_Count = 0); 1787 pragma Assert (C.Awake_Count = 0);
1788 1788
1789 if C.Alive_Count > 0 then 1789 if C.Alive_Count > 0 then
1838 -- task free itself if not already done, otherwise we risk a race 1838 -- task free itself if not already done, otherwise we risk a race
1839 -- condition where Vulnerable_Free_Task is called in the loop below, 1839 -- condition where Vulnerable_Free_Task is called in the loop below,
1840 -- while the task calls Free_Task itself, in Terminate_Task. 1840 -- while the task calls Free_Task itself, in Terminate_Task.
1841 1841
1842 if C.Common.Parent = Self_ID 1842 if C.Common.Parent = Self_ID
1843 and then C.Master_of_Task >= CM 1843 and then C.Master_Of_Task >= CM
1844 and then not C.Free_On_Termination 1844 and then not C.Free_On_Termination
1845 then 1845 then
1846 if P /= null then 1846 if P /= null then
1847 P.Common.All_Tasks_Link := C.Common.All_Tasks_Link; 1847 P.Common.All_Tasks_Link := C.Common.All_Tasks_Link;
1848 else 1848 else
1910 end; 1910 end;
1911 end if; 1911 end if;
1912 1912
1913 if (T.Common.Parent /= null 1913 if (T.Common.Parent /= null
1914 and then T.Common.Parent.Common.Parent /= null) 1914 and then T.Common.Parent.Common.Parent /= null)
1915 or else T.Master_of_Task > Library_Task_Level 1915 or else T.Master_Of_Task > Library_Task_Level
1916 then 1916 then
1917 Initialization.Task_Lock (Self_ID); 1917 Initialization.Task_Lock (Self_ID);
1918 1918
1919 -- If Sec_Stack_Ptr is not null, it means that Destroy_TSD 1919 -- If Sec_Stack_Ptr is not null, it means that Destroy_TSD
1920 -- has not been called yet (case of an unactivated task). 1920 -- has not been called yet (case of an unactivated task).
1975 (Self_ID.Deferral_Level > 0 1975 (Self_ID.Deferral_Level > 0
1976 or else not System.Restrictions.Abort_Allowed); 1976 or else not System.Restrictions.Abort_Allowed);
1977 pragma Assert (Self_ID = Self); 1977 pragma Assert (Self_ID = Self);
1978 pragma Assert 1978 pragma Assert
1979 (Self_ID.Master_Within in 1979 (Self_ID.Master_Within in
1980 Self_ID.Master_of_Task + 1 .. Self_ID.Master_of_Task + 3); 1980 Self_ID.Master_Of_Task .. Self_ID.Master_Of_Task + 3);
1981 pragma Assert (Self_ID.Common.Wait_Count = 0); 1981 pragma Assert (Self_ID.Common.Wait_Count = 0);
1982 pragma Assert (Self_ID.Open_Accepts = null); 1982 pragma Assert (Self_ID.Open_Accepts = null);
1983 pragma Assert (Self_ID.ATC_Nesting_Level = 1); 1983 pragma Assert (Self_ID.ATC_Nesting_Level = 1);
1984 1984
1985 pragma Debug (Debug.Trace (Self_ID, "V_Complete_Task", 'C')); 1985 pragma Debug (Debug.Trace (Self_ID, "V_Complete_Task", 'C'));
2005 2005
2006 if Single_Lock then 2006 if Single_Lock then
2007 Unlock_RTS; 2007 Unlock_RTS;
2008 end if; 2008 end if;
2009 2009
2010 -- If Self_ID.Master_Within = Self_ID.Master_of_Task + 2 we may have 2010 -- If Self_ID.Master_Within = Self_ID.Master_Of_Task + 2 we may have
2011 -- dependent tasks for which we need to wait. Otherwise we just exit. 2011 -- dependent tasks for which we need to wait. Otherwise we just exit.
2012 2012
2013 if Self_ID.Master_Within = Self_ID.Master_of_Task + 2 then 2013 if Self_ID.Master_Within = Self_ID.Master_Of_Task + 2 then
2014 Vulnerable_Complete_Master (Self_ID); 2014 Vulnerable_Complete_Master (Self_ID);
2015 end if; 2015 end if;
2016 end Vulnerable_Complete_Task; 2016 end Vulnerable_Complete_Task;
2017 2017
2018 -------------------------- 2018 --------------------------