summaryrefslogtreecommitdiff
path: root/gcc/ada/s-tpoben.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/s-tpoben.adb')
-rw-r--r--gcc/ada/s-tpoben.adb80
1 files changed, 72 insertions, 8 deletions
diff --git a/gcc/ada/s-tpoben.adb b/gcc/ada/s-tpoben.adb
index a195828c9b2..c1d7d3ccae4 100644
--- a/gcc/ada/s-tpoben.adb
+++ b/gcc/ada/s-tpoben.adb
@@ -44,6 +44,7 @@
with Ada.Exceptions;
-- used for Exception_Occurrence_Access
+-- Raise_Exception
with System.Task_Primitives.Operations;
-- used for Initialize_Lock
@@ -72,6 +73,10 @@ package body System.Tasking.Protected_Objects.Entries is
use Task_Primitives.Operations;
use Ada.Exceptions;
+ ----------------
+ -- Local Data --
+ ----------------
+
Locking_Policy : Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
@@ -216,13 +221,36 @@ package body System.Tasking.Protected_Objects.Entries is
------------------
procedure Lock_Entries
- (Object : Protection_Entries_Access; Ceiling_Violation : out Boolean) is
+ (Object : Protection_Entries_Access; Ceiling_Violation : out Boolean)
+ is
begin
if Object.Finalized then
Raise_Exception
(Program_Error'Identity, "Protected Object is finalized");
end if;
+ -- If pragma Detect_Blocking is active then Program_Error must
+ -- be raised if this potentially blocking operation is called from
+ -- a protected action, and the protected object nesting level
+ -- must be increased.
+
+ if Detect_Blocking then
+ declare
+ Self_Id : constant Task_Id := STPO.Self;
+ begin
+ if Self_Id.Common.Protected_Action_Nesting > 0 then
+ Ada.Exceptions.Raise_Exception
+ (Program_Error'Identity, "potentially blocking operation");
+ else
+ -- We are entering in a protected action, so that we
+ -- increase the protected object nesting level.
+
+ Self_Id.Common.Protected_Action_Nesting :=
+ Self_Id.Common.Protected_Action_Nesting + 1;
+ end if;
+ end;
+ end if;
+
-- The lock is made without defering abortion.
-- Therefore the abortion has to be deferred before calling this
@@ -239,14 +267,9 @@ package body System.Tasking.Protected_Objects.Entries is
procedure Lock_Entries (Object : Protection_Entries_Access) is
Ceiling_Violation : Boolean;
- begin
- if Object.Finalized then
- Raise_Exception
- (Program_Error'Identity, "Protected Object is finalized");
- end if;
- pragma Assert (STPO.Self.Deferral_Level > 0);
- Write_Lock (Object.L'Access, Ceiling_Violation);
+ begin
+ Lock_Entries (Object, Ceiling_Violation);
if Ceiling_Violation then
Raise_Exception (Program_Error'Identity, "Ceiling Violation");
@@ -259,12 +282,35 @@ package body System.Tasking.Protected_Objects.Entries is
procedure Lock_Read_Only_Entries (Object : Protection_Entries_Access) is
Ceiling_Violation : Boolean;
+
begin
if Object.Finalized then
Raise_Exception
(Program_Error'Identity, "Protected Object is finalized");
end if;
+ -- If pragma Detect_Blocking is active then Program_Error must be
+ -- raised if this potentially blocking operation is called from a
+ -- protected action, and the protected object nesting level must
+ -- be increased.
+
+ if Detect_Blocking then
+ declare
+ Self_Id : constant Task_Id := STPO.Self;
+ begin
+ if Self_Id.Common.Protected_Action_Nesting > 0 then
+ Ada.Exceptions.Raise_Exception
+ (Program_Error'Identity, "potentially blocking operation");
+ else
+ -- We are entering in a protected action, so that we
+ -- increase the protected object nesting level.
+
+ Self_Id.Common.Protected_Action_Nesting :=
+ Self_Id.Common.Protected_Action_Nesting + 1;
+ end if;
+ end;
+ end if;
+
Read_Lock (Object.L'Access, Ceiling_Violation);
if Ceiling_Violation then
@@ -278,6 +324,24 @@ package body System.Tasking.Protected_Objects.Entries is
procedure Unlock_Entries (Object : Protection_Entries_Access) is
begin
+ -- We are exiting from a protected action, so that we decrease the
+ -- protected object nesting level (if pragma Detect_Blocking is
+ -- active).
+
+ if Detect_Blocking then
+ declare
+ Self_Id : constant Task_Id := Self;
+ begin
+ -- Cannot call this procedure without being within a protected
+ -- action.
+
+ pragma Assert (Self_Id.Common.Protected_Action_Nesting > 0);
+
+ Self_Id.Common.Protected_Action_Nesting :=
+ Self_Id.Common.Protected_Action_Nesting - 1;
+ end;
+ end if;
+
Unlock (Object.L'Access);
end Unlock_Entries;