PR c++/3637
[official-gcc.git] / gcc / ada / s-tpoben.adb
blobfa37450cef82a1adcab0570382d8a19738b735bc
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS --
4 -- --
5 -- S Y S T E M . T A S K I N G . P R O T E C T E D _ O B J E C T S . --
6 -- E N T R I E S --
7 -- --
8 -- B o d y --
9 -- --
10 -- $Revision: 1.11 $
11 -- --
12 -- Copyright (C) 1991-2001, Florida State University --
13 -- --
14 -- GNARL is free software; you can redistribute it and/or modify it under --
15 -- terms of the GNU General Public License as published by the Free Soft- --
16 -- ware Foundation; either version 2, or (at your option) any later ver- --
17 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
18 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
19 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
20 -- for more details. You should have received a copy of the GNU General --
21 -- Public License distributed with GNARL; see file COPYING. If not, write --
22 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
23 -- MA 02111-1307, USA. --
24 -- --
25 -- As a special exception, if other files instantiate generics from this --
26 -- unit, or you link this unit with other files to produce an executable, --
27 -- this unit does not by itself cause the resulting executable to be --
28 -- covered by the GNU General Public License. This exception does not --
29 -- however invalidate any other reasons why the executable file might be --
30 -- covered by the GNU Public License. --
31 -- --
32 -- GNARL was developed by the GNARL team at Florida State University. It is --
33 -- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
34 -- State University (http://www.gnat.com). --
35 -- --
36 ------------------------------------------------------------------------------
38 -- This package contains all the simple primitives related to
39 -- Protected_Objects with entries (i.e init, lock, unlock).
41 -- The handling of protected objects with no entries is done in
42 -- System.Tasking.Protected_Objects, the complex routines for protected
43 -- objects with entries in System.Tasking.Protected_Objects.Operations.
44 -- The split between Entries and Operations is needed to break circular
45 -- dependencies inside the run time.
47 -- Note: the compiler generates direct calls to this interface, via Rtsfind.
49 with Ada.Exceptions;
50 -- used for Exception_Occurrence_Access
52 with System.Task_Primitives.Operations;
53 -- used for Initialize_Lock
54 -- Write_Lock
55 -- Unlock
56 -- Get_Priority
57 -- Wakeup
59 with System.Tasking.Initialization;
60 -- used for Defer_Abort,
61 -- Undefer_Abort,
62 -- Change_Base_Priority
64 pragma Elaborate_All (System.Tasking.Initialization);
65 -- this insures that tasking is initialized if any protected objects are
66 -- created.
68 package body System.Tasking.Protected_Objects.Entries is
70 package STPO renames System.Task_Primitives.Operations;
72 use Ada.Exceptions;
73 use STPO;
75 Locking_Policy : Character;
76 pragma Import (C, Locking_Policy, "__gl_locking_policy");
78 --------------
79 -- Finalize --
80 --------------
82 procedure Finalize (Object : in out Protection_Entries) is
83 Entry_Call : Entry_Call_Link;
84 Caller : Task_ID;
85 Ceiling_Violation : Boolean;
86 Self_ID : constant Task_ID := STPO.Self;
87 Old_Base_Priority : System.Any_Priority;
89 begin
90 if Object.Finalized then
91 return;
92 end if;
94 STPO.Write_Lock (Object.L'Unrestricted_Access, Ceiling_Violation);
96 if Ceiling_Violation then
98 -- Dip our own priority down to ceiling of lock.
99 -- See similar code in Tasking.Entry_Calls.Lock_Server.
101 STPO.Write_Lock (Self_ID);
102 Old_Base_Priority := Self_ID.Common.Base_Priority;
103 Self_ID.New_Base_Priority := Object.Ceiling;
104 Initialization.Change_Base_Priority (Self_ID);
105 STPO.Unlock (Self_ID);
106 STPO.Write_Lock (Object.L'Unrestricted_Access, Ceiling_Violation);
108 if Ceiling_Violation then
109 Raise_Exception (Program_Error'Identity, "Ceiling Violation");
110 end if;
112 Object.Old_Base_Priority := Old_Base_Priority;
113 Object.Pending_Action := True;
114 end if;
116 -- Send program_error to all tasks still queued on this object.
118 for E in Object.Entry_Queues'Range loop
119 Entry_Call := Object.Entry_Queues (E).Head;
121 while Entry_Call /= null loop
122 Caller := Entry_Call.Self;
123 Entry_Call.Exception_To_Raise := Program_Error'Identity;
124 STPO.Write_Lock (Caller);
125 Initialization.Wakeup_Entry_Caller (Self_ID, Entry_Call, Done);
126 STPO.Unlock (Caller);
127 exit when Entry_Call = Object.Entry_Queues (E).Tail;
128 Entry_Call := Entry_Call.Next;
129 end loop;
130 end loop;
132 Object.Finalized := True;
133 STPO.Unlock (Object.L'Unrestricted_Access);
134 STPO.Finalize_Lock (Object.L'Unrestricted_Access);
135 end Finalize;
137 -------------------------------------
138 -- Has_Interrupt_Or_Attach_Handler --
139 -------------------------------------
141 function Has_Interrupt_Or_Attach_Handler
142 (Object : Protection_Entries_Access)
143 return Boolean
145 begin
146 return False;
147 end Has_Interrupt_Or_Attach_Handler;
149 -----------------------------------
150 -- Initialize_Protection_Entries --
151 -----------------------------------
153 procedure Initialize_Protection_Entries
154 (Object : Protection_Entries_Access;
155 Ceiling_Priority : Integer;
156 Compiler_Info : System.Address;
157 Entry_Bodies : Protected_Entry_Body_Access;
158 Find_Body_Index : Find_Body_Index_Access)
160 Init_Priority : Integer := Ceiling_Priority;
161 Self_ID : constant Task_ID := STPO.Self;
163 begin
164 if Init_Priority = Unspecified_Priority then
165 Init_Priority := System.Priority'Last;
166 end if;
168 if Locking_Policy = 'C'
169 and then Has_Interrupt_Or_Attach_Handler (Object)
170 and then Init_Priority not in System.Interrupt_Priority
171 then
172 -- Required by C.3.1(11)
174 raise Program_Error;
175 end if;
177 Initialization.Defer_Abort (Self_ID);
178 Initialize_Lock (Init_Priority, Object.L'Access);
179 Initialization.Undefer_Abort (Self_ID);
180 Object.Ceiling := System.Any_Priority (Init_Priority);
181 Object.Compiler_Info := Compiler_Info;
182 Object.Pending_Action := False;
183 Object.Call_In_Progress := null;
184 Object.Entry_Bodies := Entry_Bodies;
185 Object.Find_Body_Index := Find_Body_Index;
187 for E in Object.Entry_Queues'Range loop
188 Object.Entry_Queues (E).Head := null;
189 Object.Entry_Queues (E).Tail := null;
190 end loop;
191 end Initialize_Protection_Entries;
193 ------------------
194 -- Lock_Entries --
195 ------------------
197 procedure Lock_Entries
198 (Object : Protection_Entries_Access; Ceiling_Violation : out Boolean) is
199 begin
200 -- The lock is made without defering abortion.
202 -- Therefore the abortion has to be deferred before calling this
203 -- routine. This means that the compiler has to generate a Defer_Abort
204 -- call before the call to Lock.
206 -- The caller is responsible for undeferring abortion, and compiler
207 -- generated calls must be protected with cleanup handlers to ensure
208 -- that abortion is undeferred in all cases.
210 pragma Assert (STPO.Self.Deferral_Level > 0);
211 Write_Lock (Object.L'Access, Ceiling_Violation);
212 end Lock_Entries;
214 procedure Lock_Entries (Object : Protection_Entries_Access) is
215 Ceiling_Violation : Boolean;
216 begin
217 pragma Assert (STPO.Self.Deferral_Level > 0);
218 Write_Lock (Object.L'Access, Ceiling_Violation);
220 if Ceiling_Violation then
221 Raise_Exception (Program_Error'Identity, "Ceiling Violation");
222 end if;
223 end Lock_Entries;
225 ----------------------------
226 -- Lock_Read_Only_Entries --
227 ----------------------------
229 procedure Lock_Read_Only_Entries (Object : Protection_Entries_Access) is
230 Ceiling_Violation : Boolean;
231 begin
232 Read_Lock (Object.L'Access, Ceiling_Violation);
234 if Ceiling_Violation then
235 Raise_Exception (Program_Error'Identity, "Ceiling Violation");
236 end if;
237 end Lock_Read_Only_Entries;
239 --------------------
240 -- Unlock_Entries --
241 --------------------
243 procedure Unlock_Entries (Object : Protection_Entries_Access) is
244 begin
245 Unlock (Object.L'Access);
246 end Unlock_Entries;
248 end System.Tasking.Protected_Objects.Entries;