Mercurial > hg > CbC > CbC_gcc
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 -------------------------- |