1------------------------------------------------------------------------------ 2-- -- 3-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS -- 4-- -- 5-- S Y S T E M . T A S K I N G . I N I T I A L I Z A T I O N -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 1992-2013, Free Software Foundation, Inc. -- 10-- -- 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- -- 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- -- 15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 16-- or FITNESS FOR A PARTICULAR PURPOSE. -- 17-- -- 18-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 21-- -- 22-- You should have received a copy of the GNU General Public License and -- 23-- a copy of the GCC Runtime Library Exception along with this program; -- 24-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 25-- <http://www.gnu.org/licenses/>. -- 26-- -- 27-- GNARL was developed by the GNARL team at Florida State University. -- 28-- Extensive contributions were provided by Ada Core Technologies, Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 32pragma Style_Checks (All_Checks); 33-- Turn off subprogram alpha ordering check, since we group soft link bodies 34-- and dummy soft link bodies together separately in this unit. 35 36pragma Polling (Off); 37-- Turn polling off for this package. We don't need polling during any of the 38-- routines in this package, and more to the point, if we try to poll it can 39-- cause infinite loops. 40 41with Ada.Exceptions; 42 43with System.Task_Primitives; 44with System.Task_Primitives.Operations; 45with System.Soft_Links; 46with System.Soft_Links.Tasking; 47with System.Tasking.Debug; 48with System.Parameters; 49 50package body System.Tasking.Initialization is 51 52 package STPO renames System.Task_Primitives.Operations; 53 package SSL renames System.Soft_Links; 54 package AE renames Ada.Exceptions; 55 56 use Parameters; 57 use Task_Primitives.Operations; 58 59 Global_Task_Lock : aliased System.Task_Primitives.RTS_Lock; 60 -- This is a global lock; it is used to execute in mutual exclusion from 61 -- all other tasks. It is only used by Task_Lock, Task_Unlock, and 62 -- Final_Task_Unlock. 63 64 ---------------------------------------------------------------------- 65 -- Tasking versions of some services needed by non-tasking programs -- 66 ---------------------------------------------------------------------- 67 68 procedure Abort_Defer; 69 -- NON-INLINE versions without Self_ID for soft links 70 71 procedure Abort_Undefer; 72 -- NON-INLINE versions without Self_ID for soft links 73 74 procedure Task_Lock; 75 -- Locks out other tasks. Preceding a section of code by Task_Lock and 76 -- following it by Task_Unlock creates a critical region. This is used 77 -- for ensuring that a region of non-tasking code (such as code used to 78 -- allocate memory) is tasking safe. Note that it is valid for calls to 79 -- Task_Lock/Task_Unlock to be nested, and this must work properly, i.e. 80 -- only the corresponding outer level Task_Unlock will actually unlock. 81 82 procedure Task_Unlock; 83 -- Releases lock previously set by call to Task_Lock. In the nested case, 84 -- all nested locks must be released before other tasks competing for the 85 -- tasking lock are released. 86 87 function Get_Current_Excep return SSL.EOA; 88 -- Task-safe version of SSL.Get_Current_Excep 89 90 procedure Update_Exception 91 (X : AE.Exception_Occurrence := SSL.Current_Target_Exception); 92 -- Handle exception setting and check for pending actions 93 94 function Task_Name return String; 95 -- Returns current task's name 96 97 ------------------------ 98 -- Local Subprograms -- 99 ------------------------ 100 101 ---------------------------- 102 -- Tasking Initialization -- 103 ---------------------------- 104 105 procedure Init_RTS; 106 -- This procedure completes the initialization of the GNARL. The first part 107 -- of the initialization is done in the body of System.Tasking. It consists 108 -- of initializing global locks, and installing tasking versions of certain 109 -- operations used by the compiler. Init_RTS is called during elaboration. 110 111 -------------------------- 112 -- Change_Base_Priority -- 113 -------------------------- 114 115 -- Call only with abort deferred and holding Self_ID locked 116 117 procedure Change_Base_Priority (T : Task_Id) is 118 begin 119 if T.Common.Base_Priority /= T.New_Base_Priority then 120 T.Common.Base_Priority := T.New_Base_Priority; 121 Set_Priority (T, T.Common.Base_Priority); 122 end if; 123 end Change_Base_Priority; 124 125 ------------------------ 126 -- Check_Abort_Status -- 127 ------------------------ 128 129 function Check_Abort_Status return Integer is 130 Self_ID : constant Task_Id := Self; 131 begin 132 if Self_ID /= null 133 and then Self_ID.Deferral_Level = 0 134 and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level 135 then 136 return 1; 137 else 138 return 0; 139 end if; 140 end Check_Abort_Status; 141 142 ----------------- 143 -- Defer_Abort -- 144 ----------------- 145 146 procedure Defer_Abort (Self_ID : Task_Id) is 147 begin 148 if No_Abort then 149 return; 150 end if; 151 152 pragma Assert (Self_ID.Deferral_Level = 0); 153 154 -- pragma Assert 155 -- (Self_ID.Pending_ATC_Level >= Self_ID.ATC_Nesting_Level); 156 157 -- The above check has been useful in detecting mismatched defer/undefer 158 -- pairs. You may uncomment it when testing on systems that support 159 -- preemptive abort. 160 161 -- If the OS supports preemptive abort (e.g. pthread_kill), it should 162 -- have happened already. A problem is with systems that do not support 163 -- preemptive abort, and so rely on polling. On such systems we may get 164 -- false failures of the assertion, since polling for pending abort does 165 -- no occur until the abort undefer operation. 166 167 -- Even on systems that only poll for abort, the assertion may be useful 168 -- for catching missed abort completion polling points. The operations 169 -- that undefer abort poll for pending aborts. This covers most of the 170 -- places where the core Ada semantics require abort to be caught, 171 -- without any special attention. However, this generally happens on 172 -- exit from runtime system call, which means a pending abort will not 173 -- be noticed on the way into the runtime system. We considered adding a 174 -- check for pending aborts at this point, but chose not to, because of 175 -- the overhead. Instead, we searched for RTS calls where abort 176 -- completion is required and a task could go farther than Ada allows 177 -- before undeferring abort; we then modified the code to ensure the 178 -- abort would be detected. 179 180 Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1; 181 end Defer_Abort; 182 183 -------------------------- 184 -- Defer_Abort_Nestable -- 185 -------------------------- 186 187 procedure Defer_Abort_Nestable (Self_ID : Task_Id) is 188 begin 189 if No_Abort then 190 return; 191 end if; 192 193 -- The following assertion is by default disabled. See the comment in 194 -- Defer_Abort on the situations in which it may be useful to uncomment 195 -- this assertion and enable the test. 196 197 -- pragma Assert 198 -- (Self_ID.Pending_ATC_Level >= Self_ID.ATC_Nesting_Level or else 199 -- Self_ID.Deferral_Level > 0); 200 201 Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1; 202 end Defer_Abort_Nestable; 203 204 ----------------- 205 -- Abort_Defer -- 206 ----------------- 207 208 procedure Abort_Defer is 209 Self_ID : Task_Id; 210 begin 211 if No_Abort then 212 return; 213 end if; 214 215 Self_ID := STPO.Self; 216 Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1; 217 end Abort_Defer; 218 219 ----------------------- 220 -- Get_Current_Excep -- 221 ----------------------- 222 223 function Get_Current_Excep return SSL.EOA is 224 begin 225 return STPO.Self.Common.Compiler_Data.Current_Excep'Access; 226 end Get_Current_Excep; 227 228 ----------------------- 229 -- Do_Pending_Action -- 230 ----------------------- 231 232 -- Call only when holding no locks 233 234 procedure Do_Pending_Action (Self_ID : Task_Id) is 235 use type Ada.Exceptions.Exception_Id; 236 237 begin 238 pragma Assert (Self_ID = Self and then Self_ID.Deferral_Level = 0); 239 240 -- Needs loop to recheck for pending action in case a new one occurred 241 -- while we had abort deferred below. 242 243 loop 244 -- Temporarily defer abort so that we can lock Self_ID 245 246 Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1; 247 248 if Single_Lock then 249 Lock_RTS; 250 end if; 251 252 Write_Lock (Self_ID); 253 Self_ID.Pending_Action := False; 254 Unlock (Self_ID); 255 256 if Single_Lock then 257 Unlock_RTS; 258 end if; 259 260 -- Restore the original Deferral value 261 262 Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1; 263 264 if not Self_ID.Pending_Action then 265 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then 266 if not Self_ID.Aborting then 267 Self_ID.Aborting := True; 268 pragma Debug 269 (Debug.Trace (Self_ID, "raise Abort_Signal", 'B')); 270 raise Standard'Abort_Signal; 271 272 pragma Assert (not Self_ID.ATC_Hack); 273 274 elsif Self_ID.ATC_Hack then 275 276 -- The solution really belongs in the Abort_Signal handler 277 -- for async. entry calls. The present hack is very 278 -- fragile. It relies that the very next point after 279 -- Exit_One_ATC_Level at which the task becomes abortable 280 -- will be the call to Undefer_Abort in the 281 -- Abort_Signal handler. 282 283 Self_ID.ATC_Hack := False; 284 285 pragma Debug 286 (Debug.Trace 287 (Self_ID, "raise Abort_Signal (ATC hack)", 'B')); 288 raise Standard'Abort_Signal; 289 end if; 290 end if; 291 292 return; 293 end if; 294 end loop; 295 end Do_Pending_Action; 296 297 ----------------------- 298 -- Final_Task_Unlock -- 299 ----------------------- 300 301 -- This version is only for use in Terminate_Task, when the task is 302 -- relinquishing further rights to its own ATCB. 303 304 -- There is a very interesting potential race condition there, where the 305 -- old task may run concurrently with a new task that is allocated the old 306 -- tasks (now reused) ATCB. The critical thing here is to not make any 307 -- reference to the ATCB after the lock is released. See also comments on 308 -- Terminate_Task and Unlock. 309 310 procedure Final_Task_Unlock (Self_ID : Task_Id) is 311 begin 312 pragma Assert (Self_ID.Common.Global_Task_Lock_Nesting = 1); 313 Unlock (Global_Task_Lock'Access, Global_Lock => True); 314 end Final_Task_Unlock; 315 316 -------------- 317 -- Init_RTS -- 318 -------------- 319 320 procedure Init_RTS is 321 Self_Id : Task_Id; 322 begin 323 Tasking.Initialize; 324 325 -- Terminate run time (regular vs restricted) specific initialization 326 -- of the environment task. 327 328 Self_Id := Environment_Task; 329 Self_Id.Master_of_Task := Environment_Task_Level; 330 Self_Id.Master_Within := Self_Id.Master_of_Task + 1; 331 332 for L in Self_Id.Entry_Calls'Range loop 333 Self_Id.Entry_Calls (L).Self := Self_Id; 334 Self_Id.Entry_Calls (L).Level := L; 335 end loop; 336 337 Self_Id.Awake_Count := 1; 338 Self_Id.Alive_Count := 1; 339 340 -- Normally, a task starts out with internal master nesting level one 341 -- larger than external master nesting level. It is incremented to one 342 -- by Enter_Master, which is called in the task body only if the 343 -- compiler thinks the task may have dependent tasks. There is no 344 -- corresponding call to Enter_Master for the environment task, so we 345 -- would need to increment it to 2 here. Instead, we set it to 3. By 346 -- doing this we reserve the level 2 for server tasks of the runtime 347 -- system. The environment task does not need to wait for these server 348 349 Self_Id.Master_Within := Library_Task_Level; 350 351 -- Initialize lock used to implement mutual exclusion between all tasks 352 353 Initialize_Lock (Global_Task_Lock'Access, STPO.Global_Task_Level); 354 355 -- Notify that the tasking run time has been elaborated so that 356 -- the tasking version of the soft links can be used. 357 358 if not No_Abort then 359 SSL.Abort_Defer := Abort_Defer'Access; 360 SSL.Abort_Undefer := Abort_Undefer'Access; 361 end if; 362 363 SSL.Lock_Task := Task_Lock'Access; 364 SSL.Unlock_Task := Task_Unlock'Access; 365 SSL.Check_Abort_Status := Check_Abort_Status'Access; 366 SSL.Task_Name := Task_Name'Access; 367 SSL.Update_Exception := Update_Exception'Access; 368 SSL.Get_Current_Excep := Get_Current_Excep'Access; 369 370 -- Initialize the tasking soft links (if not done yet) that are common 371 -- to the full and the restricted run times. 372 373 SSL.Tasking.Init_Tasking_Soft_Links; 374 375 -- Abort is deferred in a new ATCB, so we need to undefer abort at this 376 -- stage to make the environment task abortable. 377 378 Undefer_Abort (Environment_Task); 379 end Init_RTS; 380 381 --------------------------- 382 -- Locked_Abort_To_Level-- 383 --------------------------- 384 385 -- Abort a task to the specified ATC nesting level. 386 -- Call this only with T locked. 387 388 -- An earlier version of this code contained a call to Wakeup. That should 389 -- not be necessary here, if Abort_Task is implemented correctly, since 390 -- Abort_Task should include the effect of Wakeup. However, the above call 391 -- was in earlier versions of this file, and at least for some targets 392 -- Abort_Task has not been doing Wakeup. It should not hurt to uncomment 393 -- the above call, until the error is corrected for all targets. 394 395 -- See extended comments in package body System.Tasking.Abort for the 396 -- overall design of the implementation of task abort. 397 -- ??? there is no such package ??? 398 399 -- If the task is sleeping it will be in an abort-deferred region, and will 400 -- not have Abort_Signal raised by Abort_Task. Such an "abort deferral" is 401 -- just to protect the RTS internals, and not necessarily required to 402 -- enforce Ada semantics. Abort_Task should wake the task up and let it 403 -- decide if it wants to complete the aborted construct immediately. 404 405 -- Note that the effect of the low-level Abort_Task is not persistent. 406 -- If the target task is not blocked, this wakeup will be missed. 407 408 -- We don't bother calling Abort_Task if this task is aborting itself, 409 -- since we are inside the RTS and have abort deferred. Similarly, We don't 410 -- bother to call Abort_Task if T is terminated, since there is no need to 411 -- abort a terminated task, and it could be dangerous to try if the task 412 -- has stopped executing. 413 414 -- Note that an earlier version of this code had some false reasoning about 415 -- being able to reliably wake up a task that had suspended on a blocking 416 -- system call that does not atomically release the task's lock (e.g., UNIX 417 -- nanosleep, which we once thought could be used to implement delays). 418 -- That still left the possibility of missed wakeups. 419 420 -- We cannot safely call Vulnerable_Complete_Activation here, since that 421 -- requires locking Self_ID.Parent. The anti-deadlock lock ordering rules 422 -- would then require us to release the lock on Self_ID first, which would 423 -- create a timing window for other tasks to lock Self_ID. This is 424 -- significant for tasks that may be aborted before their execution can 425 -- enter the task body, and so they do not get a chance to call 426 -- Complete_Task. The actual work for this case is done in Terminate_Task. 427 428 procedure Locked_Abort_To_Level 429 (Self_ID : Task_Id; 430 T : Task_Id; 431 L : ATC_Level) 432 is 433 begin 434 if not T.Aborting and then T /= Self_ID then 435 case T.Common.State is 436 when Unactivated | Terminated => 437 pragma Assert (False); 438 null; 439 440 when Activating | Runnable => 441 442 -- This is needed to cancel an asynchronous protected entry 443 -- call during a requeue with abort. 444 445 T.Entry_Calls 446 (T.ATC_Nesting_Level).Cancellation_Attempted := True; 447 448 when Interrupt_Server_Blocked_On_Event_Flag => 449 null; 450 451 when Delay_Sleep | 452 Async_Select_Sleep | 453 Interrupt_Server_Idle_Sleep | 454 Interrupt_Server_Blocked_Interrupt_Sleep | 455 Timer_Server_Sleep | 456 AST_Server_Sleep => 457 Wakeup (T, T.Common.State); 458 459 when Acceptor_Sleep | Acceptor_Delay_Sleep => 460 T.Open_Accepts := null; 461 Wakeup (T, T.Common.State); 462 463 when Entry_Caller_Sleep => 464 T.Entry_Calls 465 (T.ATC_Nesting_Level).Cancellation_Attempted := True; 466 Wakeup (T, T.Common.State); 467 468 when Activator_Sleep | 469 Master_Completion_Sleep | 470 Master_Phase_2_Sleep | 471 Asynchronous_Hold => 472 null; 473 end case; 474 end if; 475 476 if T.Pending_ATC_Level > L then 477 T.Pending_ATC_Level := L; 478 T.Pending_Action := True; 479 480 if L = 0 then 481 T.Callable := False; 482 end if; 483 484 -- This prevents aborted task from accepting calls 485 486 if T.Aborting then 487 488 -- The test above is just a heuristic, to reduce wasteful 489 -- calls to Abort_Task. We are holding T locked, and this 490 -- value will not be set to False except with T also locked, 491 -- inside Exit_One_ATC_Level, so we should not miss wakeups. 492 493 if T.Common.State = Acceptor_Sleep 494 or else 495 T.Common.State = Acceptor_Delay_Sleep 496 then 497 T.Open_Accepts := null; 498 end if; 499 500 elsif T /= Self_ID and then 501 (T.Common.State = Runnable 502 or else T.Common.State = Interrupt_Server_Blocked_On_Event_Flag) 503 504 -- The task is blocked on a system call waiting for the 505 -- completion event. In this case Abort_Task may need to take 506 -- special action in order to succeed. Example system: VMS. 507 508 then 509 Abort_Task (T); 510 end if; 511 end if; 512 end Locked_Abort_To_Level; 513 514 -------------------------------- 515 -- Remove_From_All_Tasks_List -- 516 -------------------------------- 517 518 procedure Remove_From_All_Tasks_List (T : Task_Id) is 519 C : Task_Id; 520 Previous : Task_Id; 521 522 begin 523 pragma Debug 524 (Debug.Trace (Self, "Remove_From_All_Tasks_List", 'C')); 525 526 Previous := Null_Task; 527 C := All_Tasks_List; 528 while C /= Null_Task loop 529 if C = T then 530 if Previous = Null_Task then 531 All_Tasks_List := All_Tasks_List.Common.All_Tasks_Link; 532 else 533 Previous.Common.All_Tasks_Link := C.Common.All_Tasks_Link; 534 end if; 535 536 return; 537 end if; 538 539 Previous := C; 540 C := C.Common.All_Tasks_Link; 541 end loop; 542 543 pragma Assert (False); 544 end Remove_From_All_Tasks_List; 545 546 --------------- 547 -- Task_Lock -- 548 --------------- 549 550 procedure Task_Lock (Self_ID : Task_Id) is 551 begin 552 Self_ID.Common.Global_Task_Lock_Nesting := 553 Self_ID.Common.Global_Task_Lock_Nesting + 1; 554 555 if Self_ID.Common.Global_Task_Lock_Nesting = 1 then 556 Defer_Abort_Nestable (Self_ID); 557 Write_Lock (Global_Task_Lock'Access, Global_Lock => True); 558 end if; 559 end Task_Lock; 560 561 procedure Task_Lock is 562 begin 563 Task_Lock (STPO.Self); 564 end Task_Lock; 565 566 --------------- 567 -- Task_Name -- 568 --------------- 569 570 function Task_Name return String is 571 Self_Id : constant Task_Id := STPO.Self; 572 begin 573 return Self_Id.Common.Task_Image (1 .. Self_Id.Common.Task_Image_Len); 574 end Task_Name; 575 576 ----------------- 577 -- Task_Unlock -- 578 ----------------- 579 580 procedure Task_Unlock (Self_ID : Task_Id) is 581 begin 582 pragma Assert (Self_ID.Common.Global_Task_Lock_Nesting > 0); 583 Self_ID.Common.Global_Task_Lock_Nesting := 584 Self_ID.Common.Global_Task_Lock_Nesting - 1; 585 586 if Self_ID.Common.Global_Task_Lock_Nesting = 0 then 587 Unlock (Global_Task_Lock'Access, Global_Lock => True); 588 Undefer_Abort_Nestable (Self_ID); 589 end if; 590 end Task_Unlock; 591 592 procedure Task_Unlock is 593 begin 594 Task_Unlock (STPO.Self); 595 end Task_Unlock; 596 597 ------------------- 598 -- Undefer_Abort -- 599 ------------------- 600 601 -- Precondition : Self does not hold any locks 602 603 -- Undefer_Abort is called on any abort completion point (aka. 604 -- synchronization point). It performs the following actions if they 605 -- are pending: (1) change the base priority, (2) abort the task. 606 607 -- The priority change has to occur before abort. Otherwise, it would 608 -- take effect no earlier than the next abort completion point. 609 610 procedure Undefer_Abort (Self_ID : Task_Id) is 611 begin 612 if No_Abort then 613 return; 614 end if; 615 616 pragma Assert (Self_ID.Deferral_Level = 1); 617 618 Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1; 619 620 if Self_ID.Deferral_Level = 0 then 621 pragma Assert (Check_No_Locks (Self_ID)); 622 623 if Self_ID.Pending_Action then 624 Do_Pending_Action (Self_ID); 625 end if; 626 end if; 627 end Undefer_Abort; 628 629 ---------------------------- 630 -- Undefer_Abort_Nestable -- 631 ---------------------------- 632 633 -- An earlier version would re-defer abort if an abort is in progress. 634 -- Then, we modified the effect of the raise statement so that it defers 635 -- abort until control reaches a handler. That was done to prevent 636 -- "skipping over" a handler if another asynchronous abort occurs during 637 -- the propagation of the abort to the handler. 638 639 -- There has been talk of reversing that decision, based on a newer 640 -- implementation of exception propagation. Care must be taken to evaluate 641 -- how such a change would interact with the above code and all the places 642 -- where abort-deferral is used to bridge over critical transitions, such 643 -- as entry to the scope of a region with a finalizer and entry into the 644 -- body of an accept-procedure. 645 646 procedure Undefer_Abort_Nestable (Self_ID : Task_Id) is 647 begin 648 if No_Abort then 649 return; 650 end if; 651 652 pragma Assert (Self_ID.Deferral_Level > 0); 653 654 Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1; 655 656 if Self_ID.Deferral_Level = 0 then 657 658 pragma Assert (Check_No_Locks (Self_ID)); 659 660 if Self_ID.Pending_Action then 661 Do_Pending_Action (Self_ID); 662 end if; 663 end if; 664 end Undefer_Abort_Nestable; 665 666 ------------------- 667 -- Abort_Undefer -- 668 ------------------- 669 670 procedure Abort_Undefer is 671 Self_ID : Task_Id; 672 begin 673 if No_Abort then 674 return; 675 end if; 676 677 Self_ID := STPO.Self; 678 679 if Self_ID.Deferral_Level = 0 then 680 681 -- In case there are different views on whether Abort is supported 682 -- between the expander and the run time, we may end up with 683 -- Self_ID.Deferral_Level being equal to zero, when called from 684 -- the procedure created by the expander that corresponds to a 685 -- task body. In this case, there's nothing to be done. 686 687 -- See related code in System.Tasking.Stages.Create_Task resetting 688 -- Deferral_Level when System.Restrictions.Abort_Allowed is False. 689 690 return; 691 end if; 692 693 pragma Assert (Self_ID.Deferral_Level > 0); 694 Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1; 695 696 if Self_ID.Deferral_Level = 0 then 697 pragma Assert (Check_No_Locks (Self_ID)); 698 699 if Self_ID.Pending_Action then 700 Do_Pending_Action (Self_ID); 701 end if; 702 end if; 703 end Abort_Undefer; 704 705 ---------------------- 706 -- Update_Exception -- 707 ---------------------- 708 709 -- Call only when holding no locks 710 711 procedure Update_Exception 712 (X : AE.Exception_Occurrence := SSL.Current_Target_Exception) 713 is 714 Self_Id : constant Task_Id := Self; 715 use Ada.Exceptions; 716 717 begin 718 Save_Occurrence (Self_Id.Common.Compiler_Data.Current_Excep, X); 719 720 if Self_Id.Deferral_Level = 0 then 721 if Self_Id.Pending_Action then 722 Self_Id.Pending_Action := False; 723 Self_Id.Deferral_Level := Self_Id.Deferral_Level + 1; 724 725 if Single_Lock then 726 Lock_RTS; 727 end if; 728 729 Write_Lock (Self_Id); 730 Self_Id.Pending_Action := False; 731 Unlock (Self_Id); 732 733 if Single_Lock then 734 Unlock_RTS; 735 end if; 736 737 Self_Id.Deferral_Level := Self_Id.Deferral_Level - 1; 738 739 if Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level then 740 if not Self_Id.Aborting then 741 Self_Id.Aborting := True; 742 raise Standard'Abort_Signal; 743 end if; 744 end if; 745 end if; 746 end if; 747 end Update_Exception; 748 749 -------------------------- 750 -- Wakeup_Entry_Caller -- 751 -------------------------- 752 753 -- This is called at the end of service of an entry call, to abort the 754 -- caller if he is in an abortable part, and to wake up the caller if it 755 -- is on Entry_Caller_Sleep. It assumes that the call is already off-queue. 756 757 -- (This enforces the rule that a task must be off-queue if its state is 758 -- Done or Cancelled.) Call it holding the lock of Entry_Call.Self. 759 760 -- Timed_Call or Simple_Call: 761 -- The caller is waiting on Entry_Caller_Sleep, in 762 -- Wait_For_Completion, or Wait_For_Completion_With_Timeout. 763 764 -- Conditional_Call: 765 -- The caller might be in Wait_For_Completion, 766 -- waiting for a rendezvous (possibly requeued without abort) 767 -- to complete. 768 769 -- Asynchronous_Call: 770 -- The caller may be executing in the abortable part o 771 -- an async. select, or on a time delay, 772 -- if Entry_Call.State >= Was_Abortable. 773 774 procedure Wakeup_Entry_Caller 775 (Self_ID : Task_Id; 776 Entry_Call : Entry_Call_Link; 777 New_State : Entry_Call_State) 778 is 779 Caller : constant Task_Id := Entry_Call.Self; 780 781 begin 782 pragma Debug (Debug.Trace 783 (Self_ID, "Wakeup_Entry_Caller", 'E', Caller)); 784 pragma Assert (New_State = Done or else New_State = Cancelled); 785 786 pragma Assert (Caller.Common.State /= Unactivated); 787 788 Entry_Call.State := New_State; 789 790 if Entry_Call.Mode = Asynchronous_Call then 791 792 -- Abort the caller in his abortable part, but do so only if call has 793 -- been queued abortably. 794 795 if Entry_Call.State >= Was_Abortable or else New_State = Done then 796 Locked_Abort_To_Level (Self_ID, Caller, Entry_Call.Level - 1); 797 end if; 798 799 elsif Caller.Common.State = Entry_Caller_Sleep then 800 Wakeup (Caller, Entry_Caller_Sleep); 801 end if; 802 end Wakeup_Entry_Caller; 803 804 ----------------------- 805 -- Soft-Link Dummies -- 806 ----------------------- 807 808 -- These are dummies for subprograms that are only needed by certain 809 -- optional run-time system packages. If they are needed, the soft links 810 -- will be redirected to the real subprogram by elaboration of the 811 -- subprogram body where the real subprogram is declared. 812 813 procedure Finalize_Attributes (T : Task_Id) is 814 pragma Unreferenced (T); 815 begin 816 null; 817 end Finalize_Attributes; 818 819 procedure Initialize_Attributes (T : Task_Id) is 820 pragma Unreferenced (T); 821 begin 822 null; 823 end Initialize_Attributes; 824 825begin 826 Init_RTS; 827end System.Tasking.Initialization; 828