1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- S Y S T E M . T A S K _ P R I M I T I V E S . O P E R A T I O N S --
9 -- Copyright (C) 1992-2007, Free Software Foundation, Inc. --
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 2, or (at your option) any later ver- --
14 -- sion. GNARL 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNARL; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNARL was developed by the GNARL team at Florida State University. --
30 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
32 ------------------------------------------------------------------------------
34 -- This is a OpenVMS/Alpha version of this package
36 -- This package contains all the GNULL primitives that interface directly
37 -- with the underlying OS.
40 -- Turn off polling, we do not want ATC polling to take place during
41 -- tasking operations. It causes infinite loops and other problems.
43 with System.Tasking.Debug;
44 -- used for Known_Tasks
46 with System.OS_Primitives;
47 -- used for Delay_Modes
53 with System.Soft_Links;
54 -- used for Get_Exc_Stack_Addr
55 -- Abort_Defer/Undefer
57 with Ada.Unchecked_Conversion;
58 with Ada.Unchecked_Deallocation;
60 package body System.Task_Primitives.Operations is
62 use System.Tasking.Debug;
65 use System.OS_Interface;
66 use System.Parameters;
67 use System.OS_Primitives;
68 use type System.OS_Primitives.OS_Time;
70 package SSL renames System.Soft_Links;
76 -- The followings are logically constants, but need to be initialized
79 Single_RTS_Lock : aliased RTS_Lock;
80 -- This is a lock to allow only one thread of control in the RTS at
81 -- a time; it is used to execute in mutual exclusion from all other tasks.
82 -- Used mainly in Single_Lock mode, but also to protect All_Tasks_List
84 ATCB_Key : aliased pthread_key_t;
85 -- Key used to find the Ada Task_Id associated with a thread
87 Environment_Task_Id : Task_Id;
88 -- A variable to hold Task_Id for the environment task
90 Time_Slice_Val : Integer;
91 pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
93 Dispatching_Policy : Character;
94 pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
96 Foreign_Task_Elaborated : aliased Boolean := True;
97 -- Used to identified fake tasks (i.e., non-Ada Threads)
105 procedure Initialize (Environment_Task : Task_Id);
106 pragma Inline (Initialize);
107 -- Initialize various data needed by this package
109 function Is_Valid_Task return Boolean;
110 pragma Inline (Is_Valid_Task);
111 -- Does executing thread have a TCB?
113 procedure Set (Self_Id : Task_Id);
115 -- Set the self id for the current task
117 function Self return Task_Id;
118 pragma Inline (Self);
119 -- Return a pointer to the Ada Task Control Block of the calling task
123 package body Specific is separate;
124 -- The body of this package is target specific
126 ---------------------------------
127 -- Support for foreign threads --
128 ---------------------------------
130 function Register_Foreign_Thread (Thread : Thread_Id) return Task_Id;
131 -- Allocate and Initialize a new ATCB for the current Thread
133 function Register_Foreign_Thread
134 (Thread : Thread_Id) return Task_Id is separate;
136 -----------------------
137 -- Local Subprograms --
138 -----------------------
140 function To_Task_Id is
141 new Ada.Unchecked_Conversion (System.Address, Task_Id);
143 function To_Address is
144 new Ada.Unchecked_Conversion (Task_Id, System.Address);
146 function Get_Exc_Stack_Addr return Address;
147 -- Replace System.Soft_Links.Get_Exc_Stack_Addr_NT
149 procedure Timer_Sleep_AST (ID : Address);
150 -- Signal the condition variable when AST fires
152 procedure Timer_Sleep_AST (ID : Address) is
153 Result : Interfaces.C.int;
154 pragma Warnings (Off, Result);
155 Self_ID : constant Task_Id := To_Task_Id (ID);
157 Self_ID.Common.LL.AST_Pending := False;
158 Result := pthread_cond_signal_int_np (Self_ID.Common.LL.CV'Access);
159 pragma Assert (Result = 0);
166 -- The underlying thread system sets a guard page at the bottom of a thread
167 -- stack, so nothing is needed.
168 -- ??? Check the comment above
170 procedure Stack_Guard (T : ST.Task_Id; On : Boolean) is
171 pragma Unreferenced (T);
172 pragma Unreferenced (On);
181 function Get_Thread_Id (T : ST.Task_Id) return OSI.Thread_Id is
183 return T.Common.LL.Thread;
190 function Self return Task_Id renames Specific.Self;
192 ---------------------
193 -- Initialize_Lock --
194 ---------------------
196 -- Note: mutexes and cond_variables needed per-task basis are initialized
197 -- in Initialize_TCB and the Storage_Error is handled. Other mutexes (such
198 -- as RTS_Lock, Memory_Lock...) used in RTS is initialized before any
199 -- status change of RTS. Therefore rasing Storage_Error in the following
200 -- routines should be able to be handled safely.
202 procedure Initialize_Lock
203 (Prio : System.Any_Priority;
204 L : not null access Lock)
206 Attributes : aliased pthread_mutexattr_t;
207 Result : Interfaces.C.int;
210 Result := pthread_mutexattr_init (Attributes'Access);
211 pragma Assert (Result = 0 or else Result = ENOMEM);
213 if Result = ENOMEM then
218 L.Prio := Interfaces.C.int (Prio);
220 Result := pthread_mutex_init (L.L'Access, Attributes'Access);
221 pragma Assert (Result = 0 or else Result = ENOMEM);
223 if Result = ENOMEM then
227 Result := pthread_mutexattr_destroy (Attributes'Access);
228 pragma Assert (Result = 0);
231 procedure Initialize_Lock
232 (L : not null access RTS_Lock;
235 pragma Unreferenced (Level);
237 Attributes : aliased pthread_mutexattr_t;
238 Result : Interfaces.C.int;
241 Result := pthread_mutexattr_init (Attributes'Access);
242 pragma Assert (Result = 0 or else Result = ENOMEM);
244 if Result = ENOMEM then
248 -- Don't use, see comment in s-osinte.ads about ERRORCHECK mutexes???
249 -- Result := pthread_mutexattr_settype_np
250 -- (Attributes'Access, PTHREAD_MUTEX_ERRORCHECK_NP);
251 -- pragma Assert (Result = 0);
253 -- Result := pthread_mutexattr_setprotocol
254 -- (Attributes'Access, PTHREAD_PRIO_PROTECT);
255 -- pragma Assert (Result = 0);
257 -- Result := pthread_mutexattr_setprioceiling
258 -- (Attributes'Access, Interfaces.C.int (System.Any_Priority'Last));
259 -- pragma Assert (Result = 0);
261 Result := pthread_mutex_init (L, Attributes'Access);
263 pragma Assert (Result = 0 or else Result = ENOMEM);
265 if Result = ENOMEM then
269 Result := pthread_mutexattr_destroy (Attributes'Access);
270 pragma Assert (Result = 0);
277 procedure Finalize_Lock (L : not null access Lock) is
278 Result : Interfaces.C.int;
280 Result := pthread_mutex_destroy (L.L'Access);
281 pragma Assert (Result = 0);
284 procedure Finalize_Lock (L : not null access RTS_Lock) is
285 Result : Interfaces.C.int;
287 Result := pthread_mutex_destroy (L);
288 pragma Assert (Result = 0);
296 (L : not null access Lock;
297 Ceiling_Violation : out Boolean)
299 Self_ID : constant Task_Id := Self;
300 All_Tasks_Link : constant Task_Id := Self.Common.All_Tasks_Link;
301 Current_Prio : System.Any_Priority;
302 Result : Interfaces.C.int;
305 Current_Prio := Get_Priority (Self_ID);
307 -- If there is no other tasks, no need to check priorities
309 if All_Tasks_Link /= Null_Task
310 and then L.Prio < Interfaces.C.int (Current_Prio)
312 Ceiling_Violation := True;
316 Result := pthread_mutex_lock (L.L'Access);
317 pragma Assert (Result = 0);
319 Ceiling_Violation := False;
320 -- Why is this commented out ???
321 -- L.Prio_Save := Interfaces.C.int (Current_Prio);
322 -- Set_Priority (Self_ID, System.Any_Priority (L.Prio));
326 (L : not null access RTS_Lock;
327 Global_Lock : Boolean := False)
329 Result : Interfaces.C.int;
331 if not Single_Lock or else Global_Lock then
332 Result := pthread_mutex_lock (L);
333 pragma Assert (Result = 0);
337 procedure Write_Lock (T : Task_Id) is
338 Result : Interfaces.C.int;
340 if not Single_Lock then
341 Result := pthread_mutex_lock (T.Common.LL.L'Access);
342 pragma Assert (Result = 0);
351 (L : not null access Lock;
352 Ceiling_Violation : out Boolean)
355 Write_Lock (L, Ceiling_Violation);
362 procedure Unlock (L : not null access Lock) is
363 Result : Interfaces.C.int;
365 Result := pthread_mutex_unlock (L.L'Access);
366 pragma Assert (Result = 0);
370 (L : not null access RTS_Lock;
371 Global_Lock : Boolean := False)
373 Result : Interfaces.C.int;
375 if not Single_Lock or else Global_Lock then
376 Result := pthread_mutex_unlock (L);
377 pragma Assert (Result = 0);
381 procedure Unlock (T : Task_Id) is
382 Result : Interfaces.C.int;
384 if not Single_Lock then
385 Result := pthread_mutex_unlock (T.Common.LL.L'Access);
386 pragma Assert (Result = 0);
394 -- Dynamic priority ceilings are not supported by the underlying system
396 procedure Set_Ceiling
397 (L : not null access Lock;
398 Prio : System.Any_Priority)
400 pragma Unreferenced (L, Prio);
411 Reason : System.Tasking.Task_States)
413 pragma Unreferenced (Reason);
414 Result : Interfaces.C.int;
420 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
424 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
427 -- EINTR is not considered a failure
429 pragma Assert (Result = 0 or else Result = EINTR);
431 if Self_ID.Deferral_Level = 0
432 and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
435 raise Standard'Abort_Signal;
443 procedure Timed_Sleep
446 Mode : ST.Delay_Modes;
447 Reason : System.Tasking.Task_States;
448 Timedout : out Boolean;
449 Yielded : out Boolean)
451 pragma Unreferenced (Reason);
453 Sleep_Time : OS_Time;
454 Result : Interfaces.C.int;
455 Status : Cond_Value_Type;
457 -- The body below requires more comments ???
463 Sleep_Time := To_OS_Time (Time, Mode);
465 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
469 Self_ID.Common.LL.AST_Pending := True;
472 (Status, 0, Sleep_Time,
473 Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
475 if (Status and 1) /= 1 then
482 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
483 pragma Assert (Result = 0);
488 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
489 pragma Assert (Result = 0);
494 if not Self_ID.Common.LL.AST_Pending then
497 Sys_Cantim (Status, To_Address (Self_ID), 0);
498 pragma Assert ((Status and 1) = 1);
506 procedure Timed_Delay
509 Mode : ST.Delay_Modes)
511 Sleep_Time : OS_Time;
512 Result : Interfaces.C.int;
513 Status : Cond_Value_Type;
514 Yielded : Boolean := False;
521 -- More comments required in body below ???
523 Write_Lock (Self_ID);
525 if Time /= 0.0 or else Mode /= Relative then
526 Sleep_Time := To_OS_Time (Time, Mode);
528 if Mode = Relative or else OS_Clock < Sleep_Time then
529 Self_ID.Common.State := Delay_Sleep;
530 Self_ID.Common.LL.AST_Pending := True;
533 (Status, 0, Sleep_Time,
534 Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
536 -- Comment following test
538 if (Status and 1) /= 1 then
543 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
544 Sys_Cantim (Status, To_Address (Self_ID), 0);
545 pragma Assert ((Status and 1) = 1);
552 (Self_ID.Common.LL.CV'Access,
553 Single_RTS_Lock'Access);
554 pragma Assert (Result = 0);
558 (Self_ID.Common.LL.CV'Access,
559 Self_ID.Common.LL.L'Access);
560 pragma Assert (Result = 0);
565 exit when not Self_ID.Common.LL.AST_Pending;
568 Self_ID.Common.State := Runnable;
579 Result := sched_yield;
580 pragma Assert (Result = 0);
584 ---------------------
585 -- Monotonic_Clock --
586 ---------------------
588 function Monotonic_Clock return Duration
589 renames System.OS_Primitives.Monotonic_Clock;
595 function RT_Resolution return Duration is
597 -- Document origin of this magic constant ???
605 procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
606 pragma Unreferenced (Reason);
607 Result : Interfaces.C.int;
609 Result := pthread_cond_signal (T.Common.LL.CV'Access);
610 pragma Assert (Result = 0);
617 procedure Yield (Do_Yield : Boolean := True) is
618 Result : Interfaces.C.int;
619 pragma Unreferenced (Result);
622 Result := sched_yield;
630 procedure Set_Priority
632 Prio : System.Any_Priority;
633 Loss_Of_Inheritance : Boolean := False)
635 pragma Unreferenced (Loss_Of_Inheritance);
637 Result : Interfaces.C.int;
638 Param : aliased struct_sched_param;
640 function Get_Policy (Prio : System.Any_Priority) return Character;
641 pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
642 -- Get priority specific dispatching policy
644 Priority_Specific_Policy : constant Character := Get_Policy (Prio);
645 -- Upper case first character of the policy name corresponding to the
646 -- task as set by a Priority_Specific_Dispatching pragma.
649 T.Common.Current_Priority := Prio;
650 Param.sched_priority := Interfaces.C.int (Underlying_Priorities (Prio));
652 if Dispatching_Policy = 'R'
653 or else Priority_Specific_Policy = 'R'
654 or else Time_Slice_Val > 0
657 pthread_setschedparam
658 (T.Common.LL.Thread, SCHED_RR, Param'Access);
660 elsif Dispatching_Policy = 'F'
661 or else Priority_Specific_Policy = 'F'
662 or else Time_Slice_Val = 0
665 pthread_setschedparam
666 (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
669 -- SCHED_OTHER priorities are restricted to the range 8 - 15.
670 -- Since the translation from Underlying priorities results
671 -- in a range of 16 - 31, dividing by 2 gives the correct result.
673 Param.sched_priority := Param.sched_priority / 2;
675 pthread_setschedparam
676 (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
679 pragma Assert (Result = 0);
686 function Get_Priority (T : Task_Id) return System.Any_Priority is
688 return T.Common.Current_Priority;
695 procedure Enter_Task (Self_ID : Task_Id) is
697 Self_ID.Common.LL.Thread := pthread_self;
699 Specific.Set (Self_ID);
703 for J in Known_Tasks'Range loop
704 if Known_Tasks (J) = null then
705 Known_Tasks (J) := Self_ID;
706 Self_ID.Known_Tasks_Index := J;
718 function New_ATCB (Entry_Num : Task_Entry_Index) return Task_Id is
720 return new Ada_Task_Control_Block (Entry_Num);
727 function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
729 -----------------------------
730 -- Register_Foreign_Thread --
731 -----------------------------
733 function Register_Foreign_Thread return Task_Id is
735 if Is_Valid_Task then
738 return Register_Foreign_Thread (pthread_self);
740 end Register_Foreign_Thread;
746 procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
747 Mutex_Attr : aliased pthread_mutexattr_t;
748 Result : Interfaces.C.int;
749 Cond_Attr : aliased pthread_condattr_t;
752 -- More comments required in body below ???
754 if not Single_Lock then
755 Result := pthread_mutexattr_init (Mutex_Attr'Access);
756 pragma Assert (Result = 0 or else Result = ENOMEM);
761 (Self_ID.Common.LL.L'Access, Mutex_Attr'Access);
762 pragma Assert (Result = 0 or else Result = ENOMEM);
770 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
771 pragma Assert (Result = 0);
774 Result := pthread_condattr_init (Cond_Attr'Access);
775 pragma Assert (Result = 0 or else Result = ENOMEM);
780 (Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
781 pragma Assert (Result = 0 or else Result = ENOMEM);
786 Self_ID.Common.LL.Exc_Stack_Ptr := new Exc_Stack_T;
789 if not Single_Lock then
790 Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
791 pragma Assert (Result = 0);
797 Result := pthread_condattr_destroy (Cond_Attr'Access);
798 pragma Assert (Result = 0);
801 ------------------------
802 -- Get_Exc_Stack_Addr --
803 ------------------------
805 function Get_Exc_Stack_Addr return Address is
807 return Self.Common.LL.Exc_Stack_Ptr (Exc_Stack_T'Last)'Address;
808 end Get_Exc_Stack_Addr;
814 procedure Create_Task
816 Wrapper : System.Address;
817 Stack_Size : System.Parameters.Size_Type;
818 Priority : System.Any_Priority;
819 Succeeded : out Boolean)
821 Attributes : aliased pthread_attr_t;
822 Result : Interfaces.C.int;
824 function Thread_Body_Access is new
825 Ada.Unchecked_Conversion (System.Address, Thread_Body);
828 -- Since the initial signal mask of a thread is inherited from the
829 -- creator, we need to set our local signal mask mask all signals
830 -- during the creation operation, to make sure the new thread is
831 -- not disturbed by signals before it has set its own Task_Id.
833 Result := pthread_attr_init (Attributes'Access);
834 pragma Assert (Result = 0 or else Result = ENOMEM);
841 Result := pthread_attr_setdetachstate
842 (Attributes'Access, PTHREAD_CREATE_DETACHED);
843 pragma Assert (Result = 0);
845 Result := pthread_attr_setstacksize
846 (Attributes'Access, Interfaces.C.size_t (Stack_Size));
847 pragma Assert (Result = 0);
849 -- This call may be unnecessary, not sure. ???
852 pthread_attr_setinheritsched
853 (Attributes'Access, PTHREAD_EXPLICIT_SCHED);
854 pragma Assert (Result = 0);
858 (T.Common.LL.Thread'Access,
860 Thread_Body_Access (Wrapper),
863 -- ENOMEM is a valid run-time error -- do not shut down
865 pragma Assert (Result = 0
866 or else Result = EAGAIN or else Result = ENOMEM);
868 Succeeded := Result = 0;
870 Result := pthread_attr_destroy (Attributes'Access);
871 pragma Assert (Result = 0);
874 Set_Priority (T, Priority);
882 procedure Finalize_TCB (T : Task_Id) is
883 Result : Interfaces.C.int;
885 Is_Self : constant Boolean := T = Self;
887 procedure Free is new
888 Ada.Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
890 procedure Free is new Ada.Unchecked_Deallocation
891 (Exc_Stack_T, Exc_Stack_Ptr_T);
894 if not Single_Lock then
895 Result := pthread_mutex_destroy (T.Common.LL.L'Access);
896 pragma Assert (Result = 0);
899 Result := pthread_cond_destroy (T.Common.LL.CV'Access);
900 pragma Assert (Result = 0);
902 if T.Known_Tasks_Index /= -1 then
903 Known_Tasks (T.Known_Tasks_Index) := null;
906 Free (T.Common.LL.Exc_Stack_Ptr);
918 procedure Exit_Task is
927 procedure Abort_Task (T : Task_Id) is
929 -- Interrupt Server_Tasks may be waiting on an event flag
931 if T.Common.State = Interrupt_Server_Blocked_On_Event_Flag then
932 Wakeup (T, Interrupt_Server_Blocked_On_Event_Flag);
940 procedure Initialize (S : in out Suspension_Object) is
941 Mutex_Attr : aliased pthread_mutexattr_t;
942 Cond_Attr : aliased pthread_condattr_t;
943 Result : Interfaces.C.int;
945 -- Initialize internal state (always to False (D.10 (6)))
950 -- Initialize internal mutex
952 Result := pthread_mutexattr_init (Mutex_Attr'Access);
953 pragma Assert (Result = 0 or else Result = ENOMEM);
955 if Result = ENOMEM then
959 Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
960 pragma Assert (Result = 0 or else Result = ENOMEM);
962 if Result = ENOMEM then
963 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
964 pragma Assert (Result = 0);
969 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
970 pragma Assert (Result = 0);
972 -- Initialize internal condition variable
974 Result := pthread_condattr_init (Cond_Attr'Access);
975 pragma Assert (Result = 0 or else Result = ENOMEM);
978 Result := pthread_mutex_destroy (S.L'Access);
979 pragma Assert (Result = 0);
981 if Result = ENOMEM then
986 Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
987 pragma Assert (Result = 0 or else Result = ENOMEM);
990 Result := pthread_mutex_destroy (S.L'Access);
991 pragma Assert (Result = 0);
993 if Result = ENOMEM then
994 Result := pthread_condattr_destroy (Cond_Attr'Access);
995 pragma Assert (Result = 0);
1001 Result := pthread_condattr_destroy (Cond_Attr'Access);
1002 pragma Assert (Result = 0);
1009 procedure Finalize (S : in out Suspension_Object) is
1010 Result : Interfaces.C.int;
1013 -- Destroy internal mutex
1015 Result := pthread_mutex_destroy (S.L'Access);
1016 pragma Assert (Result = 0);
1018 -- Destroy internal condition variable
1020 Result := pthread_cond_destroy (S.CV'Access);
1021 pragma Assert (Result = 0);
1028 function Current_State (S : Suspension_Object) return Boolean is
1030 -- We do not want to use lock on this read operation. State is marked
1031 -- as Atomic so that we ensure that the value retrieved is correct.
1040 procedure Set_False (S : in out Suspension_Object) is
1041 Result : Interfaces.C.int;
1044 SSL.Abort_Defer.all;
1046 Result := pthread_mutex_lock (S.L'Access);
1047 pragma Assert (Result = 0);
1051 Result := pthread_mutex_unlock (S.L'Access);
1052 pragma Assert (Result = 0);
1054 SSL.Abort_Undefer.all;
1061 procedure Set_True (S : in out Suspension_Object) is
1062 Result : Interfaces.C.int;
1065 SSL.Abort_Defer.all;
1067 Result := pthread_mutex_lock (S.L'Access);
1068 pragma Assert (Result = 0);
1070 -- If there is already a task waiting on this suspension object then
1071 -- we resume it, leaving the state of the suspension object to False,
1072 -- as specified in (RM D.10(9)), otherwise leave state set to True.
1078 Result := pthread_cond_signal (S.CV'Access);
1079 pragma Assert (Result = 0);
1085 Result := pthread_mutex_unlock (S.L'Access);
1086 pragma Assert (Result = 0);
1088 SSL.Abort_Undefer.all;
1091 ------------------------
1092 -- Suspend_Until_True --
1093 ------------------------
1095 procedure Suspend_Until_True (S : in out Suspension_Object) is
1096 Result : Interfaces.C.int;
1099 SSL.Abort_Defer.all;
1101 Result := pthread_mutex_lock (S.L'Access);
1102 pragma Assert (Result = 0);
1106 -- Program_Error must be raised upon calling Suspend_Until_True
1107 -- if another task is already waiting on that suspension object
1110 Result := pthread_mutex_unlock (S.L'Access);
1111 pragma Assert (Result = 0);
1113 SSL.Abort_Undefer.all;
1115 raise Program_Error;
1118 -- Suspend the task if the state is False. Otherwise, the task
1119 -- continues its execution, and the state of the suspension object
1120 -- is set to False (ARM D.10 par. 9).
1126 Result := pthread_cond_wait (S.CV'Access, S.L'Access);
1129 Result := pthread_mutex_unlock (S.L'Access);
1130 pragma Assert (Result = 0);
1132 SSL.Abort_Undefer.all;
1134 end Suspend_Until_True;
1142 function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
1143 pragma Unreferenced (Self_ID);
1148 --------------------
1149 -- Check_No_Locks --
1150 --------------------
1152 function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
1153 pragma Unreferenced (Self_ID);
1158 ----------------------
1159 -- Environment_Task --
1160 ----------------------
1162 function Environment_Task return Task_Id is
1164 return Environment_Task_Id;
1165 end Environment_Task;
1171 procedure Lock_RTS is
1173 Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
1180 procedure Unlock_RTS is
1182 Unlock (Single_RTS_Lock'Access, Global_Lock => True);
1189 function Suspend_Task
1191 Thread_Self : Thread_Id) return Boolean
1193 pragma Unreferenced (T);
1194 pragma Unreferenced (Thread_Self);
1203 function Resume_Task
1205 Thread_Self : Thread_Id) return Boolean
1207 pragma Unreferenced (T);
1208 pragma Unreferenced (Thread_Self);
1213 --------------------
1214 -- Stop_All_Tasks --
1215 --------------------
1217 procedure Stop_All_Tasks is
1226 function Stop_Task (T : ST.Task_Id) return Boolean is
1227 pragma Unreferenced (T);
1236 function Continue_Task (T : ST.Task_Id) return Boolean is
1237 pragma Unreferenced (T);
1246 procedure Initialize (Environment_Task : Task_Id) is
1248 Environment_Task_Id := Environment_Task;
1250 SSL.Get_Exc_Stack_Addr := Get_Exc_Stack_Addr'Access;
1252 -- Initialize the lock used to synchronize chain of all ATCBs
1254 Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
1256 Specific.Initialize (Environment_Task);
1258 Enter_Task (Environment_Task);
1261 end System.Task_Primitives.Operations;