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 --
11 -- Copyright (C) 1991-2001 Florida State University --
13 -- GNARL is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNARL; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNARL was developed by the GNARL team at Florida State University. It is --
32 -- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
33 -- State University (http://www.gnat.com). --
35 ------------------------------------------------------------------------------
37 -- This is the VxWorks version of this package
39 -- This package contains all the GNULL primitives that interface directly
40 -- with the underlying OS.
43 -- Turn off polling, we do not want ATC polling to take place during
44 -- tasking operations. It causes infinite loops and other problems.
46 with System
.Tasking
.Debug
;
47 -- used for Known_Tasks
53 with System
.Interrupt_Management
;
54 -- used for Keep_Unmasked
55 -- Abort_Task_Interrupt
57 -- Initialize_Interrupts
59 with System
.Soft_Links
;
60 -- used for Defer/Undefer_Abort
62 -- Note that we do not use System.Tasking.Initialization directly since
63 -- this is a higher level package that we shouldn't depend on. For example
64 -- when using the restricted run time, it is replaced by
65 -- System.Tasking.Restricted.Initialization
67 with System
.OS_Interface
;
68 -- used for various type, constant, and operations
70 with System
.Parameters
;
74 -- used for Ada_Task_Control_Block
76 -- ATCB components and types
78 with System
.Task_Info
;
79 -- used for Task_Image
81 with System
.OS_Primitives
;
82 -- used for Delay_Modes
87 with Unchecked_Conversion
;
88 with Unchecked_Deallocation
;
90 package body System
.Task_Primitives
.Operations
is
92 use System
.Tasking
.Debug
;
96 use System
.OS_Interface
;
97 use System
.Parameters
;
98 use System
.OS_Primitives
;
100 package SSL
renames System
.Soft_Links
;
106 -- The followings are logically constants, but need to be initialized
109 ATCB_Key
: aliased pthread_key_t
;
110 -- Key used to find the Ada Task_ID associated with a VxWorks task.
112 All_Tasks_L
: aliased System
.Task_Primitives
.RTS_Lock
;
113 -- See comments on locking rules in System.Tasking (spec).
115 Environment_Task_ID
: Task_ID
;
116 -- A variable to hold Task_ID for the environment task.
118 Unblocked_Signal_Mask
: aliased sigset_t
;
119 -- The set of signals that should unblocked in all tasks
121 -- The followings are internal configuration constants needed.
123 Time_Slice_Val
: Integer;
124 pragma Import
(C
, Time_Slice_Val
, "__gl_time_slice_val");
126 Locking_Policy
: Character;
127 pragma Import
(C
, Locking_Policy
, "__gl_locking_policy");
129 Dispatching_Policy
: Character;
130 pragma Import
(C
, Dispatching_Policy
, "__gl_task_dispatching_policy");
132 FIFO_Within_Priorities
: constant Boolean := Dispatching_Policy
= 'F';
133 -- Indicates whether FIFO_Within_Priorities is set.
135 Mutex_Protocol
: Interfaces
.C
.int
;
137 Stack_Limit
: aliased System
.Address
;
138 pragma Import
(C
, Stack_Limit
, "__gnat_stack_limit");
140 -----------------------
141 -- Local Subprograms --
142 -----------------------
144 procedure Abort_Handler
(signo
: Signal
);
146 function To_Task_ID
is new Unchecked_Conversion
(System
.Address
, Task_ID
);
148 function To_Address
is new Unchecked_Conversion
(Task_ID
, System
.Address
);
154 procedure Abort_Handler
(signo
: Signal
) is
155 Self_ID
: constant Task_ID
:= Self
;
156 Result
: Interfaces
.C
.int
;
157 Old_Set
: aliased sigset_t
;
160 if Self_ID
.Deferral_Level
= 0
161 and then Self_ID
.Pending_ATC_Level
< Self_ID
.ATC_Nesting_Level
and then
164 Self_ID
.Aborting
:= True;
166 -- Make sure signals used for RTS internal purpose are unmasked
168 Result
:= pthread_sigmask
(SIG_UNBLOCK
,
169 Unblocked_Signal_Mask
'Unchecked_Access, Old_Set
'Unchecked_Access);
170 pragma Assert
(Result
= 0);
172 raise Standard
'Abort_Signal;
180 procedure Stack_Guard
(T
: ST
.Task_ID
; On
: Boolean) is
181 Task_Descriptor
: aliased System
.VxWorks
.TASK_DESC
;
182 Result
: Interfaces
.C
.int
;
186 Result
:= taskInfoGet
(T
.Common
.LL
.Thread
,
187 Task_Descriptor
'Unchecked_Access);
188 pragma Assert
(Result
= 0);
190 Stack_Limit
:= Task_Descriptor
.td_pStackLimit
;
198 function Get_Thread_Id
(T
: ST
.Task_ID
) return OSI
.Thread_Id
is
200 return T
.Common
.LL
.Thread
;
207 function Self
return Task_ID
is
208 Result
: System
.Address
;
211 Result
:= pthread_getspecific
(ATCB_Key
);
212 pragma Assert
(Result
/= System
.Null_Address
);
213 return To_Task_ID
(Result
);
216 -----------------------------
217 -- Install_Signal_Handlers --
218 -----------------------------
220 procedure Install_Signal_Handlers
;
221 pragma Inline
(Install_Signal_Handlers
);
223 procedure Install_Signal_Handlers
is
224 act
: aliased struct_sigaction
;
225 old_act
: aliased struct_sigaction
;
226 Tmp_Set
: aliased sigset_t
;
227 Result
: Interfaces
.C
.int
;
231 act
.sa_handler
:= Abort_Handler
'Address;
233 Result
:= sigemptyset
(Tmp_Set
'Access);
234 pragma Assert
(Result
= 0);
235 act
.sa_mask
:= Tmp_Set
;
239 (Signal
(Interrupt_Management
.Abort_Task_Interrupt
),
240 act
'Unchecked_Access,
241 old_act
'Unchecked_Access);
242 pragma Assert
(Result
= 0);
244 Interrupt_Management
.Initialize_Interrupts
;
245 end Install_Signal_Handlers
;
247 ---------------------
248 -- Initialize_Lock --
249 ---------------------
251 -- Note: mutexes and cond_variables needed per-task basis are
252 -- initialized in Initialize_TCB and the Storage_Error is
253 -- handled. Other mutexes (such as All_Tasks_Lock, Memory_Lock...)
254 -- used in RTS is initialized before any status change of RTS.
255 -- Therefore rasing Storage_Error in the following routines
256 -- should be able to be handled safely.
258 procedure Initialize_Lock
259 (Prio
: System
.Any_Priority
;
262 Attributes
: aliased pthread_mutexattr_t
;
263 Result
: Interfaces
.C
.int
;
265 Result
:= pthread_mutexattr_init
(Attributes
'Access);
266 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
268 if Result
= ENOMEM
then
272 Result
:= pthread_mutexattr_setprotocol
273 (Attributes
'Access, Mutex_Protocol
);
274 pragma Assert
(Result
= 0);
276 Result
:= pthread_mutexattr_setprioceiling
277 (Attributes
'Access, Interfaces
.C
.int
(Prio
));
278 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
287 Result
:= pthread_mutexattr_destroy
(Attributes
'Access);
288 pragma Assert
(Result
= 0);
291 procedure Initialize_Lock
(L
: access RTS_Lock
; Level
: Lock_Level
) is
292 Attributes
: aliased pthread_mutexattr_t
;
293 Result
: Interfaces
.C
.int
;
296 Result
:= pthread_mutexattr_init
(Attributes
'Access);
297 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
299 if Result
= ENOMEM
then
303 Result
:= pthread_mutexattr_setprotocol
304 (Attributes
'Access, Mutex_Protocol
);
305 pragma Assert
(Result
= 0);
307 Result
:= pthread_mutexattr_setprioceiling
309 Interfaces
.C
.int
(System
.Any_Priority
'Last));
310 pragma Assert
(Result
= 0);
312 Result
:= pthread_mutex_init
(L
, Attributes
'Access);
313 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
315 if Result
= ENOMEM
then
319 Result
:= pthread_mutexattr_destroy
(Attributes
'Access);
320 pragma Assert
(Result
= 0);
327 procedure Finalize_Lock
(L
: access Lock
) is
328 Result
: Interfaces
.C
.int
;
331 Result
:= pthread_mutex_destroy
(L
);
332 pragma Assert
(Result
= 0);
335 procedure Finalize_Lock
(L
: access RTS_Lock
) is
336 Result
: Interfaces
.C
.int
;
339 Result
:= pthread_mutex_destroy
(L
);
340 pragma Assert
(Result
= 0);
347 procedure Write_Lock
(L
: access Lock
; Ceiling_Violation
: out Boolean) is
348 Result
: Interfaces
.C
.int
;
351 Result
:= pthread_mutex_lock
(L
);
353 -- Assume that the cause of EINVAL is a priority ceiling violation
355 Ceiling_Violation
:= (Result
= EINVAL
);
356 pragma Assert
(Result
= 0 or else Result
= EINVAL
);
359 procedure Write_Lock
(L
: access RTS_Lock
) is
360 Result
: Interfaces
.C
.int
;
363 Result
:= pthread_mutex_lock
(L
);
364 pragma Assert
(Result
= 0);
367 procedure Write_Lock
(T
: Task_ID
) is
368 Result
: Interfaces
.C
.int
;
371 Result
:= pthread_mutex_lock
(T
.Common
.LL
.L
'Access);
372 pragma Assert
(Result
= 0);
379 procedure Read_Lock
(L
: access Lock
; Ceiling_Violation
: out Boolean) is
381 Write_Lock
(L
, Ceiling_Violation
);
388 procedure Unlock
(L
: access Lock
) is
389 Result
: Interfaces
.C
.int
;
392 Result
:= pthread_mutex_unlock
(L
);
393 pragma Assert
(Result
= 0);
396 procedure Unlock
(L
: access RTS_Lock
) is
397 Result
: Interfaces
.C
.int
;
400 Result
:= pthread_mutex_unlock
(L
);
401 pragma Assert
(Result
= 0);
404 procedure Unlock
(T
: Task_ID
) is
405 Result
: Interfaces
.C
.int
;
408 Result
:= pthread_mutex_unlock
(T
.Common
.LL
.L
'Access);
409 pragma Assert
(Result
= 0);
416 procedure Sleep
(Self_ID
: Task_ID
;
417 Reason
: System
.Tasking
.Task_States
) is
418 Result
: Interfaces
.C
.int
;
421 pragma Assert
(Self_ID
= Self
);
422 Result
:= pthread_cond_wait
(Self_ID
.Common
.LL
.CV
'Access,
423 Self_ID
.Common
.LL
.L
'Access);
425 -- EINTR is not considered a failure.
427 pragma Assert
(Result
= 0 or else Result
= EINTR
);
434 -- This is for use within the run-time system, so abort is
435 -- assumed to be already deferred, and the caller should be
436 -- holding its own ATCB lock.
438 procedure Timed_Sleep
441 Mode
: ST
.Delay_Modes
;
442 Reason
: System
.Tasking
.Task_States
;
443 Timedout
: out Boolean;
444 Yielded
: out Boolean)
446 Check_Time
: constant Duration := Monotonic_Clock
;
448 Request
: aliased timespec
;
449 Result
: Interfaces
.C
.int
;
455 if Mode
= Relative
then
456 Abs_Time
:= Duration'Min (Time
, Max_Sensible_Delay
) + Check_Time
;
458 Abs_Time
:= Duration'Min (Check_Time
+ Max_Sensible_Delay
, Time
);
461 if Abs_Time
> Check_Time
then
462 Request
:= To_Timespec
(Abs_Time
);
464 exit when Self_ID
.Pending_ATC_Level
< Self_ID
.ATC_Nesting_Level
465 or else Self_ID
.Pending_Priority_Change
;
467 Result
:= pthread_cond_timedwait
(Self_ID
.Common
.LL
.CV
'Access,
468 Self_ID
.Common
.LL
.L
'Access, Request
'Access);
470 exit when Abs_Time
<= Monotonic_Clock
;
472 if Result
= 0 or Result
= EINTR
then
474 -- Somebody may have called Wakeup for us
480 pragma Assert
(Result
= ETIMEDOUT
);
489 -- This is for use in implementing delay statements, so
490 -- we assume the caller is abort-deferred but is holding
493 procedure Timed_Delay
496 Mode
: ST
.Delay_Modes
)
498 Check_Time
: constant Duration := Monotonic_Clock
;
500 Request
: aliased timespec
;
501 Result
: Interfaces
.C
.int
;
502 Yielded
: Boolean := False;
505 -- Only the little window between deferring abort and
506 -- locking Self_ID is the reason we need to
507 -- check for pending abort and priority change below! :(
510 Write_Lock
(Self_ID
);
512 if Mode
= Relative
then
513 Abs_Time
:= Time
+ Check_Time
;
515 Abs_Time
:= Duration'Min (Check_Time
+ Max_Sensible_Delay
, Time
);
518 if Abs_Time
> Check_Time
then
519 Request
:= To_Timespec
(Abs_Time
);
520 Self_ID
.Common
.State
:= Delay_Sleep
;
523 if Self_ID
.Pending_Priority_Change
then
524 Self_ID
.Pending_Priority_Change
:= False;
525 Self_ID
.Common
.Base_Priority
:= Self_ID
.New_Base_Priority
;
526 Set_Priority
(Self_ID
, Self_ID
.Common
.Base_Priority
);
529 exit when Self_ID
.Pending_ATC_Level
< Self_ID
.ATC_Nesting_Level
;
531 Result
:= pthread_cond_timedwait
(Self_ID
.Common
.LL
.CV
'Access,
532 Self_ID
.Common
.LL
.L
'Access, Request
'Access);
534 exit when Abs_Time
<= Monotonic_Clock
;
536 pragma Assert
(Result
= 0
537 or else Result
= ETIMEDOUT
538 or else Result
= EINTR
);
541 Self_ID
.Common
.State
:= Runnable
;
547 Result
:= sched_yield
;
549 SSL
.Abort_Undefer
.all;
552 ---------------------
553 -- Monotonic_Clock --
554 ---------------------
556 function Monotonic_Clock
return Duration is
557 TS
: aliased timespec
;
558 Result
: Interfaces
.C
.int
;
560 Result
:= clock_gettime
(CLOCK_REALTIME
, TS
'Unchecked_Access);
561 pragma Assert
(Result
= 0);
562 return To_Duration
(TS
);
569 function RT_Resolution
return Duration is
578 procedure Wakeup
(T
: Task_ID
; Reason
: System
.Tasking
.Task_States
) is
579 Result
: Interfaces
.C
.int
;
582 Result
:= pthread_cond_signal
(T
.Common
.LL
.CV
'Access);
583 pragma Assert
(Result
= 0);
590 procedure Yield
(Do_Yield
: Boolean := True) is
591 Result
: Interfaces
.C
.int
;
594 Result
:= sched_yield
;
601 type Prio_Array_Type
is array (System
.Any_Priority
) of Integer;
602 pragma Atomic_Components
(Prio_Array_Type
);
604 Prio_Array
: Prio_Array_Type
;
605 -- Global array containing the id of the currently running task for
608 -- Note: we assume that we are on a single processor with run-til-blocked
611 procedure Set_Priority
613 Prio
: System
.Any_Priority
;
614 Loss_Of_Inheritance
: Boolean := False)
616 Param
: aliased struct_sched_param
;
617 Array_Item
: Integer;
618 Result
: Interfaces
.C
.int
;
621 Param
.sched_priority
:= Interfaces
.C
.int
(Prio
);
623 if Time_Slice_Val
<= 0 then
624 Result
:= pthread_setschedparam
625 (T
.Common
.LL
.Thread
, SCHED_FIFO
, Param
'Access);
627 Result
:= pthread_setschedparam
628 (T
.Common
.LL
.Thread
, SCHED_RR
, Param
'Access);
631 pragma Assert
(Result
= 0);
633 if FIFO_Within_Priorities
then
635 -- Annex D requirement [RM D.2.2 par. 9]:
636 -- If the task drops its priority due to the loss of inherited
637 -- priority, it is added at the head of the ready queue for its
638 -- new active priority.
640 if Loss_Of_Inheritance
641 and then Prio
< T
.Common
.Current_Priority
643 Array_Item
:= Prio_Array
(T
.Common
.Base_Priority
) + 1;
644 Prio_Array
(T
.Common
.Base_Priority
) := Array_Item
;
647 -- Let some processes a chance to arrive
651 -- Then wait for our turn to proceed
653 exit when Array_Item
= Prio_Array
(T
.Common
.Base_Priority
)
654 or else Prio_Array
(T
.Common
.Base_Priority
) = 1;
657 Prio_Array
(T
.Common
.Base_Priority
) :=
658 Prio_Array
(T
.Common
.Base_Priority
) - 1;
662 T
.Common
.Current_Priority
:= Prio
;
669 function Get_Priority
(T
: Task_ID
) return System
.Any_Priority
is
671 return T
.Common
.Current_Priority
;
678 procedure Enter_Task
(Self_ID
: Task_ID
) is
679 Result
: Interfaces
.C
.int
;
681 procedure Init_Float
;
682 pragma Import
(C
, Init_Float
, "__gnat_init_float");
683 -- Properly initializes the FPU for PPC/MIPS systems.
686 Self_ID
.Common
.LL
.Thread
:= pthread_self
;
688 Result
:= pthread_setspecific
(ATCB_Key
, To_Address
(Self_ID
));
689 pragma Assert
(Result
= 0);
693 -- Install the signal handlers.
694 -- This is called for each task since there is no signal inheritance
695 -- between VxWorks tasks.
697 Install_Signal_Handlers
;
701 for T
in Known_Tasks
'Range loop
702 if Known_Tasks
(T
) = null then
703 Known_Tasks
(T
) := Self_ID
;
704 Self_ID
.Known_Tasks_Index
:= T
;
709 Unlock_All_Tasks_List
;
716 function New_ATCB
(Entry_Num
: Task_Entry_Index
) return Task_ID
is
718 return new Ada_Task_Control_Block
(Entry_Num
);
721 ----------------------
723 ----------------------
725 procedure Initialize_TCB
(Self_ID
: Task_ID
; Succeeded
: out Boolean) is
726 Mutex_Attr
: aliased pthread_mutexattr_t
;
727 Result
: Interfaces
.C
.int
;
728 Cond_Attr
: aliased pthread_condattr_t
;
731 Self_ID
.Common
.LL
.Thread
:= null_pthread
;
733 Result
:= pthread_mutexattr_init
(Mutex_Attr
'Access);
734 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
741 Result
:= pthread_mutexattr_setprotocol
742 (Mutex_Attr
'Access, Mutex_Protocol
);
743 pragma Assert
(Result
= 0);
745 Result
:= pthread_mutexattr_setprioceiling
746 (Mutex_Attr
'Access, Interfaces
.C
.int
(System
.Any_Priority
'Last));
747 pragma Assert
(Result
= 0);
749 Result
:= pthread_mutex_init
(Self_ID
.Common
.LL
.L
'Access,
751 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
758 Result
:= pthread_mutexattr_destroy
(Mutex_Attr
'Access);
759 pragma Assert
(Result
= 0);
761 Result
:= pthread_condattr_init
(Cond_Attr
'Access);
762 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
765 Result
:= pthread_mutex_destroy
(Self_ID
.Common
.LL
.L
'Access);
766 pragma Assert
(Result
= 0);
771 Result
:= pthread_cond_init
(Self_ID
.Common
.LL
.CV
'Access,
773 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
778 Result
:= pthread_mutex_destroy
(Self_ID
.Common
.LL
.L
'Access);
779 pragma Assert
(Result
= 0);
783 Result
:= pthread_condattr_destroy
(Cond_Attr
'Access);
784 pragma Assert
(Result
= 0);
791 procedure Create_Task
793 Wrapper
: System
.Address
;
794 Stack_Size
: System
.Parameters
.Size_Type
;
795 Priority
: System
.Any_Priority
;
796 Succeeded
: out Boolean)
798 use type System
.Task_Info
.Task_Image_Type
;
800 Adjusted_Stack_Size
: Interfaces
.C
.size_t
;
801 Attributes
: aliased pthread_attr_t
;
802 Result
: Interfaces
.C
.int
;
804 function Thread_Body_Access
is new
805 Unchecked_Conversion
(System
.Address
, Thread_Body
);
808 if Stack_Size
= Unspecified_Size
then
809 Adjusted_Stack_Size
:= Interfaces
.C
.size_t
(Default_Stack_Size
);
811 elsif Stack_Size
< Minimum_Stack_Size
then
812 Adjusted_Stack_Size
:= Interfaces
.C
.size_t
(Minimum_Stack_Size
);
815 Adjusted_Stack_Size
:= Interfaces
.C
.size_t
(Stack_Size
);
818 -- Ask for 4 extra bytes of stack space so that the ATCB
819 -- pointer can be stored below the stack limit, plus extra
820 -- space for the frame of Task_Wrapper. This is so the user
821 -- gets the amount of stack requested exclusive of the needs
824 -- We also have to allocate 10 more bytes for the task name
825 -- storage and enough space for the Wind Task Control Block
826 -- which is around 0x778 bytes. VxWorks also seems to carve out
827 -- additional space, so use 2048 as a nice round number.
828 -- We might want to increment to the nearest page size in
829 -- case we ever support VxVMI.
831 -- XXX - we should come back and visit this so we can
832 -- set the task name to something appropriate.
833 Adjusted_Stack_Size
:= Adjusted_Stack_Size
+ 2048;
835 Result
:= pthread_attr_init
(Attributes
'Access);
836 pragma Assert
(Result
= 0 or else Result
= ENOMEM
);
843 Result
:= pthread_attr_setdetachstate
844 (Attributes
'Access, PTHREAD_CREATE_DETACHED
);
845 pragma Assert
(Result
= 0);
847 Result
:= pthread_attr_setstacksize
848 (Attributes
'Access, Adjusted_Stack_Size
);
849 pragma Assert
(Result
= 0);
851 -- Let's check to see if the task has an image string and
852 -- use that as the VxWorks task name.
853 if T
.Common
.Task_Image
/= null then
855 Task_Name
: aliased constant String :=
856 T
.Common
.Task_Image
.all & ASCII
.NUL
;
858 Result
:= pthread_attr_setname_np
859 (Attributes
'Access, Task_Name
'Address);
861 -- Since the initial signal mask of a thread is inherited from the
862 -- creator, and the Environment task has all its signals masked,
863 -- we do not need to manipulate caller's signal mask at this
864 -- point. All tasks in RTS will have All_Tasks_Mask initially.
865 Result
:= pthread_create
866 (T
.Common
.LL
.Thread
'Access,
868 Thread_Body_Access
(Wrapper
),
872 -- No specified task name
873 Result
:= pthread_create
874 (T
.Common
.LL
.Thread
'Access,
876 Thread_Body_Access
(Wrapper
),
879 pragma Assert
(Result
= 0);
881 Succeeded
:= Result
= 0;
883 Result
:= pthread_attr_destroy
(Attributes
'Access);
884 pragma Assert
(Result
= 0);
886 Task_Creation_Hook
(T
.Common
.LL
.Thread
);
888 Set_Priority
(T
, Priority
);
895 procedure Finalize_TCB
(T
: Task_ID
) is
896 Result
: Interfaces
.C
.int
;
899 procedure Free
is new
900 Unchecked_Deallocation
(Ada_Task_Control_Block
, Task_ID
);
903 T
.Common
.LL
.Thread
:= null_pthread
;
905 Result
:= pthread_mutex_destroy
(T
.Common
.LL
.L
'Access);
906 pragma Assert
(Result
= 0);
908 Result
:= pthread_cond_destroy
(T
.Common
.LL
.CV
'Access);
909 pragma Assert
(Result
= 0);
911 if T
.Known_Tasks_Index
/= -1 then
912 Known_Tasks
(T
.Known_Tasks_Index
) := null;
922 procedure Exit_Task
is
924 Task_Termination_Hook
;
925 pthread_exit
(System
.Null_Address
);
932 procedure Abort_Task
(T
: Task_ID
) is
933 Result
: Interfaces
.C
.int
;
935 Result
:= kill
(T
.Common
.LL
.Thread
,
936 Signal
(Interrupt_Management
.Abort_Task_Interrupt
));
937 pragma Assert
(Result
= 0);
944 -- Dummy versions. The only currently working versions is for solaris
947 function Check_Exit
(Self_ID
: ST
.Task_ID
) return Boolean is
956 function Check_No_Locks
(Self_ID
: ST
.Task_ID
) return Boolean is
961 ----------------------
962 -- Environment_Task --
963 ----------------------
965 function Environment_Task
return Task_ID
is
967 return Environment_Task_ID
;
968 end Environment_Task
;
970 -------------------------
971 -- Lock_All_Tasks_List --
972 -------------------------
974 procedure Lock_All_Tasks_List
is
976 Write_Lock
(All_Tasks_L
'Access);
977 end Lock_All_Tasks_List
;
979 ---------------------------
980 -- Unlock_All_Tasks_List --
981 ---------------------------
983 procedure Unlock_All_Tasks_List
is
985 Unlock
(All_Tasks_L
'Access);
986 end Unlock_All_Tasks_List
;
992 function Suspend_Task
994 Thread_Self
: Thread_Id
) return Boolean is
996 if T
.Common
.LL
.Thread
/= null_pthread
997 and then T
.Common
.LL
.Thread
/= Thread_Self
999 return taskSuspend
(T
.Common
.LL
.Thread
) = 0;
1009 function Resume_Task
1011 Thread_Self
: Thread_Id
) return Boolean is
1013 if T
.Common
.LL
.Thread
/= null_pthread
1014 and then T
.Common
.LL
.Thread
/= Thread_Self
1016 return taskResume
(T
.Common
.LL
.Thread
) = 0;
1026 procedure Initialize
(Environment_Task
: Task_ID
) is
1028 Environment_Task_ID
:= Environment_Task
;
1030 -- Initialize the lock used to synchronize chain of all ATCBs.
1032 Initialize_Lock
(All_Tasks_L
'Access, All_Tasks_Level
);
1034 Enter_Task
(Environment_Task
);
1039 Result
: Interfaces
.C
.int
;
1042 if Locking_Policy
= 'C' then
1043 Mutex_Protocol
:= PTHREAD_PRIO_PROTECT
;
1045 -- We default to VxWorks native priority inheritence
1046 -- and inversion safe mutexes with no ceiling checks.
1047 Mutex_Protocol
:= PTHREAD_PRIO_INHERIT
;
1050 if Time_Slice_Val
> 0 then
1051 Result
:= pthread_sched_rr_set_interval
1052 (Interfaces
.C
.int
(Time_Slice_Val
));
1055 -- Prepare the set of signals that should unblocked in all tasks
1057 Result
:= sigemptyset
(Unblocked_Signal_Mask
'Access);
1058 pragma Assert
(Result
= 0);
1060 for J
in Interrupt_Management
.Interrupt_ID
loop
1061 if Interrupt_Management
.Keep_Unmasked
(J
) then
1062 Result
:= sigaddset
(Unblocked_Signal_Mask
'Access, Signal
(J
));
1063 pragma Assert
(Result
= 0);
1067 Result
:= pthread_key_create
(ATCB_Key
'Access, null);
1068 pragma Assert
(Result
= 0);
1070 Result
:= taskVarAdd
(getpid
, Stack_Limit
'Access);
1071 pragma Assert
(Result
= 0);
1073 end System
.Task_Primitives
.Operations
;