1 ------------------------------------------------------------------------------
3 -- GNU ADA 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-2004, 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, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, 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 IRIX (pthread library) 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.
47 with System
.Task_Info
;
49 with System
.Tasking
.Debug
;
50 -- used for Known_Tasks
55 with System
.Interrupt_Management
;
56 -- used for Keep_Unmasked
57 -- Abort_Task_Interrupt
60 with System
.Interrupt_Management
.Operations
;
61 -- used for Set_Interrupt_Mask
63 pragma Elaborate_All
(System
.Interrupt_Management
.Operations
);
65 with System
.Parameters
;
69 -- used for Ada_Task_Control_Block
72 with System
.Soft_Links
;
73 -- used for Defer/Undefer_Abort
75 -- Note that we do not use System.Tasking.Initialization directly since
76 -- this is a higher level package that we shouldn't depend on. For example
77 -- when using the restricted run time, it is replaced by
78 -- System.Tasking.Restricted.Stages.
80 with System
.Program_Info
;
81 -- used for Default_Task_Stack
84 -- Pthread_Sched_Signal
87 with System
.OS_Interface
;
88 -- used for various type, constant, and operations
90 with System
.OS_Primitives
;
91 -- used for Delay_Modes
93 with Unchecked_Conversion
;
94 with Unchecked_Deallocation
;
96 package body System
.Task_Primitives
.Operations
is
99 use System
.Tasking
.Debug
;
101 use System
.OS_Interface
;
102 use System
.OS_Primitives
;
103 use System
.Parameters
;
105 package SSL
renames System
.Soft_Links
;
111 -- The followings are logically constants, but need to be initialized
114 Single_RTS_Lock
: aliased RTS_Lock
;
115 -- This is a lock to allow only one thread of control in the RTS at
116 -- a time; it is used to execute in mutual exclusion from all other tasks.
117 -- Used mainly in Single_Lock mode, but also to protect All_Tasks_List
119 ATCB_Key
: aliased pthread_key_t
;
120 -- Key used to find the Ada Task_Id associated with a thread
122 Environment_Task_Id
: Task_Id
;
123 -- A variable to hold Task_Id for the environment task
125 Locking_Policy
: Character;
126 pragma Import
(C
, Locking_Policy
, "__gl_locking_policy");
128 Real_Time_Clock_Id
: constant clockid_t
:= CLOCK_REALTIME
;
130 Unblocked_Signal_Mask
: aliased sigset_t
;
132 Foreign_Task_Elaborated
: aliased Boolean := True;
133 -- Used to identified fake tasks (i.e., non-Ada Threads)
141 procedure Initialize
(Environment_Task
: Task_Id
);
142 pragma Inline
(Initialize
);
143 -- Initialize various data needed by this package
145 function Is_Valid_Task
return Boolean;
146 pragma Inline
(Is_Valid_Task
);
147 -- Does executing thread have a TCB?
149 procedure Set
(Self_Id
: Task_Id
);
151 -- Set the self id for the current task
153 function Self
return Task_Id
;
154 pragma Inline
(Self
);
155 -- Return a pointer to the Ada Task Control Block of the calling task
159 package body Specific
is separate;
160 -- The body of this package is target specific
162 ---------------------------------
163 -- Support for foreign threads --
164 ---------------------------------
166 function Register_Foreign_Thread
(Thread
: Thread_Id
) return Task_Id
;
167 -- Allocate and Initialize a new ATCB for the current Thread
169 function Register_Foreign_Thread
170 (Thread
: Thread_Id
) return Task_Id
is separate;
172 -----------------------
173 -- Local Subprograms --
174 -----------------------
176 function To_Address
is new Unchecked_Conversion
(Task_Id
, System
.Address
);
178 procedure Abort_Handler
(Sig
: Signal
);
179 -- Signal handler used to implement asynchronous abort
185 procedure Abort_Handler
(Sig
: Signal
) is
186 pragma Unreferenced
(Sig
);
188 T
: constant Task_Id
:= Self
;
189 Result
: Interfaces
.C
.int
;
190 Old_Set
: aliased sigset_t
;
193 -- It is not safe to raise an exception when using ZCX and the GCC
194 -- exception handling mechanism.
196 if ZCX_By_Default
and then GCC_ZCX_Support
then
200 if T
.Deferral_Level
= 0
201 and then T
.Pending_ATC_Level
< T
.ATC_Nesting_Level
203 -- Make sure signals used for RTS internal purpose are unmasked
205 Result
:= pthread_sigmask
207 Unblocked_Signal_Mask
'Unchecked_Access,
208 Old_Set
'Unchecked_Access);
209 pragma Assert
(Result
= 0);
211 raise Standard
'Abort_Signal;
219 -- The underlying thread system sets a guard page at the
220 -- bottom of a thread stack, so nothing is needed.
222 procedure Stack_Guard
(T
: ST
.Task_Id
; On
: Boolean) is
223 pragma Unreferenced
(On
);
224 pragma Unreferenced
(T
);
233 function Get_Thread_Id
(T
: ST
.Task_Id
) return OSI
.Thread_Id
is
235 return T
.Common
.LL
.Thread
;
242 function Self
return Task_Id
renames Specific
.Self
;
244 ---------------------
245 -- Initialize_Lock --
246 ---------------------
248 -- Note: mutexes and cond_variables needed per-task basis are
249 -- initialized in Initialize_TCB and the Storage_Error is
250 -- handled. Other mutexes (such as RTS_Lock, Memory_Lock...)
251 -- used in RTS is initialized before any status change of RTS.
252 -- Therefore rasing Storage_Error in the following routines
253 -- should be able to be handled safely.
255 procedure Initialize_Lock
256 (Prio
: System
.Any_Priority
;
259 Attributes
: aliased pthread_mutexattr_t
;
260 Result
: Interfaces
.C
.int
;
263 Result
:= pthread_mutexattr_init
(Attributes
'Access);
264 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
266 if Result
= ENOMEM
then
270 if Locking_Policy
= 'C' then
271 Result
:= pthread_mutexattr_setprotocol
272 (Attributes
'Access, PTHREAD_PRIO_PROTECT
);
273 pragma Assert
(Result
= 0);
275 Result
:= pthread_mutexattr_setprioceiling
276 (Attributes
'Access, Interfaces
.C
.int
(Prio
));
277 pragma Assert
(Result
= 0);
280 Result
:= pthread_mutex_init
(L
, Attributes
'Access);
281 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
283 if Result
= ENOMEM
then
284 Result
:= pthread_mutexattr_destroy
(Attributes
'Access);
288 Result
:= pthread_mutexattr_destroy
(Attributes
'Access);
289 pragma Assert
(Result
= 0);
292 procedure Initialize_Lock
(L
: access RTS_Lock
; Level
: Lock_Level
) is
293 pragma Unreferenced
(Level
);
295 Attributes
: aliased pthread_mutexattr_t
;
296 Result
: Interfaces
.C
.int
;
299 Result
:= pthread_mutexattr_init
(Attributes
'Access);
300 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
302 if Result
= ENOMEM
then
306 if Locking_Policy
= 'C' then
307 Result
:= pthread_mutexattr_setprotocol
308 (Attributes
'Access, PTHREAD_PRIO_PROTECT
);
309 pragma Assert
(Result
= 0);
311 Result
:= pthread_mutexattr_setprioceiling
312 (Attributes
'Access, Interfaces
.C
.int
(System
.Any_Priority
'Last));
313 pragma Assert
(Result
= 0);
316 Result
:= pthread_mutex_init
(L
, Attributes
'Access);
318 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
320 if Result
= ENOMEM
then
321 Result
:= pthread_mutexattr_destroy
(Attributes
'Access);
325 Result
:= pthread_mutexattr_destroy
(Attributes
'Access);
332 procedure Finalize_Lock
(L
: access Lock
) is
333 Result
: Interfaces
.C
.int
;
335 Result
:= pthread_mutex_destroy
(L
);
336 pragma Assert
(Result
= 0);
339 procedure Finalize_Lock
(L
: access RTS_Lock
) is
340 Result
: Interfaces
.C
.int
;
342 Result
:= pthread_mutex_destroy
(L
);
343 pragma Assert
(Result
= 0);
350 procedure Write_Lock
(L
: access Lock
; Ceiling_Violation
: out Boolean) is
351 Result
: Interfaces
.C
.int
;
353 Result
:= pthread_mutex_lock
(L
);
354 Ceiling_Violation
:= Result
= EINVAL
;
356 -- Assumes the cause of EINVAL is a priority ceiling violation
358 pragma Assert
(Result
= 0 or else Result
= EINVAL
);
362 (L
: access RTS_Lock
;
363 Global_Lock
: Boolean := False)
365 Result
: Interfaces
.C
.int
;
367 if not Single_Lock
or else Global_Lock
then
368 Result
:= pthread_mutex_lock
(L
);
369 pragma Assert
(Result
= 0);
373 procedure Write_Lock
(T
: Task_Id
) is
374 Result
: Interfaces
.C
.int
;
376 if not Single_Lock
then
377 Result
:= pthread_mutex_lock
(T
.Common
.LL
.L
'Access);
378 pragma Assert
(Result
= 0);
386 procedure Read_Lock
(L
: access Lock
; Ceiling_Violation
: out Boolean) is
388 Write_Lock
(L
, Ceiling_Violation
);
395 procedure Unlock
(L
: access Lock
) is
396 Result
: Interfaces
.C
.int
;
398 Result
:= pthread_mutex_unlock
(L
);
399 pragma Assert
(Result
= 0);
402 procedure Unlock
(L
: access RTS_Lock
; Global_Lock
: Boolean := False) is
403 Result
: Interfaces
.C
.int
;
406 if not Single_Lock
or else Global_Lock
then
407 Result
:= pthread_mutex_unlock
(L
);
408 pragma Assert
(Result
= 0);
412 procedure Unlock
(T
: Task_Id
) is
413 Result
: Interfaces
.C
.int
;
416 if not Single_Lock
then
417 Result
:= pthread_mutex_unlock
(T
.Common
.LL
.L
'Access);
418 pragma Assert
(Result
= 0);
427 (Self_ID
: ST
.Task_Id
;
428 Reason
: System
.Tasking
.Task_States
)
430 pragma Unreferenced
(Reason
);
432 Result
: Interfaces
.C
.int
;
436 Result
:= pthread_cond_wait
437 (Self_ID
.Common
.LL
.CV
'Access, Single_RTS_Lock
'Access);
439 Result
:= pthread_cond_wait
440 (Self_ID
.Common
.LL
.CV
'Access, Self_ID
.Common
.LL
.L
'Access);
443 -- EINTR is not considered a failure
445 pragma Assert
(Result
= 0 or else Result
= EINTR
);
452 procedure Timed_Sleep
455 Mode
: ST
.Delay_Modes
;
456 Reason
: Task_States
;
457 Timedout
: out Boolean;
458 Yielded
: out Boolean)
460 pragma Unreferenced
(Reason
);
462 Check_Time
: constant Duration := Monotonic_Clock
;
464 Request
: aliased timespec
;
465 Result
: Interfaces
.C
.int
;
471 if Mode
= Relative
then
472 Abs_Time
:= Duration'Min (Time
, Max_Sensible_Delay
) + Check_Time
;
474 Abs_Time
:= Duration'Min (Check_Time
+ Max_Sensible_Delay
, Time
);
477 if Abs_Time
> Check_Time
then
478 Request
:= To_Timespec
(Abs_Time
);
481 exit when Self_ID
.Pending_ATC_Level
< Self_ID
.ATC_Nesting_Level
482 or else Self_ID
.Pending_Priority_Change
;
485 Result
:= pthread_cond_timedwait
486 (Self_ID
.Common
.LL
.CV
'Access, Single_RTS_Lock
'Access,
490 Result
:= pthread_cond_timedwait
491 (Self_ID
.Common
.LL
.CV
'Access, Self_ID
.Common
.LL
.L
'Access,
495 exit when Abs_Time
<= Monotonic_Clock
;
497 if Result
= 0 or else errno
= EINTR
then
509 -- This is for use in implementing delay statements, so we assume
510 -- the caller is abort-deferred but is holding no locks.
512 procedure Timed_Delay
515 Mode
: ST
.Delay_Modes
)
517 Check_Time
: constant Duration := Monotonic_Clock
;
519 Request
: aliased timespec
;
520 Result
: Interfaces
.C
.int
;
523 -- The little window between deferring abort and locking Self_ID is
524 -- the only reason we need to check for pending abort and priority
533 Write_Lock
(Self_ID
);
535 if Mode
= Relative
then
536 Abs_Time
:= Time
+ Check_Time
;
538 Abs_Time
:= Duration'Min (Check_Time
+ Max_Sensible_Delay
, Time
);
541 if Abs_Time
> Check_Time
then
542 Request
:= To_Timespec
(Abs_Time
);
543 Self_ID
.Common
.State
:= Delay_Sleep
;
546 if Self_ID
.Pending_Priority_Change
then
547 Self_ID
.Pending_Priority_Change
:= False;
548 Self_ID
.Common
.Base_Priority
:= Self_ID
.New_Base_Priority
;
549 Set_Priority
(Self_ID
, Self_ID
.Common
.Base_Priority
);
552 exit when Self_ID
.Pending_ATC_Level
< Self_ID
.ATC_Nesting_Level
;
554 Result
:= pthread_cond_timedwait
(Self_ID
.Common
.LL
.CV
'Access,
555 Self_ID
.Common
.LL
.L
'Access, Request
'Access);
556 exit when Abs_Time
<= Monotonic_Clock
;
558 pragma Assert
(Result
= 0
559 or else Result
= ETIMEDOUT
560 or else Result
= EINTR
);
563 Self_ID
.Common
.State
:= Runnable
;
573 SSL
.Abort_Undefer
.all;
576 ---------------------
577 -- Monotonic_Clock --
578 ---------------------
580 function Monotonic_Clock
return Duration is
581 TS
: aliased timespec
;
582 Result
: Interfaces
.C
.int
;
584 Result
:= clock_gettime
(Real_Time_Clock_Id
, TS
'Unchecked_Access);
585 pragma Assert
(Result
= 0);
586 return To_Duration
(TS
);
593 function RT_Resolution
return Duration is
595 -- The clock_getres (Real_Time_Clock_Id) function appears to return
596 -- the interrupt resolution of the realtime clock and not the actual
597 -- resolution of reading the clock. Even though this last value is
598 -- only guaranteed to be 100 Hz, at least the Origin 200 appears to
599 -- have a microsecond resolution or better.
601 -- ??? We should figure out a method to return the right value on
611 procedure Wakeup
(T
: ST
.Task_Id
; Reason
: System
.Tasking
.Task_States
) is
612 pragma Unreferenced
(Reason
);
613 Result
: Interfaces
.C
.int
;
615 Result
:= pthread_cond_signal
(T
.Common
.LL
.CV
'Access);
616 pragma Assert
(Result
= 0);
623 procedure Yield
(Do_Yield
: Boolean := True) is
624 Result
: Interfaces
.C
.int
;
625 pragma Unreferenced
(Result
);
628 Result
:= sched_yield
;
636 procedure Set_Priority
638 Prio
: System
.Any_Priority
;
639 Loss_Of_Inheritance
: Boolean := False)
641 pragma Unreferenced
(Loss_Of_Inheritance
);
643 Result
: Interfaces
.C
.int
;
644 Param
: aliased struct_sched_param
;
645 Sched_Policy
: Interfaces
.C
.int
;
647 use type System
.Task_Info
.Task_Info_Type
;
649 function To_Int
is new Unchecked_Conversion
650 (System
.Task_Info
.Thread_Scheduling_Policy
, Interfaces
.C
.int
);
653 T
.Common
.Current_Priority
:= Prio
;
654 Param
.sched_priority
:= Interfaces
.C
.int
(Prio
);
656 if T
.Common
.Task_Info
/= null then
657 Sched_Policy
:= To_Int
(T
.Common
.Task_Info
.Policy
);
659 Sched_Policy
:= SCHED_FIFO
;
662 Result
:= pthread_setschedparam
(T
.Common
.LL
.Thread
, Sched_Policy
,
664 pragma Assert
(Result
= 0);
671 function Get_Priority
(T
: Task_Id
) return System
.Any_Priority
is
673 return T
.Common
.Current_Priority
;
680 procedure Enter_Task
(Self_ID
: Task_Id
) is
681 Result
: Interfaces
.C
.int
;
683 function To_Int
is new Unchecked_Conversion
684 (System
.Task_Info
.CPU_Number
, Interfaces
.C
.int
);
686 use System
.Task_Info
;
689 Self_ID
.Common
.LL
.Thread
:= pthread_self
;
690 Specific
.Set
(Self_ID
);
692 if Self_ID
.Common
.Task_Info
/= null
693 and then Self_ID
.Common
.Task_Info
.Scope
= PTHREAD_SCOPE_SYSTEM
694 and then Self_ID
.Common
.Task_Info
.Runon_CPU
/= ANY_CPU
696 Result
:= pthread_setrunon_np
697 (To_Int
(Self_ID
.Common
.Task_Info
.Runon_CPU
));
698 pragma Assert
(Result
= 0);
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 Result
: Interfaces
.C
.int
;
748 Cond_Attr
: aliased pthread_condattr_t
;
751 if not Single_Lock
then
752 Initialize_Lock
(Self_ID
.Common
.LL
.L
'Access, ATCB_Level
);
755 Result
:= pthread_condattr_init
(Cond_Attr
'Access);
756 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
759 Result
:= pthread_cond_init
(Self_ID
.Common
.LL
.CV
'Access,
761 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
767 if not Single_Lock
then
768 Result
:= pthread_mutex_destroy
(Self_ID
.Common
.LL
.L
'Access);
769 pragma Assert
(Result
= 0);
775 Result
:= pthread_condattr_destroy
(Cond_Attr
'Access);
776 pragma Assert
(Result
= 0);
783 procedure Create_Task
785 Wrapper
: System
.Address
;
786 Stack_Size
: System
.Parameters
.Size_Type
;
787 Priority
: System
.Any_Priority
;
788 Succeeded
: out Boolean)
790 use System
.Task_Info
;
792 Attributes
: aliased pthread_attr_t
;
793 Sched_Param
: aliased struct_sched_param
;
794 Adjusted_Stack_Size
: Interfaces
.C
.size_t
;
795 Result
: Interfaces
.C
.int
;
797 function Thread_Body_Access
is new
798 Unchecked_Conversion
(System
.Address
, Thread_Body
);
800 function To_Int
is new Unchecked_Conversion
801 (System
.Task_Info
.Thread_Scheduling_Scope
, Interfaces
.C
.int
);
802 function To_Int
is new Unchecked_Conversion
803 (System
.Task_Info
.Thread_Scheduling_Inheritance
, Interfaces
.C
.int
);
804 function To_Int
is new Unchecked_Conversion
805 (System
.Task_Info
.Thread_Scheduling_Policy
, Interfaces
.C
.int
);
808 if Stack_Size
= System
.Parameters
.Unspecified_Size
then
809 Adjusted_Stack_Size
:=
810 Interfaces
.C
.size_t
(System
.Program_Info
.Default_Task_Stack
);
812 elsif Stack_Size
< Size_Type
(Minimum_Stack_Size
) then
813 Adjusted_Stack_Size
:=
814 Interfaces
.C
.size_t
(Minimum_Stack_Size
);
817 Adjusted_Stack_Size
:= Interfaces
.C
.size_t
(Stack_Size
);
820 Result
:= pthread_attr_init
(Attributes
'Access);
821 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
828 Result
:= pthread_attr_setdetachstate
829 (Attributes
'Access, PTHREAD_CREATE_DETACHED
);
830 pragma Assert
(Result
= 0);
832 Result
:= pthread_attr_setstacksize
833 (Attributes
'Access, Adjusted_Stack_Size
);
834 pragma Assert
(Result
= 0);
836 if T
.Common
.Task_Info
/= null then
837 Result
:= pthread_attr_setscope
838 (Attributes
'Access, To_Int
(T
.Common
.Task_Info
.Scope
));
839 pragma Assert
(Result
= 0);
841 Result
:= pthread_attr_setinheritsched
842 (Attributes
'Access, To_Int
(T
.Common
.Task_Info
.Inheritance
));
843 pragma Assert
(Result
= 0);
845 Result
:= pthread_attr_setschedpolicy
846 (Attributes
'Access, To_Int
(T
.Common
.Task_Info
.Policy
));
847 pragma Assert
(Result
= 0);
849 Sched_Param
.sched_priority
:=
850 Interfaces
.C
.int
(T
.Common
.Task_Info
.Priority
);
852 Result
:= pthread_attr_setschedparam
853 (Attributes
'Access, Sched_Param
'Access);
854 pragma Assert
(Result
= 0);
857 -- Since the initial signal mask of a thread is inherited from the
858 -- creator, and the Environment task has all its signals masked, we
859 -- do not need to manipulate caller's signal mask at this point.
860 -- All tasks in RTS will have All_Tasks_Mask initially.
862 Result
:= pthread_create
863 (T
.Common
.LL
.Thread
'Access,
865 Thread_Body_Access
(Wrapper
),
869 and then T
.Common
.Task_Info
/= null
870 and then T
.Common
.Task_Info
.Scope
= PTHREAD_SCOPE_SYSTEM
872 -- The pthread_create call may have failed because we
873 -- asked for a system scope pthread and none were
874 -- available (probably because the program was not executed
875 -- by the superuser). Let's try for a process scope pthread
876 -- instead of raising Tasking_Error.
879 ("Request for PTHREAD_SCOPE_SYSTEM in Task_Info pragma for task");
880 System
.IO
.Put
("""");
881 System
.IO
.Put
(T
.Common
.Task_Image
(1 .. T
.Common
.Task_Image_Len
));
882 System
.IO
.Put_Line
(""" could not be honored. ");
883 System
.IO
.Put_Line
("Scope changed to PTHREAD_SCOPE_PROCESS");
885 T
.Common
.Task_Info
.Scope
:= PTHREAD_SCOPE_PROCESS
;
886 Result
:= pthread_attr_setscope
887 (Attributes
'Access, To_Int
(T
.Common
.Task_Info
.Scope
));
888 pragma Assert
(Result
= 0);
890 Result
:= pthread_create
891 (T
.Common
.LL
.Thread
'Access,
893 Thread_Body_Access
(Wrapper
),
897 pragma Assert
(Result
= 0 or else Result
= EAGAIN
);
899 Succeeded
:= Result
= 0;
901 -- The following needs significant commenting ???
903 if T
.Common
.Task_Info
/= null then
904 T
.Common
.Base_Priority
:= T
.Common
.Task_Info
.Priority
;
905 Set_Priority
(T
, T
.Common
.Task_Info
.Priority
);
907 Set_Priority
(T
, Priority
);
910 Result
:= pthread_attr_destroy
(Attributes
'Access);
911 pragma Assert
(Result
= 0);
918 procedure Finalize_TCB
(T
: Task_Id
) is
919 Result
: Interfaces
.C
.int
;
921 Is_Self
: constant Boolean := T
= Self
;
923 procedure Free
is new
924 Unchecked_Deallocation
(Ada_Task_Control_Block
, Task_Id
);
927 if not Single_Lock
then
928 Result
:= pthread_mutex_destroy
(T
.Common
.LL
.L
'Access);
929 pragma Assert
(Result
= 0);
932 Result
:= pthread_cond_destroy
(T
.Common
.LL
.CV
'Access);
933 pragma Assert
(Result
= 0);
935 if T
.Known_Tasks_Index
/= -1 then
936 Known_Tasks
(T
.Known_Tasks_Index
) := null;
950 procedure Exit_Task
is
959 procedure Abort_Task
(T
: Task_Id
) is
960 Result
: Interfaces
.C
.int
;
962 Result
:= pthread_kill
(T
.Common
.LL
.Thread
,
963 Signal
(System
.Interrupt_Management
.Abort_Task_Interrupt
));
964 pragma Assert
(Result
= 0);
973 function Check_Exit
(Self_ID
: ST
.Task_Id
) return Boolean is
974 pragma Unreferenced
(Self_ID
);
983 function Check_No_Locks
(Self_ID
: ST
.Task_Id
) return Boolean is
984 pragma Unreferenced
(Self_ID
);
989 ----------------------
990 -- Environment_Task --
991 ----------------------
993 function Environment_Task
return Task_Id
is
995 return Environment_Task_Id
;
996 end Environment_Task
;
1002 procedure Lock_RTS
is
1004 Write_Lock
(Single_RTS_Lock
'Access, Global_Lock
=> True);
1011 procedure Unlock_RTS
is
1013 Unlock
(Single_RTS_Lock
'Access, Global_Lock
=> True);
1020 function Suspend_Task
1022 Thread_Self
: Thread_Id
) return Boolean
1024 pragma Unreferenced
(T
);
1025 pragma Unreferenced
(Thread_Self
);
1034 function Resume_Task
1036 Thread_Self
: Thread_Id
) return Boolean
1038 pragma Unreferenced
(T
);
1039 pragma Unreferenced
(Thread_Self
);
1048 procedure Initialize
(Environment_Task
: Task_Id
) is
1049 act
: aliased struct_sigaction
;
1050 old_act
: aliased struct_sigaction
;
1051 Tmp_Set
: aliased sigset_t
;
1052 Result
: Interfaces
.C
.int
;
1055 (Int
: System
.Interrupt_Management
.Interrupt_ID
) return Character;
1056 pragma Import
(C
, State
, "__gnat_get_interrupt_state");
1057 -- Get interrupt state. Defined in a-init.c. The input argument is
1058 -- the interrupt number, and the result is one of the following:
1060 Default
: constant Character := 's';
1061 -- 'n' this interrupt not set by any Interrupt_State pragma
1062 -- 'u' Interrupt_State pragma set state to User
1063 -- 'r' Interrupt_State pragma set state to Runtime
1064 -- 's' Interrupt_State pragma set state to System (use "default"
1068 Environment_Task_Id
:= Environment_Task
;
1070 -- Initialize the lock used to synchronize chain of all ATCBs.
1072 Initialize_Lock
(Single_RTS_Lock
'Access, RTS_Lock_Level
);
1074 Specific
.Initialize
(Environment_Task
);
1076 Enter_Task
(Environment_Task
);
1078 -- Install the abort-signal handler
1080 if State
(System
.Interrupt_Management
.Abort_Task_Interrupt
)
1084 act
.sa_handler
:= Abort_Handler
'Address;
1086 Result
:= sigemptyset
(Tmp_Set
'Access);
1087 pragma Assert
(Result
= 0);
1088 act
.sa_mask
:= Tmp_Set
;
1092 Signal
(System
.Interrupt_Management
.Abort_Task_Interrupt
),
1093 act
'Unchecked_Access,
1094 old_act
'Unchecked_Access);
1095 pragma Assert
(Result
= 0);
1101 Result
: Interfaces
.C
.int
;
1104 -- Mask Environment task for all signals. The original mask of the
1105 -- Environment task will be recovered by Interrupt_Server task
1106 -- during the elaboration of s-interr.adb.
1108 System
.Interrupt_Management
.Operations
.Set_Interrupt_Mask
1109 (System
.Interrupt_Management
.Operations
.All_Tasks_Mask
'Access);
1111 -- Prepare the set of signals that should unblocked in all tasks
1113 Result
:= sigemptyset
(Unblocked_Signal_Mask
'Access);
1114 pragma Assert
(Result
= 0);
1116 for J
in Interrupt_Management
.Interrupt_ID
loop
1117 if System
.Interrupt_Management
.Keep_Unmasked
(J
) then
1118 Result
:= sigaddset
(Unblocked_Signal_Mask
'Access, Signal
(J
));
1119 pragma Assert
(Result
= 0);
1123 -- Pick the highest resolution Clock for Clock_Realtime
1125 -- ??? This code currently doesn't work (see c94007[ab] for example)
1127 -- if syssgi (SGI_CYCLECNTR_SIZE) = 64 then
1128 -- Real_Time_Clock_Id := CLOCK_SGI_CYCLE;
1130 -- Real_Time_Clock_Id := CLOCK_REALTIME;
1133 end System
.Task_Primitives
.Operations
;