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-2005, 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.Parameters;
56 with System.Soft_Links;
57 -- used for Get_Exc_Stack_Addr
59 with Unchecked_Conversion;
60 with Unchecked_Deallocation;
62 package body System.Task_Primitives.Operations is
64 use System.Tasking.Debug;
67 use System.OS_Interface;
68 use System.Parameters;
69 use System.OS_Primitives;
70 use type System.OS_Primitives.OS_Time;
72 package SSL renames System.Soft_Links;
78 -- The followings are logically constants, but need to be initialized
81 Single_RTS_Lock : aliased RTS_Lock;
82 -- This is a lock to allow only one thread of control in the RTS at
83 -- a time; it is used to execute in mutual exclusion from all other tasks.
84 -- Used mainly in Single_Lock mode, but also to protect All_Tasks_List
86 ATCB_Key : aliased pthread_key_t;
87 -- Key used to find the Ada Task_Id associated with a thread
89 Environment_Task_Id : Task_Id;
90 -- A variable to hold Task_Id for the environment task.
92 Time_Slice_Val : Integer;
93 pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
95 Dispatching_Policy : Character;
96 pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
98 Foreign_Task_Elaborated : aliased Boolean := True;
99 -- Used to identified fake tasks (i.e., non-Ada Threads).
107 procedure Initialize (Environment_Task : Task_Id);
108 pragma Inline (Initialize);
109 -- Initialize various data needed by this package.
111 function Is_Valid_Task return Boolean;
112 pragma Inline (Is_Valid_Task);
113 -- Does executing thread have a TCB?
115 procedure Set (Self_Id : Task_Id);
117 -- Set the self id for the current task
119 function Self return Task_Id;
120 pragma Inline (Self);
121 -- Return a pointer to the Ada Task Control Block of the calling task
125 package body Specific is separate;
126 -- The body of this package is target specific.
128 ---------------------------------
129 -- Support for foreign threads --
130 ---------------------------------
132 function Register_Foreign_Thread (Thread : Thread_Id) return Task_Id;
133 -- Allocate and Initialize a new ATCB for the current Thread
135 function Register_Foreign_Thread
136 (Thread : Thread_Id) return Task_Id is separate;
138 -----------------------
139 -- Local Subprograms --
140 -----------------------
142 function To_Task_Id is new Unchecked_Conversion (System.Address, Task_Id);
144 function To_Address is new 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
166 -- bottom of a thread 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
196 -- initialized in Initialize_TCB and the Storage_Error is
197 -- handled. Other mutexes (such as RTS_Lock, Memory_Lock...)
198 -- used in RTS is initialized before any status change of RTS.
199 -- Therefore rasing Storage_Error in the following routines
200 -- should be able to be handled safely.
202 procedure Initialize_Lock (Prio : System.Any_Priority; L : access Lock) is
203 Attributes : aliased pthread_mutexattr_t;
204 Result : Interfaces.C.int;
207 Result := pthread_mutexattr_init (Attributes'Access);
208 pragma Assert (Result = 0 or else Result = ENOMEM);
210 if Result = ENOMEM then
215 L.Prio := Interfaces.C.int (Prio);
217 Result := pthread_mutex_init (L.L'Access, Attributes'Access);
218 pragma Assert (Result = 0 or else Result = ENOMEM);
220 if Result = ENOMEM then
224 Result := pthread_mutexattr_destroy (Attributes'Access);
225 pragma Assert (Result = 0);
228 procedure Initialize_Lock (L : access RTS_Lock; Level : Lock_Level) is
229 pragma Unreferenced (Level);
231 Attributes : aliased pthread_mutexattr_t;
232 Result : Interfaces.C.int;
235 Result := pthread_mutexattr_init (Attributes'Access);
236 pragma Assert (Result = 0 or else Result = ENOMEM);
238 if Result = ENOMEM then
242 -- Don't use, see comment in s-osinte.ads about ERRORCHECK mutexes???
243 -- Result := pthread_mutexattr_settype_np
244 -- (Attributes'Access, PTHREAD_MUTEX_ERRORCHECK_NP);
245 -- pragma Assert (Result = 0);
247 -- Result := pthread_mutexattr_setprotocol
248 -- (Attributes'Access, PTHREAD_PRIO_PROTECT);
249 -- pragma Assert (Result = 0);
251 -- Result := pthread_mutexattr_setprioceiling
252 -- (Attributes'Access, Interfaces.C.int (System.Any_Priority'Last));
253 -- pragma Assert (Result = 0);
255 Result := pthread_mutex_init (L, Attributes'Access);
257 pragma Assert (Result = 0 or else Result = ENOMEM);
259 if Result = ENOMEM then
263 Result := pthread_mutexattr_destroy (Attributes'Access);
264 pragma Assert (Result = 0);
271 procedure Finalize_Lock (L : access Lock) is
272 Result : Interfaces.C.int;
274 Result := pthread_mutex_destroy (L.L'Access);
275 pragma Assert (Result = 0);
278 procedure Finalize_Lock (L : access RTS_Lock) is
279 Result : Interfaces.C.int;
281 Result := pthread_mutex_destroy (L);
282 pragma Assert (Result = 0);
289 procedure Write_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
290 Self_ID : constant Task_Id := Self;
291 All_Tasks_Link : constant Task_Id := Self.Common.All_Tasks_Link;
292 Current_Prio : System.Any_Priority;
293 Result : Interfaces.C.int;
296 Current_Prio := Get_Priority (Self_ID);
298 -- If there is no other tasks, no need to check priorities
300 if All_Tasks_Link /= Null_Task
301 and then L.Prio < Interfaces.C.int (Current_Prio)
303 Ceiling_Violation := True;
307 Result := pthread_mutex_lock (L.L'Access);
308 pragma Assert (Result = 0);
310 Ceiling_Violation := False;
311 -- Why is this commented out ???
312 -- L.Prio_Save := Interfaces.C.int (Current_Prio);
313 -- Set_Priority (Self_ID, System.Any_Priority (L.Prio));
317 (L : access RTS_Lock;
318 Global_Lock : Boolean := False)
320 Result : Interfaces.C.int;
322 if not Single_Lock or else Global_Lock then
323 Result := pthread_mutex_lock (L);
324 pragma Assert (Result = 0);
328 procedure Write_Lock (T : Task_Id) is
329 Result : Interfaces.C.int;
331 if not Single_Lock then
332 Result := pthread_mutex_lock (T.Common.LL.L'Access);
333 pragma Assert (Result = 0);
341 procedure Read_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
343 Write_Lock (L, Ceiling_Violation);
350 procedure Unlock (L : access Lock) is
351 Result : Interfaces.C.int;
353 Result := pthread_mutex_unlock (L.L'Access);
354 pragma Assert (Result = 0);
357 procedure Unlock (L : access RTS_Lock; Global_Lock : Boolean := False) is
358 Result : Interfaces.C.int;
360 if not Single_Lock or else Global_Lock then
361 Result := pthread_mutex_unlock (L);
362 pragma Assert (Result = 0);
366 procedure Unlock (T : Task_Id) is
367 Result : Interfaces.C.int;
369 if not Single_Lock then
370 Result := pthread_mutex_unlock (T.Common.LL.L'Access);
371 pragma Assert (Result = 0);
381 Reason : System.Tasking.Task_States)
383 pragma Unreferenced (Reason);
384 Result : Interfaces.C.int;
388 Result := pthread_cond_wait
389 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
391 Result := pthread_cond_wait
392 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
395 -- EINTR is not considered a failure
397 pragma Assert (Result = 0 or else Result = EINTR);
399 if Self_ID.Deferral_Level = 0
400 and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
403 raise Standard'Abort_Signal;
411 procedure Timed_Sleep
414 Mode : ST.Delay_Modes;
415 Reason : System.Tasking.Task_States;
416 Timedout : out Boolean;
417 Yielded : out Boolean)
419 pragma Unreferenced (Reason);
421 Sleep_Time : OS_Time;
422 Result : Interfaces.C.int;
423 Status : Cond_Value_Type;
425 -- The body below requires more comments ???
431 Sleep_Time := To_OS_Time (Time, Mode);
433 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
434 or else Self_ID.Pending_Priority_Change
439 Self_ID.Common.LL.AST_Pending := True;
442 (Status, 0, Sleep_Time,
443 Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
445 if (Status and 1) /= 1 then
450 Result := pthread_cond_wait
451 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
452 pragma Assert (Result = 0);
455 Result := pthread_cond_wait
456 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
457 pragma Assert (Result = 0);
462 if not Self_ID.Common.LL.AST_Pending then
465 Sys_Cantim (Status, To_Address (Self_ID), 0);
466 pragma Assert ((Status and 1) = 1);
474 procedure Timed_Delay
477 Mode : ST.Delay_Modes)
479 Sleep_Time : OS_Time;
480 Result : Interfaces.C.int;
481 Status : Cond_Value_Type;
482 Yielded : Boolean := False;
489 -- More comments required in body below ???
491 Write_Lock (Self_ID);
493 if Time /= 0.0 or else Mode /= Relative then
494 Sleep_Time := To_OS_Time (Time, Mode);
496 if Mode = Relative or else OS_Clock < Sleep_Time then
497 Self_ID.Common.State := Delay_Sleep;
498 Self_ID.Common.LL.AST_Pending := True;
501 (Status, 0, Sleep_Time,
502 Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
504 if (Status and 1) /= 1 then
509 if Self_ID.Pending_Priority_Change then
510 Self_ID.Pending_Priority_Change := False;
511 Self_ID.Common.Base_Priority := Self_ID.New_Base_Priority;
512 Set_Priority (Self_ID, Self_ID.Common.Base_Priority);
515 if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
516 Sys_Cantim (Status, To_Address (Self_ID), 0);
517 pragma Assert ((Status and 1) = 1);
522 Result := pthread_cond_wait
523 (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
524 pragma Assert (Result = 0);
526 Result := pthread_cond_wait
527 (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
528 pragma Assert (Result = 0);
533 exit when not Self_ID.Common.LL.AST_Pending;
536 Self_ID.Common.State := Runnable;
547 Result := sched_yield;
548 pragma Assert (Result = 0);
552 ---------------------
553 -- Monotonic_Clock --
554 ---------------------
556 function Monotonic_Clock return Duration
557 renames System.OS_Primitives.Monotonic_Clock;
563 function RT_Resolution return Duration is
572 procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
573 pragma Unreferenced (Reason);
574 Result : Interfaces.C.int;
576 Result := pthread_cond_signal (T.Common.LL.CV'Access);
577 pragma Assert (Result = 0);
584 procedure Yield (Do_Yield : Boolean := True) is
585 Result : Interfaces.C.int;
586 pragma Unreferenced (Result);
589 Result := sched_yield;
597 procedure Set_Priority
599 Prio : System.Any_Priority;
600 Loss_Of_Inheritance : Boolean := False)
602 pragma Unreferenced (Loss_Of_Inheritance);
604 Result : Interfaces.C.int;
605 Param : aliased struct_sched_param;
608 T.Common.Current_Priority := Prio;
609 Param.sched_priority := Interfaces.C.int (Underlying_Priorities (Prio));
611 if Time_Slice_Val > 0 then
612 Result := pthread_setschedparam
613 (T.Common.LL.Thread, SCHED_RR, Param'Access);
615 elsif Dispatching_Policy = 'F' or else Time_Slice_Val = 0 then
616 Result := pthread_setschedparam
617 (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
620 -- SCHED_OTHER priorities are restricted to the range 8 - 15.
621 -- Since the translation from Underlying priorities results
622 -- in a range of 16 - 31, dividing by 2 gives the correct result.
624 Param.sched_priority := Param.sched_priority / 2;
625 Result := pthread_setschedparam
626 (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
629 pragma Assert (Result = 0);
636 function Get_Priority (T : Task_Id) return System.Any_Priority is
638 return T.Common.Current_Priority;
645 procedure Enter_Task (Self_ID : Task_Id) is
647 Self_ID.Common.LL.Thread := pthread_self;
649 Specific.Set (Self_ID);
653 for J in Known_Tasks'Range loop
654 if Known_Tasks (J) = null then
655 Known_Tasks (J) := Self_ID;
656 Self_ID.Known_Tasks_Index := J;
668 function New_ATCB (Entry_Num : Task_Entry_Index) return Task_Id is
670 return new Ada_Task_Control_Block (Entry_Num);
677 function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
679 -----------------------------
680 -- Register_Foreign_Thread --
681 -----------------------------
683 function Register_Foreign_Thread return Task_Id is
685 if Is_Valid_Task then
688 return Register_Foreign_Thread (pthread_self);
690 end Register_Foreign_Thread;
696 procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
697 Mutex_Attr : aliased pthread_mutexattr_t;
698 Result : Interfaces.C.int;
699 Cond_Attr : aliased pthread_condattr_t;
702 -- More comments required in body below ???
704 if not Single_Lock then
705 Result := pthread_mutexattr_init (Mutex_Attr'Access);
706 pragma Assert (Result = 0 or else Result = ENOMEM);
709 Result := pthread_mutex_init (Self_ID.Common.LL.L'Access,
711 pragma Assert (Result = 0 or else Result = ENOMEM);
719 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
720 pragma Assert (Result = 0);
723 Result := pthread_condattr_init (Cond_Attr'Access);
724 pragma Assert (Result = 0 or else Result = ENOMEM);
727 Result := pthread_cond_init (Self_ID.Common.LL.CV'Access,
729 pragma Assert (Result = 0 or else Result = ENOMEM);
734 Self_ID.Common.LL.Exc_Stack_Ptr := new Exc_Stack_T;
737 if not Single_Lock then
738 Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
739 pragma Assert (Result = 0);
745 Result := pthread_condattr_destroy (Cond_Attr'Access);
746 pragma Assert (Result = 0);
749 ------------------------
750 -- Get_Exc_Stack_Addr --
751 ------------------------
753 function Get_Exc_Stack_Addr return Address is
755 return Self.Common.LL.Exc_Stack_Ptr (Exc_Stack_T'Last)'Address;
756 end Get_Exc_Stack_Addr;
762 procedure Create_Task
764 Wrapper : System.Address;
765 Stack_Size : System.Parameters.Size_Type;
766 Priority : System.Any_Priority;
767 Succeeded : out Boolean)
769 Attributes : aliased pthread_attr_t;
770 Adjusted_Stack_Size : Interfaces.C.size_t;
771 Result : Interfaces.C.int;
773 function Thread_Body_Access is new
774 Unchecked_Conversion (System.Address, Thread_Body);
777 if Stack_Size = Unspecified_Size then
778 Adjusted_Stack_Size := Interfaces.C.size_t (Default_Stack_Size);
780 elsif Stack_Size < Minimum_Stack_Size then
781 Adjusted_Stack_Size := Interfaces.C.size_t (Minimum_Stack_Size);
784 Adjusted_Stack_Size := Interfaces.C.size_t (Stack_Size);
787 -- Since the initial signal mask of a thread is inherited from the
788 -- creator, we need to set our local signal mask mask all signals
789 -- during the creation operation, to make sure the new thread is
790 -- not disturbed by signals before it has set its own Task_Id.
792 Result := pthread_attr_init (Attributes'Access);
793 pragma Assert (Result = 0 or else Result = ENOMEM);
800 Result := pthread_attr_setdetachstate
801 (Attributes'Access, PTHREAD_CREATE_DETACHED);
802 pragma Assert (Result = 0);
804 Result := pthread_attr_setstacksize
805 (Attributes'Access, Adjusted_Stack_Size);
806 pragma Assert (Result = 0);
808 -- This call may be unnecessary, not sure. ???
811 pthread_attr_setinheritsched
812 (Attributes'Access, PTHREAD_EXPLICIT_SCHED);
813 pragma Assert (Result = 0);
815 Result := pthread_create
816 (T.Common.LL.Thread'Access,
818 Thread_Body_Access (Wrapper),
821 -- ENOMEM is a valid run-time error. Don't shut down.
823 pragma Assert (Result = 0
824 or else Result = EAGAIN or else Result = ENOMEM);
826 Succeeded := Result = 0;
828 Result := pthread_attr_destroy (Attributes'Access);
829 pragma Assert (Result = 0);
832 Set_Priority (T, Priority);
840 procedure Finalize_TCB (T : Task_Id) is
841 Result : Interfaces.C.int;
843 Is_Self : constant Boolean := T = Self;
845 procedure Free is new
846 Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
848 procedure Free is new Unchecked_Deallocation
849 (Exc_Stack_T, Exc_Stack_Ptr_T);
852 if not Single_Lock then
853 Result := pthread_mutex_destroy (T.Common.LL.L'Access);
854 pragma Assert (Result = 0);
857 Result := pthread_cond_destroy (T.Common.LL.CV'Access);
858 pragma Assert (Result = 0);
860 if T.Known_Tasks_Index /= -1 then
861 Known_Tasks (T.Known_Tasks_Index) := null;
864 Free (T.Common.LL.Exc_Stack_Ptr);
877 procedure Exit_Task is
886 procedure Abort_Task (T : Task_Id) is
888 -- Interrupt Server_Tasks may be waiting on an event flag
890 if T.Common.State = Interrupt_Server_Blocked_On_Event_Flag then
891 Wakeup (T, Interrupt_Server_Blocked_On_Event_Flag);
899 procedure Initialize (S : in out Suspension_Object) is
900 Mutex_Attr : aliased pthread_mutexattr_t;
901 Cond_Attr : aliased pthread_condattr_t;
902 Result : Interfaces.C.int;
904 -- Initialize internal state. It is always initialized to False (ARM
910 -- Initialize internal mutex
912 Result := pthread_mutexattr_init (Mutex_Attr'Access);
913 pragma Assert (Result = 0 or else Result = ENOMEM);
915 if Result = ENOMEM then
919 Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
920 pragma Assert (Result = 0 or else Result = ENOMEM);
922 if Result = ENOMEM then
923 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
924 pragma Assert (Result = 0);
929 Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
930 pragma Assert (Result = 0);
932 -- Initialize internal condition variable
934 Result := pthread_condattr_init (Cond_Attr'Access);
935 pragma Assert (Result = 0 or else Result = ENOMEM);
938 Result := pthread_mutex_destroy (S.L'Access);
939 pragma Assert (Result = 0);
941 if Result = ENOMEM then
946 Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
947 pragma Assert (Result = 0 or else Result = ENOMEM);
950 Result := pthread_mutex_destroy (S.L'Access);
951 pragma Assert (Result = 0);
953 if Result = ENOMEM then
954 Result := pthread_condattr_destroy (Cond_Attr'Access);
955 pragma Assert (Result = 0);
961 Result := pthread_condattr_destroy (Cond_Attr'Access);
962 pragma Assert (Result = 0);
969 procedure Finalize (S : in out Suspension_Object) is
970 Result : Interfaces.C.int;
972 -- Destroy internal mutex
974 Result := pthread_mutex_destroy (S.L'Access);
975 pragma Assert (Result = 0);
977 -- Destroy internal condition variable
979 Result := pthread_cond_destroy (S.CV'Access);
980 pragma Assert (Result = 0);
987 function Current_State (S : Suspension_Object) return Boolean is
989 -- We do not want to use lock on this read operation. State is marked
990 -- as Atomic so that we ensure that the value retrieved is correct.
999 procedure Set_False (S : in out Suspension_Object) is
1000 Result : Interfaces.C.int;
1002 Result := pthread_mutex_lock (S.L'Access);
1003 pragma Assert (Result = 0);
1007 Result := pthread_mutex_unlock (S.L'Access);
1008 pragma Assert (Result = 0);
1015 procedure Set_True (S : in out Suspension_Object) is
1016 Result : Interfaces.C.int;
1018 Result := pthread_mutex_lock (S.L'Access);
1019 pragma Assert (Result = 0);
1021 -- If there is already a task waiting on this suspension object then
1022 -- we resume it, leaving the state of the suspension object to False,
1023 -- as it is specified in ARM D.10 par. 9. Otherwise, it just leaves
1024 -- the state to True.
1030 Result := pthread_cond_signal (S.CV'Access);
1031 pragma Assert (Result = 0);
1036 Result := pthread_mutex_unlock (S.L'Access);
1037 pragma Assert (Result = 0);
1040 ------------------------
1041 -- Suspend_Until_True --
1042 ------------------------
1044 procedure Suspend_Until_True (S : in out Suspension_Object) is
1045 Result : Interfaces.C.int;
1047 Result := pthread_mutex_lock (S.L'Access);
1048 pragma Assert (Result = 0);
1051 -- Program_Error must be raised upon calling Suspend_Until_True
1052 -- if another task is already waiting on that suspension object
1053 -- (ARM D.10 par. 10).
1055 Result := pthread_mutex_unlock (S.L'Access);
1056 pragma Assert (Result = 0);
1058 raise Program_Error;
1060 -- Suspend the task if the state is False. Otherwise, the task
1061 -- continues its execution, and the state of the suspension object
1062 -- is set to False (ARM D.10 par. 9).
1068 Result := pthread_cond_wait (S.CV'Access, S.L'Access);
1072 Result := pthread_mutex_unlock (S.L'Access);
1073 pragma Assert (Result = 0);
1074 end Suspend_Until_True;
1082 function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
1083 pragma Unreferenced (Self_ID);
1088 --------------------
1089 -- Check_No_Locks --
1090 --------------------
1092 function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
1093 pragma Unreferenced (Self_ID);
1098 ----------------------
1099 -- Environment_Task --
1100 ----------------------
1102 function Environment_Task return Task_Id is
1104 return Environment_Task_Id;
1105 end Environment_Task;
1111 procedure Lock_RTS is
1113 Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
1120 procedure Unlock_RTS is
1122 Unlock (Single_RTS_Lock'Access, Global_Lock => True);
1129 function Suspend_Task
1131 Thread_Self : Thread_Id) return Boolean
1133 pragma Unreferenced (T);
1134 pragma Unreferenced (Thread_Self);
1143 function Resume_Task
1145 Thread_Self : Thread_Id) return Boolean
1147 pragma Unreferenced (T);
1148 pragma Unreferenced (Thread_Self);
1157 procedure Initialize (Environment_Task : Task_Id) is
1159 Environment_Task_Id := Environment_Task;
1161 SSL.Get_Exc_Stack_Addr := Get_Exc_Stack_Addr'Access;
1163 -- Initialize the lock used to synchronize chain of all ATCBs
1165 Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
1167 Specific.Initialize (Environment_Task);
1169 Enter_Task (Environment_Task);
1172 end System.Task_Primitives.Operations;