annotate gcc/ada/libgnarl/s-tasuti.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- S Y S T E M . T A S K I N G . U T I L I T I E S --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNARL is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- GNARL was developed by the GNARL team at Florida State University. --
kono
parents:
diff changeset
28 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
kono
parents:
diff changeset
29 -- --
kono
parents:
diff changeset
30 ------------------------------------------------------------------------------
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 -- This package provides RTS Internal Declarations
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 -- These declarations are not part of the GNARLI
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 pragma Polling (Off);
kono
parents:
diff changeset
37 -- Turn off polling, we do not want ATC polling to take place during tasking
kono
parents:
diff changeset
38 -- operations. It causes infinite loops and other problems.
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 with System.Tasking.Debug;
kono
parents:
diff changeset
41 with System.Task_Primitives.Operations;
kono
parents:
diff changeset
42 with System.Tasking.Initialization;
kono
parents:
diff changeset
43 with System.Tasking.Queuing;
kono
parents:
diff changeset
44 with System.Parameters;
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 package body System.Tasking.Utilities is
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 package STPO renames System.Task_Primitives.Operations;
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 use Parameters;
kono
parents:
diff changeset
51 use Tasking.Debug;
kono
parents:
diff changeset
52 use Task_Primitives;
kono
parents:
diff changeset
53 use Task_Primitives.Operations;
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 --------------------
kono
parents:
diff changeset
56 -- Abort_One_Task --
kono
parents:
diff changeset
57 --------------------
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 -- Similar to Locked_Abort_To_Level (Self_ID, T, 0), but:
kono
parents:
diff changeset
60 -- (1) caller should be holding no locks except RTS_Lock when Single_Lock
kono
parents:
diff changeset
61 -- (2) may be called for tasks that have not yet been activated
kono
parents:
diff changeset
62 -- (3) always aborts whole task
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 procedure Abort_One_Task (Self_ID : Task_Id; T : Task_Id) is
kono
parents:
diff changeset
65 begin
kono
parents:
diff changeset
66 Write_Lock (T);
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 if T.Common.State = Unactivated then
kono
parents:
diff changeset
69 T.Common.Activator := null;
kono
parents:
diff changeset
70 T.Common.State := Terminated;
kono
parents:
diff changeset
71 T.Callable := False;
kono
parents:
diff changeset
72 Cancel_Queued_Entry_Calls (T);
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 elsif T.Common.State /= Terminated then
kono
parents:
diff changeset
75 Initialization.Locked_Abort_To_Level (Self_ID, T, 0);
kono
parents:
diff changeset
76 end if;
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 Unlock (T);
kono
parents:
diff changeset
79 end Abort_One_Task;
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 -----------------
kono
parents:
diff changeset
82 -- Abort_Tasks --
kono
parents:
diff changeset
83 -----------------
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 -- This must be called to implement the abort statement.
kono
parents:
diff changeset
86 -- Much of the actual work of the abort is done by the abortee,
kono
parents:
diff changeset
87 -- via the Abort_Handler signal handler, and propagation of the
kono
parents:
diff changeset
88 -- Abort_Signal special exception.
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 procedure Abort_Tasks (Tasks : Task_List) is
kono
parents:
diff changeset
91 Self_Id : constant Task_Id := STPO.Self;
kono
parents:
diff changeset
92 C : Task_Id;
kono
parents:
diff changeset
93 P : Task_Id;
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 begin
kono
parents:
diff changeset
96 -- If pragma Detect_Blocking is active then Program_Error must be
kono
parents:
diff changeset
97 -- raised if this potentially blocking operation is called from a
kono
parents:
diff changeset
98 -- protected action.
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 if System.Tasking.Detect_Blocking
kono
parents:
diff changeset
101 and then Self_Id.Common.Protected_Action_Nesting > 0
kono
parents:
diff changeset
102 then
kono
parents:
diff changeset
103 raise Program_Error with "potentially blocking operation";
kono
parents:
diff changeset
104 end if;
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 Initialization.Defer_Abort_Nestable (Self_Id);
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 -- ?????
kono
parents:
diff changeset
109 -- Really should not be nested deferral here.
kono
parents:
diff changeset
110 -- Patch for code generation error that defers abort before
kono
parents:
diff changeset
111 -- evaluating parameters of an entry call (at least, timed entry
kono
parents:
diff changeset
112 -- calls), and so may propagate an exception that causes abort
kono
parents:
diff changeset
113 -- to remain undeferred indefinitely. See C97404B. When all
kono
parents:
diff changeset
114 -- such bugs are fixed, this patch can be removed.
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 Lock_RTS;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 for J in Tasks'Range loop
kono
parents:
diff changeset
119 C := Tasks (J);
kono
parents:
diff changeset
120 Abort_One_Task (Self_Id, C);
kono
parents:
diff changeset
121 end loop;
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 C := All_Tasks_List;
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 while C /= null loop
kono
parents:
diff changeset
126 if C.Pending_ATC_Level > 0 then
kono
parents:
diff changeset
127 P := C.Common.Parent;
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 while P /= null loop
kono
parents:
diff changeset
130 if P.Pending_ATC_Level = 0 then
kono
parents:
diff changeset
131 Abort_One_Task (Self_Id, C);
kono
parents:
diff changeset
132 exit;
kono
parents:
diff changeset
133 end if;
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 P := P.Common.Parent;
kono
parents:
diff changeset
136 end loop;
kono
parents:
diff changeset
137 end if;
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 C := C.Common.All_Tasks_Link;
kono
parents:
diff changeset
140 end loop;
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 Unlock_RTS;
kono
parents:
diff changeset
143 Initialization.Undefer_Abort_Nestable (Self_Id);
kono
parents:
diff changeset
144 end Abort_Tasks;
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 -------------------------------
kono
parents:
diff changeset
147 -- Cancel_Queued_Entry_Calls --
kono
parents:
diff changeset
148 -------------------------------
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 -- This should only be called by T, unless T is a terminated previously
kono
parents:
diff changeset
151 -- unactivated task.
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 procedure Cancel_Queued_Entry_Calls (T : Task_Id) is
kono
parents:
diff changeset
154 Next_Entry_Call : Entry_Call_Link;
kono
parents:
diff changeset
155 Entry_Call : Entry_Call_Link;
kono
parents:
diff changeset
156 Self_Id : constant Task_Id := STPO.Self;
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 Caller : Task_Id;
kono
parents:
diff changeset
159 pragma Unreferenced (Caller);
kono
parents:
diff changeset
160 -- Should this be removed ???
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 Level : Integer;
kono
parents:
diff changeset
163 pragma Unreferenced (Level);
kono
parents:
diff changeset
164 -- Should this be removed ???
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166 begin
kono
parents:
diff changeset
167 pragma Assert (T = Self or else T.Common.State = Terminated);
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 for J in 1 .. T.Entry_Num loop
kono
parents:
diff changeset
170 Queuing.Dequeue_Head (T.Entry_Queues (J), Entry_Call);
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 while Entry_Call /= null loop
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 -- Leave Entry_Call.Done = False, since this is cancelled
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176 Caller := Entry_Call.Self;
kono
parents:
diff changeset
177 Entry_Call.Exception_To_Raise := Tasking_Error'Identity;
kono
parents:
diff changeset
178 Queuing.Dequeue_Head (T.Entry_Queues (J), Next_Entry_Call);
kono
parents:
diff changeset
179 Level := Entry_Call.Level - 1;
kono
parents:
diff changeset
180 Unlock (T);
kono
parents:
diff changeset
181 Write_Lock (Entry_Call.Self);
kono
parents:
diff changeset
182 Initialization.Wakeup_Entry_Caller
kono
parents:
diff changeset
183 (Self_Id, Entry_Call, Cancelled);
kono
parents:
diff changeset
184 Unlock (Entry_Call.Self);
kono
parents:
diff changeset
185 Write_Lock (T);
kono
parents:
diff changeset
186 Entry_Call.State := Done;
kono
parents:
diff changeset
187 Entry_Call := Next_Entry_Call;
kono
parents:
diff changeset
188 end loop;
kono
parents:
diff changeset
189 end loop;
kono
parents:
diff changeset
190 end Cancel_Queued_Entry_Calls;
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 ------------------------
kono
parents:
diff changeset
193 -- Exit_One_ATC_Level --
kono
parents:
diff changeset
194 ------------------------
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 -- Call only with abort deferred and holding lock of Self_Id.
kono
parents:
diff changeset
197 -- This is a bit of common code for all entry calls.
kono
parents:
diff changeset
198 -- The effect is to exit one level of ATC nesting.
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 -- If we have reached the desired ATC nesting level, reset the
kono
parents:
diff changeset
201 -- requested level to effective infinity, to allow further calls.
kono
parents:
diff changeset
202 -- In any case, reset Self_Id.Aborting, to allow re-raising of
kono
parents:
diff changeset
203 -- Abort_Signal.
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 procedure Exit_One_ATC_Level (Self_ID : Task_Id) is
kono
parents:
diff changeset
206 begin
kono
parents:
diff changeset
207 Self_ID.ATC_Nesting_Level := Self_ID.ATC_Nesting_Level - 1;
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 pragma Debug
kono
parents:
diff changeset
210 (Debug.Trace (Self_ID, "EOAL: exited to ATC level: " &
kono
parents:
diff changeset
211 ATC_Level'Image (Self_ID.ATC_Nesting_Level), 'A'));
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 pragma Assert (Self_ID.ATC_Nesting_Level >= 1);
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 if Self_ID.Pending_ATC_Level < ATC_Level_Infinity then
kono
parents:
diff changeset
216 if Self_ID.Pending_ATC_Level = Self_ID.ATC_Nesting_Level then
kono
parents:
diff changeset
217 Self_ID.Pending_ATC_Level := ATC_Level_Infinity;
kono
parents:
diff changeset
218 Self_ID.Aborting := False;
kono
parents:
diff changeset
219 else
kono
parents:
diff changeset
220 -- Force the next Undefer_Abort to re-raise Abort_Signal
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 pragma Assert
kono
parents:
diff changeset
223 (Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level);
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 if Self_ID.Aborting then
kono
parents:
diff changeset
226 Self_ID.ATC_Hack := True;
kono
parents:
diff changeset
227 Self_ID.Pending_Action := True;
kono
parents:
diff changeset
228 end if;
kono
parents:
diff changeset
229 end if;
kono
parents:
diff changeset
230 end if;
kono
parents:
diff changeset
231 end Exit_One_ATC_Level;
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 ----------------------
kono
parents:
diff changeset
234 -- Make_Independent --
kono
parents:
diff changeset
235 ----------------------
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 function Make_Independent return Boolean is
kono
parents:
diff changeset
238 Self_Id : constant Task_Id := STPO.Self;
kono
parents:
diff changeset
239 Environment_Task : constant Task_Id := STPO.Environment_Task;
kono
parents:
diff changeset
240 Parent : constant Task_Id := Self_Id.Common.Parent;
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 begin
kono
parents:
diff changeset
243 if Self_Id.Known_Tasks_Index /= -1 then
kono
parents:
diff changeset
244 Known_Tasks (Self_Id.Known_Tasks_Index) := null;
kono
parents:
diff changeset
245 end if;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 Initialization.Defer_Abort (Self_Id);
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 if Single_Lock then
kono
parents:
diff changeset
250 Lock_RTS;
kono
parents:
diff changeset
251 end if;
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 Write_Lock (Environment_Task);
kono
parents:
diff changeset
254 Write_Lock (Self_Id);
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 -- The run time assumes that the parent of an independent task is the
kono
parents:
diff changeset
257 -- environment task.
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 pragma Assert (Parent = Environment_Task);
kono
parents:
diff changeset
260
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
261 Self_Id.Master_Of_Task := Independent_Task_Level;
111
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 -- Update Independent_Task_Count that is needed for the GLADE
kono
parents:
diff changeset
264 -- termination rule. See also pending update in
kono
parents:
diff changeset
265 -- System.Tasking.Stages.Check_Independent
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 Independent_Task_Count := Independent_Task_Count + 1;
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 -- This should be called before the task reaches its "begin" (see spec),
kono
parents:
diff changeset
270 -- which ensures that the environment task cannot race ahead and be
kono
parents:
diff changeset
271 -- already waiting for children to complete.
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 Unlock (Self_Id);
kono
parents:
diff changeset
274 pragma Assert (Environment_Task.Common.State /= Master_Completion_Sleep);
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 Unlock (Environment_Task);
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 if Single_Lock then
kono
parents:
diff changeset
279 Unlock_RTS;
kono
parents:
diff changeset
280 end if;
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 Initialization.Undefer_Abort (Self_Id);
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 -- Return True. Actually the return value is junk, since we expect it
kono
parents:
diff changeset
285 -- always to be ignored (see spec), but we have to return something!
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 return True;
kono
parents:
diff changeset
288 end Make_Independent;
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 ------------------
kono
parents:
diff changeset
291 -- Make_Passive --
kono
parents:
diff changeset
292 ------------------
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 procedure Make_Passive (Self_ID : Task_Id; Task_Completed : Boolean) is
kono
parents:
diff changeset
295 C : Task_Id := Self_ID;
kono
parents:
diff changeset
296 P : Task_Id := C.Common.Parent;
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 Master_Completion_Phase : Integer;
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 begin
kono
parents:
diff changeset
301 if P /= null then
kono
parents:
diff changeset
302 Write_Lock (P);
kono
parents:
diff changeset
303 end if;
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 Write_Lock (C);
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 if Task_Completed then
kono
parents:
diff changeset
308 Self_ID.Common.State := Terminated;
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 if Self_ID.Awake_Count = 0 then
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 -- We are completing via a terminate alternative.
kono
parents:
diff changeset
313 -- Our parent should wait in Phase 2 of Complete_Master.
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 Master_Completion_Phase := 2;
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 pragma Assert (Task_Completed);
kono
parents:
diff changeset
318 pragma Assert (Self_ID.Terminate_Alternative);
kono
parents:
diff changeset
319 pragma Assert (Self_ID.Alive_Count = 1);
kono
parents:
diff changeset
320
kono
parents:
diff changeset
321 else
kono
parents:
diff changeset
322 -- We are NOT on a terminate alternative.
kono
parents:
diff changeset
323 -- Our parent should wait in Phase 1 of Complete_Master.
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 Master_Completion_Phase := 1;
kono
parents:
diff changeset
326 pragma Assert (Self_ID.Awake_Count >= 1);
kono
parents:
diff changeset
327 end if;
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 -- We are accepting with a terminate alternative
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 else
kono
parents:
diff changeset
332 if Self_ID.Open_Accepts = null then
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 -- Somebody started a rendezvous while we had our lock open.
kono
parents:
diff changeset
335 -- Skip the terminate alternative.
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 Unlock (C);
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 if P /= null then
kono
parents:
diff changeset
340 Unlock (P);
kono
parents:
diff changeset
341 end if;
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 return;
kono
parents:
diff changeset
344 end if;
kono
parents:
diff changeset
345
kono
parents:
diff changeset
346 Self_ID.Terminate_Alternative := True;
kono
parents:
diff changeset
347 Master_Completion_Phase := 0;
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 pragma Assert (Self_ID.Terminate_Alternative);
kono
parents:
diff changeset
350 pragma Assert (Self_ID.Awake_Count >= 1);
kono
parents:
diff changeset
351 end if;
kono
parents:
diff changeset
352
kono
parents:
diff changeset
353 if Master_Completion_Phase = 2 then
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 -- Since our Awake_Count is zero but our Alive_Count
kono
parents:
diff changeset
356 -- is nonzero, we have been accepting with a terminate
kono
parents:
diff changeset
357 -- alternative, and we now have been told to terminate
kono
parents:
diff changeset
358 -- by a completed master (in some ancestor task) that
kono
parents:
diff changeset
359 -- is waiting (with zero Awake_Count) in Phase 2 of
kono
parents:
diff changeset
360 -- Complete_Master.
kono
parents:
diff changeset
361
kono
parents:
diff changeset
362 pragma Debug (Debug.Trace (Self_ID, "Make_Passive: Phase 2", 'M'));
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 pragma Assert (P /= null);
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 C.Alive_Count := C.Alive_Count - 1;
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 if C.Alive_Count > 0 then
kono
parents:
diff changeset
369 Unlock (C);
kono
parents:
diff changeset
370 Unlock (P);
kono
parents:
diff changeset
371 return;
kono
parents:
diff changeset
372 end if;
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 -- C's count just went to zero, indicating that
kono
parents:
diff changeset
375 -- all of C's dependents are terminated.
kono
parents:
diff changeset
376 -- C has a parent, P.
kono
parents:
diff changeset
377
kono
parents:
diff changeset
378 loop
kono
parents:
diff changeset
379 -- C's count just went to zero, indicating that all of C's
kono
parents:
diff changeset
380 -- dependents are terminated. C has a parent, P. Notify P that
kono
parents:
diff changeset
381 -- C and its dependents have all terminated.
kono
parents:
diff changeset
382
kono
parents:
diff changeset
383 P.Alive_Count := P.Alive_Count - 1;
kono
parents:
diff changeset
384 exit when P.Alive_Count > 0;
kono
parents:
diff changeset
385 Unlock (C);
kono
parents:
diff changeset
386 Unlock (P);
kono
parents:
diff changeset
387 C := P;
kono
parents:
diff changeset
388 P := C.Common.Parent;
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 -- Environment task cannot have terminated yet
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 pragma Assert (P /= null);
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 Write_Lock (P);
kono
parents:
diff changeset
395 Write_Lock (C);
kono
parents:
diff changeset
396 end loop;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 if P.Common.State = Master_Phase_2_Sleep
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
399 and then C.Master_Of_Task = P.Master_Within
111
kono
parents:
diff changeset
400 then
kono
parents:
diff changeset
401 pragma Assert (P.Common.Wait_Count > 0);
kono
parents:
diff changeset
402 P.Common.Wait_Count := P.Common.Wait_Count - 1;
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 if P.Common.Wait_Count = 0 then
kono
parents:
diff changeset
405 Wakeup (P, Master_Phase_2_Sleep);
kono
parents:
diff changeset
406 end if;
kono
parents:
diff changeset
407 end if;
kono
parents:
diff changeset
408
kono
parents:
diff changeset
409 Unlock (C);
kono
parents:
diff changeset
410 Unlock (P);
kono
parents:
diff changeset
411 return;
kono
parents:
diff changeset
412 end if;
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 -- We are terminating in Phase 1 or Complete_Master,
kono
parents:
diff changeset
415 -- or are accepting on a terminate alternative.
kono
parents:
diff changeset
416
kono
parents:
diff changeset
417 C.Awake_Count := C.Awake_Count - 1;
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 if Task_Completed then
kono
parents:
diff changeset
420 C.Alive_Count := C.Alive_Count - 1;
kono
parents:
diff changeset
421 end if;
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 if C.Awake_Count > 0 or else P = null then
kono
parents:
diff changeset
424 Unlock (C);
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 if P /= null then
kono
parents:
diff changeset
427 Unlock (P);
kono
parents:
diff changeset
428 end if;
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 return;
kono
parents:
diff changeset
431 end if;
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 -- C's count just went to zero, indicating that all of C's
kono
parents:
diff changeset
434 -- dependents are terminated or accepting with terminate alt.
kono
parents:
diff changeset
435 -- C has a parent, P.
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 loop
kono
parents:
diff changeset
438 -- Notify P that C has gone passive
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 if P.Awake_Count > 0 then
kono
parents:
diff changeset
441 P.Awake_Count := P.Awake_Count - 1;
kono
parents:
diff changeset
442 end if;
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 if Task_Completed and then C.Alive_Count = 0 then
kono
parents:
diff changeset
445 P.Alive_Count := P.Alive_Count - 1;
kono
parents:
diff changeset
446 end if;
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 exit when P.Awake_Count > 0;
kono
parents:
diff changeset
449 Unlock (C);
kono
parents:
diff changeset
450 Unlock (P);
kono
parents:
diff changeset
451 C := P;
kono
parents:
diff changeset
452 P := C.Common.Parent;
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 if P = null then
kono
parents:
diff changeset
455 return;
kono
parents:
diff changeset
456 end if;
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 Write_Lock (P);
kono
parents:
diff changeset
459 Write_Lock (C);
kono
parents:
diff changeset
460 end loop;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 -- P has non-passive dependents
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 if P.Common.State = Master_Completion_Sleep
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
465 and then C.Master_Of_Task = P.Master_Within
111
kono
parents:
diff changeset
466 then
kono
parents:
diff changeset
467 pragma Debug
kono
parents:
diff changeset
468 (Debug.Trace
kono
parents:
diff changeset
469 (Self_ID, "Make_Passive: Phase 1, parent waiting", 'M'));
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 -- If parent is in Master_Completion_Sleep, it cannot be on a
kono
parents:
diff changeset
472 -- terminate alternative, hence it cannot have Wait_Count of zero.
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 pragma Assert (P.Common.Wait_Count > 0);
kono
parents:
diff changeset
475 P.Common.Wait_Count := P.Common.Wait_Count - 1;
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 if P.Common.Wait_Count = 0 then
kono
parents:
diff changeset
478 Wakeup (P, Master_Completion_Sleep);
kono
parents:
diff changeset
479 end if;
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 else
kono
parents:
diff changeset
482 pragma Debug
kono
parents:
diff changeset
483 (Debug.Trace (Self_ID, "Make_Passive: Phase 1, parent awake", 'M'));
kono
parents:
diff changeset
484 null;
kono
parents:
diff changeset
485 end if;
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 Unlock (C);
kono
parents:
diff changeset
488 Unlock (P);
kono
parents:
diff changeset
489 end Make_Passive;
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491 end System.Tasking.Utilities;