s-tasini.ads, [...] (Undefer_Abortion): Handle case of Self_Id.Deferral_Level = 0.

* s-tasini.ads, s-tasini.adb (Undefer_Abortion): Handle case of
	Self_Id.Deferral_Level = 0.
	(Do_Pending_Action): Move this function to the spec.

	* s-tasren.adb (Selective_Wait [Terminate_Selected]): Call
	Do_Pending_Action explicitely when needed, in case we're using
	No_Abort restrictions.

	* s-tassta.adb (Create_Task): If Abort is not allowed, reset the
	deferral level since it will not get changed by the generated code.
	Keeping a default value of 1 would prevent some operations (e.g.
	select or delay) to proceed successfully.

From-SVN: r92851
This commit is contained in:
Arnaud Charlet 2005-01-03 16:42:23 +01:00
parent b558cbe01b
commit e9906cbf17
4 changed files with 53 additions and 7 deletions

View File

@ -128,10 +128,6 @@ package body System.Tasking.Initialization is
-- Local Subprograms --
------------------------
procedure Do_Pending_Action (Self_ID : Task_Id);
-- This is introduced to allow more efficient
-- in-line expansion of Undefer_Abort.
----------------------------
-- Tasking Initialization --
----------------------------
@ -777,8 +773,24 @@ package body System.Tasking.Initialization is
end if;
Self_ID := STPO.Self;
pragma Assert (Self_ID.Deferral_Level > 0);
if Self_ID.Deferral_Level = 0 then
-- In case there are different views on whether Abort is supported
-- between the expander and the run time, we may end up with
-- Self_ID.Deferral_Level being equal to zero, when called from
-- the procedure created by the expander that corresponds to a
-- task body.
-- In this case, there's nothing to be done
-- See related code in System.Tasking.Stages.Create_Task resetting
-- Deferral_Level when System.Restrictions.Abort_Allowed is False.
return;
end if;
pragma Assert (Self_ID.Deferral_Level > 0);
Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1;
if Self_ID.Deferral_Level = 0 then

View File

@ -131,6 +131,14 @@ package System.Tasking.Initialization is
-- ?????
-- Try to phase out all uses of the above versions.
procedure Do_Pending_Action (Self_ID : Task_Id);
-- Only call with no locks, and when Self_ID.Pending_Action = True
-- Perform necessary pending actions (e.g. abortion, priority change).
-- This procedure is usually called when needed as a result of
-- calling Undefer_Abort, although in the case of e.g. No_Abort
-- restriction, it can be necessary to force execution of pending
-- actions.
function Check_Abort_Status return Integer;
-- Returns Boolean'Pos (True) iff abort signal should raise
-- Standard.Abort_Signal. Only used by IRIX currently.

View File

@ -55,6 +55,7 @@ with System.Tasking.Initialization;
-- used for Defer_Abort
-- Undefer_Abort
-- Poll_Base_Priority_Change
-- Do_Pending_Action
with System.Tasking.Queuing;
-- used for Enqueue
@ -972,8 +973,20 @@ package body System.Tasking.Rendezvous is
pragma Assert (Self_Id.Pending_ATC_Level = 0);
pragma Assert (Self_Id.Awake_Count = 0);
-- Trust that it is OK to fall through.
null;
STPO.Unlock (Self_Id);
if Single_Lock then
Unlock_RTS;
end if;
Index := Self_Id.Chosen_Index;
Initialization.Undefer_Abort_Nestable (Self_Id);
if Self_Id.Pending_Action then
Initialization.Do_Pending_Action (Self_Id);
end if;
return;
else
-- Self_Id.Common.Call and Self_Id.Chosen_Index

View File

@ -103,6 +103,9 @@ with System.Secondary_Stack;
with System.Storage_Elements;
-- used for Storage_Array
with System.Restrictions;
-- used for Abort_Allowed
with System.Standard_Library;
-- used for Exception_Trace
@ -614,6 +617,16 @@ package body System.Tasking.Stages is
(Storage_Error'Identity, "Failed to initialize task");
end if;
if not System.Restrictions.Abort_Allowed then
-- If Abort is not allowed, reset the deferral level since it will
-- not get changed by the generated code. Keeping a default value
-- of one would prevent some operations (e.g. select or delay) to
-- proceed successfully.
T.Deferral_Level := 0;
end if;
T.Master_of_Task := Master;
T.Master_Within := T.Master_of_Task + 1;