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 Self_ID : constant Task_Id := To_Task_Id (ID);
156 Self_ID.Common.LL.AST_Pending := False;
157 Result := pthread_cond_signal_int_np (Self_ID.Common.LL.CV'Access);
158 pragma Assert (Result = 0);
165 -- The underlying thread system sets a guard page at the bottom of a thread
166 -- stack, so nothing is needed.
167 -- ??? Check the comment above
169 procedure Stack_Guard (T : ST.Task_Id; On : Boolean) is
170 pragma Unreferenced (T);
171 pragma Unreferenced (On);
180 function Get_Thread_Id (T : ST.Task_Id) return OSI.Thread_Id is
182 return T.Common.LL.Thread;
189 function Self return Task_Id renames Specific.Self;
191 ---------------------
192 -- Initialize_Lock --
193 ---------------------
195 -- Note: mutexes and cond_variables needed per-task basis are initialized
196 -- in Initialize_TCB and the Storage_Error is handled. Other mutexes (such
197 -- as RTS_Lock, Memory_Lock...) used in RTS is initialized before any
198 -- status change of RTS. Therefore rasing Storage_Error in the following
199 -- routines should be able to be handled safely.
201 procedure Initialize_Lock
202 (Prio : System.Any_Priority;
203 L : not null access Lock)
205 Attributes : aliased pthread_mutexattr_t;
206 Result : Interfaces.C.int;
209 Result := pthread_mutexattr_init (Attributes'Access);
210 pragma Assert (Result = 0 or else Result = ENOMEM);
212 if Result = ENOMEM then
217 L.Prio := Interfaces.C.int (Prio);
219 Result := pthread_mutex_init (L.L'Access, Attributes'Access);
220 pragma Assert (Result = 0 or else Result = ENOMEM);
222 if Result = ENOMEM then
226 Result := pthread_mutexattr_destroy (Attributes'Access);
227 pragma Assert (Result = 0);
230 procedure Initialize_Lock
231 (L : not null access RTS_Lock;
234 pragma Unreferenced (Level);
236 Attributes : aliased pthread_mutexattr_t;
237 Result : Interfaces.C.int;
240 Result := pthread_mutexattr_init (Attributes'Access);
241 pragma Assert (Result = 0 or else Result = ENOMEM);
243 if Result = ENOMEM then
247 -- Don't use, see comment in s-osinte.ads about ERRORCHECK mutexes???
248 -- Result := pthread_mutexattr_settype_np
249 -- (Attributes'Access, PTHREAD_MUTEX_ERRORCHECK_NP);
250 -- pragma Assert (Result = 0);
252 -- Result := pthread_mutexattr_setprotocol
253 -- (Attributes'Access, PTHREAD_PRIO_PROTECT);
254 -- pragma Assert (Result = 0);
256 -- Result := pthread_mutexattr_setprioceiling
257 -- (Attributes'Access, Interfaces.C.int (System.Any_Priority'Last));
258 -- pragma Assert (Result = 0);
260 Result := pthread_mutex_init (L, Attributes'Access);
262 pragma Assert (Result = 0 or else Result = ENOMEM);
264 if Result = ENOMEM then
268 Result := pthread_mutexattr_destroy (Attributes'Access);
269 pragma Assert (Result = 0);
276 procedure Finalize_Lock (L : not null access Lock) is
277 Result : Interfaces.C.int;
279 Result := pthread_mutex_destroy (L.L'Access);
280 pragma Assert (Result = 0);
283 procedure Finalize_Lock (L : not null access RTS_Lock) is
284 Result : Interfaces.C.int;
286 Result := pthread_mutex_destroy (L);
287 pragma Assert (Result = 0);
295 (L : not null access Lock;
296 Ceiling_Violation : out Boolean)
298 Self_ID : constant Task_Id := Self;
299 All_Tasks_Link : constant Task_Id := Self.Common.All_Tasks_Link;
300 Current_Prio : System.Any_Priority;
301 Result : Interfaces.C.int;
304 Current_Prio := Get_Priority (Self_ID);
306 -- If there is no other tasks, no need to check priorities
308 if All_Tasks_Link /= Null_Task
309 and then L.Prio < Interfaces.C.int (Current_Prio)
311 Ceiling_Violation := True;
315 Result := pthread_mutex_lock (L.L'Access);
316 pragma Assert (Result = 0);
318 Ceiling_Violation := False;
319 -- Why is this commented out ???
320 -- L.Prio_Save := Interfaces.C.int (Current_Prio);
321 -- Set_Priority (Self_ID, System.Any_Priority (L.Prio));
325 (L : not null access RTS_Lock;
326 Global_Lock : Boolean := False)
328 Result : Interfaces.C.int;
330 if not Single_Lock or else Global_Lock then
331 Result := pthread_mutex_lock (L);
332 pragma Assert (Result = 0);
336 procedure Write_Lock (T : Task_Id) is
337 Result : Interfaces.C.int;
339 if not Single_Lock then
340 Result := pthread_mutex_lock (T.Common.LL.L'Access);
341 pragma Assert (Result = 0);
350 (L : not null access Lock;
351 Ceiling_Violation : out Boolean)
354 Write_Lock (L, Ceiling_Violation);
361 procedure Unlock (L : not null access Lock) is
362 Result : Interfaces.C.int;
364 Result := pthread_mutex_unlock (L.L'Access);
365 pragma Assert (Result = 0);
369 (L : not null access RTS_Lock;
370 Global_Lock : Boolean := False)
372 Result : Interfaces.C.int;
374 if not Single_Lock or else Global_Lock then
375 Result := pthread_mutex_unlock (L);
376 pragma Assert (Result = 0);
380 procedure Unlock (T : Task_Id) is
381 Result : Interfaces.C.int;
383 if not Single_Lock then
384 Result := pthread_mutex_unlock (T.Common.LL.L'Access);
385 pragma Assert (Result = 0);
393 -- Dynamic priority ceilings are not supported by the underlying system
395 procedure Set_Ceiling
396 (L : not null access Lock;
397 Prio : System.Any_Priority)
399 pragma Unreferenced (L, Prio);
410 Reason : System.Tasking.Task_States)
412 pragma Unreferenced (Reason);
413 Result : Interfaces.C.int;
419 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
423 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
426 -- EINTR is not considered a failure
428 pragma Assert (Result = 0 or else Result = EINTR);
430 if Self_ID.Deferral_Level = 0
431 and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
434 raise Standard'Abort_Signal;
442 procedure Timed_Sleep
445 Mode : ST.Delay_Modes;
446 Reason : System.Tasking.Task_States;
447 Timedout : out Boolean;
448 Yielded : out Boolean)
450 pragma Unreferenced (Reason);
452 Sleep_Time : OS_Time;
453 Result : Interfaces.C.int;
454 Status : Cond_Value_Type;
456 -- The body below requires more comments ???
462 Sleep_Time := To_OS_Time (Time, Mode);
464 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
468 Self_ID.Common.LL.AST_Pending := True;
471 (Status, 0, Sleep_Time,
472 Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
474 if (Status and 1) /= 1 then
481 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
482 pragma Assert (Result = 0);
487 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
488 pragma Assert (Result = 0);
493 if not Self_ID.Common.LL.AST_Pending then
496 Sys_Cantim (Status, To_Address (Self_ID), 0);
497 pragma Assert ((Status and 1) = 1);
505 procedure Timed_Delay
508 Mode : ST.Delay_Modes)
510 Sleep_Time : OS_Time;
511 Result : Interfaces.C.int;
512 Status : Cond_Value_Type;
513 Yielded : Boolean := False;
520 -- More comments required in body below ???
522 Write_Lock (Self_ID);
524 if Time /= 0.0 or else Mode /= Relative then
525 Sleep_Time := To_OS_Time (Time, Mode);
527 if Mode = Relative or else OS_Clock < Sleep_Time then
528 Self_ID.Common.State := Delay_Sleep;
529 Self_ID.Common.LL.AST_Pending := True;
532 (Status, 0, Sleep_Time,
533 Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
535 -- Comment following test
537 if (Status and 1) /= 1 then
542 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
543 Sys_Cantim (Status, To_Address (Self_ID), 0);
544 pragma Assert ((Status and 1) = 1);
551 (Self_ID.Common.LL.CV'Access,
552 Single_RTS_Lock'Access);
553 pragma Assert (Result = 0);
557 (Self_ID.Common.LL.CV'Access,
558 Self_ID.Common.LL.L'Access);
559 pragma Assert (Result = 0);
564 exit when not Self_ID.Common.LL.AST_Pending;
567 Self_ID.Common.State := Runnable;
578 Result := sched_yield;
579 pragma Assert (Result = 0);
583 ---------------------
584 -- Monotonic_Clock --
585 ---------------------
587 function Monotonic_Clock return Duration
588 renames System.OS_Primitives.Monotonic_Clock;
594 function RT_Resolution return Duration is
596 -- Document origin of this magic constant ???
604 procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
605 pragma Unreferenced (Reason);
606 Result : Interfaces.C.int;
608 Result := pthread_cond_signal (T.Common.LL.CV'Access);
609 pragma Assert (Result = 0);
616 procedure Yield (Do_Yield : Boolean := True) is
617 Result : Interfaces.C.int;
618 pragma Unreferenced (Result);
621 Result := sched_yield;
629 procedure Set_Priority
631 Prio : System.Any_Priority;
632 Loss_Of_Inheritance : Boolean := False)
634 pragma Unreferenced (Loss_Of_Inheritance);
636 Result : Interfaces.C.int;
637 Param : aliased struct_sched_param;
639 function Get_Policy (Prio : System.Any_Priority) return Character;
640 pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
641 -- Get priority specific dispatching policy
643 Priority_Specific_Policy : constant Character := Get_Policy (Prio);
644 -- Upper case first character of the policy name corresponding to the
645 -- task as set by a Priority_Specific_Dispatching pragma.
648 T.Common.Current_Priority := Prio;
649 Param.sched_priority := Interfaces.C.int (Underlying_Priorities (Prio));
651 if Dispatching_Policy = 'R'
652 or else Priority_Specific_Policy = 'R'
653 or else Time_Slice_Val > 0
656 pthread_setschedparam
657 (T.Common.LL.Thread, SCHED_RR, Param'Access);
659 elsif Dispatching_Policy = 'F'
660 or else Priority_Specific_Policy = 'F'
661 or else Time_Slice_Val = 0
664 pthread_setschedparam
665 (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
668 -- SCHED_OTHER priorities are restricted to the range 8 - 15.
669 -- Since the translation from Underlying priorities results
670 -- in a range of 16 - 31, dividing by 2 gives the correct result.
672 Param.sched_priority := Param.sched_priority / 2;
674 pthread_setschedparam
675 (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
678 pragma Assert (Result = 0);
685 function Get_Priority (T : Task_Id) return System.Any_Priority is
687 return T.Common.Current_Priority;
694 procedure Enter_Task (Self_ID : Task_Id) is
696 Self_ID.Common.LL.Thread := pthread_self;
698 Specific.Set (Self_ID);
702 for J in Known_Tasks'Range loop
703 if Known_Tasks (J) = null then
704 Known_Tasks (J) := Self_ID;
705 Self_ID.Known_Tasks_Index := J;
717 function New_ATCB (Entry_Num : Task_Entry_Index) return Task_Id is
719 return new Ada_Task_Control_Block (Entry_Num);
726 function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
728 -----------------------------
729 -- Register_Foreign_Thread --
730 -----------------------------
732 function Register_Foreign_Thread return Task_Id is
734 if Is_Valid_Task then
737 return Register_Foreign_Thread (pthread_self);
739 end Register_Foreign_Thread;
745 procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
746 Mutex_Attr : aliased pthread_mutexattr_t;
747 Result : Interfaces.C.int;
748 Cond_Attr : aliased pthread_condattr_t;
751 -- More comments required in body below ???
753 if not Single_Lock then
754 Result := pthread_mutexattr_init (Mutex_Attr'Access);
755 pragma Assert (Result = 0 or else Result = ENOMEM);
760 (Self_ID.Common.LL.L'Access, Mutex_Attr'Access);
761 pragma Assert (Result = 0 or else Result = ENOMEM);
769 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
770 pragma Assert (Result = 0);
773 Result := pthread_condattr_init (Cond_Attr'Access);
774 pragma Assert (Result = 0 or else Result = ENOMEM);
779 (Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
780 pragma Assert (Result = 0 or else Result = ENOMEM);
785 Self_ID.Common.LL.Exc_Stack_Ptr := new Exc_Stack_T;
788 if not Single_Lock then
789 Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
790 pragma Assert (Result = 0);
796 Result := pthread_condattr_destroy (Cond_Attr'Access);
797 pragma Assert (Result = 0);
800 ------------------------
801 -- Get_Exc_Stack_Addr --
802 ------------------------
804 function Get_Exc_Stack_Addr return Address is
806 return Self.Common.LL.Exc_Stack_Ptr (Exc_Stack_T'Last)'Address;
807 end Get_Exc_Stack_Addr;
813 procedure Create_Task
815 Wrapper : System.Address;
816 Stack_Size : System.Parameters.Size_Type;
817 Priority : System.Any_Priority;
818 Succeeded : out Boolean)
820 Attributes : aliased pthread_attr_t;
821 Result : Interfaces.C.int;
823 function Thread_Body_Access is new
824 Ada.Unchecked_Conversion (System.Address, Thread_Body);
827 -- Since the initial signal mask of a thread is inherited from the
828 -- creator, we need to set our local signal mask mask all signals
829 -- during the creation operation, to make sure the new thread is
830 -- not disturbed by signals before it has set its own Task_Id.
832 Result := pthread_attr_init (Attributes'Access);
833 pragma Assert (Result = 0 or else Result = ENOMEM);
840 Result := pthread_attr_setdetachstate
841 (Attributes'Access, PTHREAD_CREATE_DETACHED);
842 pragma Assert (Result = 0);
844 Result := pthread_attr_setstacksize
845 (Attributes'Access, Interfaces.C.size_t (Stack_Size));
846 pragma Assert (Result = 0);
848 -- This call may be unnecessary, not sure. ???
851 pthread_attr_setinheritsched
852 (Attributes'Access, PTHREAD_EXPLICIT_SCHED);
853 pragma Assert (Result = 0);
857 (T.Common.LL.Thread'Access,
859 Thread_Body_Access (Wrapper),
862 -- ENOMEM is a valid run-time error -- do not shut down
864 pragma Assert (Result = 0
865 or else Result = EAGAIN or else Result = ENOMEM);
867 Succeeded := Result = 0;
869 Result := pthread_attr_destroy (Attributes'Access);
870 pragma Assert (Result = 0);
873 Set_Priority (T, Priority);
881 procedure Finalize_TCB (T : Task_Id) is
882 Result : Interfaces.C.int;
884 Is_Self : constant Boolean := T = Self;
886 procedure Free is new
887 Ada.Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
889 procedure Free is new Ada.Unchecked_Deallocation
890 (Exc_Stack_T, Exc_Stack_Ptr_T);
893 if not Single_Lock then
894 Result := pthread_mutex_destroy (T.Common.LL.L'Access);
895 pragma Assert (Result = 0);
898 Result := pthread_cond_destroy (T.Common.LL.CV'Access);
899 pragma Assert (Result = 0);
901 if T.Known_Tasks_Index /= -1 then
902 Known_Tasks (T.Known_Tasks_Index) := null;
905 Free (T.Common.LL.Exc_Stack_Ptr);
917 procedure Exit_Task is
926 procedure Abort_Task (T : Task_Id) is
928 -- Interrupt Server_Tasks may be waiting on an event flag
930 if T.Common.State = Interrupt_Server_Blocked_On_Event_Flag then
931 Wakeup (T, Interrupt_Server_Blocked_On_Event_Flag);
939 procedure Initialize (S : in out Suspension_Object) is
940 Mutex_Attr : aliased pthread_mutexattr_t;
941 Cond_Attr : aliased pthread_condattr_t;
942 Result : Interfaces.C.int;
944 -- Initialize internal state (always to False (D.10 (6)))
949 -- Initialize internal mutex
951 Result := pthread_mutexattr_init (Mutex_Attr'Access);
952 pragma Assert (Result = 0 or else Result = ENOMEM);
954 if Result = ENOMEM then
958 Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
959 pragma Assert (Result = 0 or else Result = ENOMEM);
961 if Result = ENOMEM then
962 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
963 pragma Assert (Result = 0);
968 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
969 pragma Assert (Result = 0);
971 -- Initialize internal condition variable
973 Result := pthread_condattr_init (Cond_Attr'Access);
974 pragma Assert (Result = 0 or else Result = ENOMEM);
977 Result := pthread_mutex_destroy (S.L'Access);
978 pragma Assert (Result = 0);
980 if Result = ENOMEM then
985 Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
986 pragma Assert (Result = 0 or else Result = ENOMEM);
989 Result := pthread_mutex_destroy (S.L'Access);
990 pragma Assert (Result = 0);
992 if Result = ENOMEM then
993 Result := pthread_condattr_destroy (Cond_Attr'Access);
994 pragma Assert (Result = 0);
1000 Result := pthread_condattr_destroy (Cond_Attr'Access);
1001 pragma Assert (Result = 0);
1008 procedure Finalize (S : in out Suspension_Object) is
1009 Result : Interfaces.C.int;
1012 -- Destroy internal mutex
1014 Result := pthread_mutex_destroy (S.L'Access);
1015 pragma Assert (Result = 0);
1017 -- Destroy internal condition variable
1019 Result := pthread_cond_destroy (S.CV'Access);
1020 pragma Assert (Result = 0);
1027 function Current_State (S : Suspension_Object) return Boolean is
1029 -- We do not want to use lock on this read operation. State is marked
1030 -- as Atomic so that we ensure that the value retrieved is correct.
1039 procedure Set_False (S : in out Suspension_Object) is
1040 Result : Interfaces.C.int;
1043 SSL.Abort_Defer.all;
1045 Result := pthread_mutex_lock (S.L'Access);
1046 pragma Assert (Result = 0);
1050 Result := pthread_mutex_unlock (S.L'Access);
1051 pragma Assert (Result = 0);
1053 SSL.Abort_Undefer.all;
1060 procedure Set_True (S : in out Suspension_Object) is
1061 Result : Interfaces.C.int;
1064 SSL.Abort_Defer.all;
1066 Result := pthread_mutex_lock (S.L'Access);
1067 pragma Assert (Result = 0);
1069 -- If there is already a task waiting on this suspension object then
1070 -- we resume it, leaving the state of the suspension object to False,
1071 -- as specified in (RM D.10(9)), otherwise leave state set to True.
1077 Result := pthread_cond_signal (S.CV'Access);
1078 pragma Assert (Result = 0);
1084 Result := pthread_mutex_unlock (S.L'Access);
1085 pragma Assert (Result = 0);
1087 SSL.Abort_Undefer.all;
1090 ------------------------
1091 -- Suspend_Until_True --
1092 ------------------------
1094 procedure Suspend_Until_True (S : in out Suspension_Object) is
1095 Result : Interfaces.C.int;
1098 SSL.Abort_Defer.all;
1100 Result := pthread_mutex_lock (S.L'Access);
1101 pragma Assert (Result = 0);
1105 -- Program_Error must be raised upon calling Suspend_Until_True
1106 -- if another task is already waiting on that suspension object
1109 Result := pthread_mutex_unlock (S.L'Access);
1110 pragma Assert (Result = 0);
1112 SSL.Abort_Undefer.all;
1114 raise Program_Error;
1117 -- Suspend the task if the state is False. Otherwise, the task
1118 -- continues its execution, and the state of the suspension object
1119 -- is set to False (ARM D.10 par. 9).
1125 Result := pthread_cond_wait (S.CV'Access, S.L'Access);
1128 Result := pthread_mutex_unlock (S.L'Access);
1129 pragma Assert (Result = 0);
1131 SSL.Abort_Undefer.all;
1133 end Suspend_Until_True;
1141 function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
1142 pragma Unreferenced (Self_ID);
1147 --------------------
1148 -- Check_No_Locks --
1149 --------------------
1151 function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
1152 pragma Unreferenced (Self_ID);
1157 ----------------------
1158 -- Environment_Task --
1159 ----------------------
1161 function Environment_Task return Task_Id is
1163 return Environment_Task_Id;
1164 end Environment_Task;
1170 procedure Lock_RTS is
1172 Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
1179 procedure Unlock_RTS is
1181 Unlock (Single_RTS_Lock'Access, Global_Lock => True);
1188 function Suspend_Task
1190 Thread_Self : Thread_Id) return Boolean
1192 pragma Unreferenced (T);
1193 pragma Unreferenced (Thread_Self);
1202 function Resume_Task
1204 Thread_Self : Thread_Id) return Boolean
1206 pragma Unreferenced (T);
1207 pragma Unreferenced (Thread_Self);
1212 --------------------
1213 -- Stop_All_Tasks --
1214 --------------------
1216 procedure Stop_All_Tasks is
1225 function Stop_Task (T : ST.Task_Id) return Boolean is
1226 pragma Unreferenced (T);
1235 function Continue_Task (T : ST.Task_Id) return Boolean is
1236 pragma Unreferenced (T);
1245 procedure Initialize (Environment_Task : Task_Id) is
1247 Environment_Task_Id := Environment_Task;
1249 SSL.Get_Exc_Stack_Addr := Get_Exc_Stack_Addr'Access;
1251 -- Initialize the lock used to synchronize chain of all ATCBs
1253 Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
1255 Specific.Initialize (Environment_Task);
1257 Enter_Task (Environment_Task);
1260 end System.Task_Primitives.Operations;