OSDN Git Service

* reload1.c (reload_cse_simplify): Fix typo in rtx code check.
[pf3gnuchains/gcc-fork.git] / gcc / ada / 5htaprop.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS               --
4 --                                                                          --
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    --
6 --                                                                          --
7 --                                  B o d y                                 --
8 --                                                                          --
9 --                                                                          --
10 --         Copyright (C) 1992-2001, Free Software Foundation, Inc.          --
11 --                                                                          --
12 -- GNARL is free software; you can  redistribute it  and/or modify it under --
13 -- terms of the  GNU General Public License as published  by the Free Soft- --
14 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
15 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
18 -- for  more details.  You should have  received  a copy of the GNU General --
19 -- Public License  distributed with GNARL; see file COPYING.  If not, write --
20 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
21 -- MA 02111-1307, USA.                                                      --
22 --                                                                          --
23 -- As a special exception,  if other files  instantiate  generics from this --
24 -- unit, or you link  this unit with other files  to produce an executable, --
25 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
26 -- covered  by the  GNU  General  Public  License.  This exception does not --
27 -- however invalidate  any other reasons why  the executable file  might be --
28 -- covered by the  GNU Public License.                                      --
29 --                                                                          --
30 -- GNARL was developed by the GNARL team at Florida State University. It is --
31 -- now maintained by Ada Core Technologies, Inc. (http://www.gnat.com).     --
32 --                                                                          --
33 ------------------------------------------------------------------------------
34
35 --  This is a HP-UX DCE threads version of this package
36
37 --  This package contains all the GNULL primitives that interface directly
38 --  with the underlying OS.
39
40 pragma Polling (Off);
41 --  Turn off polling, we do not want ATC polling to take place during
42 --  tasking operations. It causes infinite loops and other problems.
43
44 with System.Tasking.Debug;
45 --  used for Known_Tasks
46
47 with Interfaces.C;
48 --  used for int
49 --           size_t
50
51 with System.Interrupt_Management;
52 --  used for Keep_Unmasked
53 --           Abort_Task_Interrupt
54 --           Interrupt_ID
55
56 with System.Interrupt_Management.Operations;
57 --  used for Set_Interrupt_Mask
58 --           All_Tasks_Mask
59 pragma Elaborate_All (System.Interrupt_Management.Operations);
60
61 with System.Parameters;
62 --  used for Size_Type
63
64 with System.Task_Primitives.Interrupt_Operations;
65 --  used for Get_Interrupt_ID
66
67 with System.Tasking;
68 --  used for Ada_Task_Control_Block
69 --           Task_ID
70
71 with System.Soft_Links;
72 --  used for Defer/Undefer_Abort
73
74 --  Note that we do not use System.Tasking.Initialization directly since
75 --  this is a higher level package that we shouldn't depend on. For example
76 --  when using the restricted run time, it is replaced by
77 --  System.Tasking.Restricted.Initialization
78
79 with System.OS_Primitives;
80 --  used for Delay_Modes
81
82 with Unchecked_Conversion;
83 with Unchecked_Deallocation;
84
85 package body System.Task_Primitives.Operations is
86
87    use System.Tasking.Debug;
88    use System.Tasking;
89    use Interfaces.C;
90    use System.OS_Interface;
91    use System.Parameters;
92    use System.OS_Primitives;
93
94    package PIO renames System.Task_Primitives.Interrupt_Operations;
95    package SSL renames System.Soft_Links;
96
97    ------------------
98    --  Local Data  --
99    ------------------
100
101    --  The followings are logically constants, but need to be initialized
102    --  at run time.
103
104    ATCB_Key : aliased pthread_key_t;
105    --  Key used to find the Ada Task_ID associated with a thread
106
107    Single_RTS_Lock : aliased RTS_Lock;
108    --  This is a lock to allow only one thread of control in the RTS at
109    --  a time; it is used to execute in mutual exclusion from all other tasks.
110    --  Used mainly in Single_Lock mode, but also to protect All_Tasks_List
111
112    Environment_Task_ID : Task_ID;
113    --  A variable to hold Task_ID for the environment task.
114
115    Unblocked_Signal_Mask : aliased sigset_t;
116    --  The set of signals that should unblocked in all tasks
117
118    Time_Slice_Val : Integer;
119    pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
120
121    Locking_Policy : Character;
122    pragma Import (C, Locking_Policy, "__gl_locking_policy");
123
124    Dispatching_Policy : Character;
125    pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
126
127    FIFO_Within_Priorities : constant Boolean := Dispatching_Policy = 'F';
128    --  Indicates whether FIFO_Within_Priorities is set.
129
130    --  The followings are internal configuration constants needed.
131
132    -----------------------
133    -- Local Subprograms --
134    -----------------------
135
136    procedure Abort_Handler (Sig : Signal);
137
138    function To_Task_ID is new Unchecked_Conversion (System.Address, Task_ID);
139
140    function To_Address is new Unchecked_Conversion (Task_ID, System.Address);
141
142    -------------------
143    -- Abort_Handler --
144    -------------------
145
146    procedure Abort_Handler (Sig : Signal) is
147       Self_Id : constant Task_ID := Self;
148       Result  : Interfaces.C.int;
149       Old_Set : aliased sigset_t;
150
151    begin
152       if Self_Id.Deferral_Level = 0
153         and then Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level and then
154         not Self_Id.Aborting
155       then
156          Self_Id.Aborting := True;
157
158          --  Make sure signals used for RTS internal purpose are unmasked
159
160          Result := pthread_sigmask (SIG_UNBLOCK,
161            Unblocked_Signal_Mask'Unchecked_Access, Old_Set'Unchecked_Access);
162          pragma Assert (Result = 0);
163
164          raise Standard'Abort_Signal;
165       end if;
166    end Abort_Handler;
167
168    -----------------
169    -- Stack_Guard --
170    -----------------
171
172    --  The underlying thread system sets a guard page at the
173    --  bottom of a thread stack, so nothing is needed.
174    --  ??? Check the comment above
175
176    procedure Stack_Guard (T : ST.Task_ID; On : Boolean) is
177    begin
178       null;
179    end Stack_Guard;
180
181    -------------------
182    -- Get_Thread_Id --
183    -------------------
184
185    function Get_Thread_Id (T : ST.Task_ID) return OSI.Thread_Id is
186    begin
187       return T.Common.LL.Thread;
188    end Get_Thread_Id;
189
190    ----------
191    -- Self --
192    ----------
193
194    function Self return Task_ID is
195       Result : System.Address;
196    begin
197       Result := pthread_getspecific (ATCB_Key);
198       pragma Assert (Result /= System.Null_Address);
199       return To_Task_ID (Result);
200    end Self;
201
202    ---------------------
203    -- Initialize_Lock --
204    ---------------------
205
206    --  Note: mutexes and cond_variables needed per-task basis are
207    --        initialized in Initialize_TCB and the Storage_Error is
208    --        handled. Other mutexes (such as RTS_Lock, Memory_Lock...)
209    --        used in RTS is initialized before any status change of RTS.
210    --        Therefore rasing Storage_Error in the following routines
211    --        should be able to be handled safely.
212
213    procedure Initialize_Lock
214      (Prio : System.Any_Priority;
215       L    : access Lock)
216    is
217       Attributes : aliased pthread_mutexattr_t;
218       Result     : Interfaces.C.int;
219
220    begin
221       Result := pthread_mutexattr_init (Attributes'Access);
222       pragma Assert (Result = 0 or else Result = ENOMEM);
223
224       if Result = ENOMEM then
225          raise Storage_Error;
226       end if;
227
228       L.Priority := Prio;
229
230       Result := pthread_mutex_init (L.L'Access, Attributes'Access);
231       pragma Assert (Result = 0 or else Result = ENOMEM);
232
233       if Result = ENOMEM then
234          raise Storage_Error;
235       end if;
236
237       Result := pthread_mutexattr_destroy (Attributes'Access);
238       pragma Assert (Result = 0);
239    end Initialize_Lock;
240
241    procedure Initialize_Lock (L : access RTS_Lock; Level : Lock_Level) is
242       Attributes : aliased pthread_mutexattr_t;
243       Result     : Interfaces.C.int;
244
245    begin
246       Result := pthread_mutexattr_init (Attributes'Access);
247       pragma Assert (Result = 0 or else Result = ENOMEM);
248
249       if Result = ENOMEM then
250          raise Storage_Error;
251       end if;
252
253       Result := pthread_mutex_init (L, Attributes'Access);
254
255       pragma Assert (Result = 0 or else Result = ENOMEM);
256
257       if Result = ENOMEM then
258          raise Storage_Error;
259       end if;
260
261       Result := pthread_mutexattr_destroy (Attributes'Access);
262       pragma Assert (Result = 0);
263    end Initialize_Lock;
264
265    -------------------
266    -- Finalize_Lock --
267    -------------------
268
269    procedure Finalize_Lock (L : access Lock) is
270       Result : Interfaces.C.int;
271    begin
272       Result := pthread_mutex_destroy (L.L'Access);
273       pragma Assert (Result = 0);
274    end Finalize_Lock;
275
276    procedure Finalize_Lock (L : access RTS_Lock) is
277       Result : Interfaces.C.int;
278    begin
279       Result := pthread_mutex_destroy (L);
280       pragma Assert (Result = 0);
281    end Finalize_Lock;
282
283    ----------------
284    -- Write_Lock --
285    ----------------
286
287    procedure Write_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
288       Result : Interfaces.C.int;
289    begin
290       L.Owner_Priority := Get_Priority (Self);
291
292       if L.Priority < L.Owner_Priority then
293          Ceiling_Violation := True;
294          return;
295       end if;
296
297       Result := pthread_mutex_lock (L.L'Access);
298       pragma Assert (Result = 0);
299       Ceiling_Violation := False;
300    end Write_Lock;
301
302    procedure Write_Lock
303      (L : access RTS_Lock; Global_Lock : Boolean := False)
304    is
305       Result : Interfaces.C.int;
306    begin
307       if not Single_Lock or else Global_Lock then
308          Result := pthread_mutex_lock (L);
309          pragma Assert (Result = 0);
310       end if;
311    end Write_Lock;
312
313    procedure Write_Lock (T : Task_ID) is
314       Result : Interfaces.C.int;
315    begin
316       if not Single_Lock then
317          Result := pthread_mutex_lock (T.Common.LL.L'Access);
318          pragma Assert (Result = 0);
319       end if;
320    end Write_Lock;
321
322    ---------------
323    -- Read_Lock --
324    ---------------
325
326    procedure Read_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
327    begin
328       Write_Lock (L, Ceiling_Violation);
329    end Read_Lock;
330
331    ------------
332    -- Unlock --
333    ------------
334
335    procedure Unlock (L : access Lock) is
336       Result : Interfaces.C.int;
337    begin
338       Result := pthread_mutex_unlock (L.L'Access);
339       pragma Assert (Result = 0);
340    end Unlock;
341
342    procedure Unlock (L : access RTS_Lock; Global_Lock : Boolean := False) is
343       Result : Interfaces.C.int;
344    begin
345       if not Single_Lock or else Global_Lock then
346          Result := pthread_mutex_unlock (L);
347          pragma Assert (Result = 0);
348       end if;
349    end Unlock;
350
351    procedure Unlock (T : Task_ID) is
352       Result : Interfaces.C.int;
353    begin
354       if not Single_Lock then
355          Result := pthread_mutex_unlock (T.Common.LL.L'Access);
356          pragma Assert (Result = 0);
357       end if;
358    end Unlock;
359
360    -----------
361    -- Sleep --
362    -----------
363
364    procedure Sleep
365      (Self_ID : Task_ID;
366       Reason  : System.Tasking.Task_States)
367    is
368       Result : Interfaces.C.int;
369    begin
370       if Single_Lock then
371          Result := pthread_cond_wait
372            (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
373       else
374          Result := pthread_cond_wait
375            (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
376       end if;
377
378       --  EINTR is not considered a failure.
379       pragma Assert (Result = 0 or else Result = EINTR);
380    end Sleep;
381
382    -----------------
383    -- Timed_Sleep --
384    -----------------
385
386    procedure Timed_Sleep
387      (Self_ID  : Task_ID;
388       Time     : Duration;
389       Mode     : ST.Delay_Modes;
390       Reason   : System.Tasking.Task_States;
391       Timedout : out Boolean;
392       Yielded  : out Boolean)
393    is
394       Check_Time : constant Duration := Monotonic_Clock;
395       Abs_Time   : Duration;
396       Request    : aliased timespec;
397       Result     : Interfaces.C.int;
398
399    begin
400       Timedout := True;
401       Yielded := False;
402
403       if Mode = Relative then
404          Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
405       else
406          Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
407       end if;
408
409       if Abs_Time > Check_Time then
410          Request := To_Timespec (Abs_Time);
411
412          loop
413             exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
414               or else Self_ID.Pending_Priority_Change;
415
416             if Single_Lock then
417                Result := pthread_cond_timedwait
418                  (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access,
419                   Request'Access);
420
421             else
422                Result := pthread_cond_timedwait
423                  (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access,
424                   Request'Access);
425             end if;
426
427             exit when Abs_Time <= Monotonic_Clock;
428
429             if Result = 0 or Result = EINTR then
430                --  somebody may have called Wakeup for us
431                Timedout := False;
432                exit;
433             end if;
434
435             pragma Assert (Result = ETIMEDOUT);
436          end loop;
437       end if;
438    end Timed_Sleep;
439
440    -----------------
441    -- Timed_Delay --
442    -----------------
443
444    procedure Timed_Delay
445      (Self_ID  : Task_ID;
446       Time     : Duration;
447       Mode     : ST.Delay_Modes)
448    is
449       Check_Time : constant Duration := Monotonic_Clock;
450       Abs_Time   : Duration;
451       Request    : aliased timespec;
452       Result     : Interfaces.C.int;
453
454    begin
455       --  Only the little window between deferring abort and
456       --  locking Self_ID is the reason we need to
457       --  check for pending abort and priority change below! :(
458
459       SSL.Abort_Defer.all;
460
461       if Single_Lock then
462          Lock_RTS;
463       end if;
464
465       Write_Lock (Self_ID);
466
467       if Mode = Relative then
468          Abs_Time := Time + Check_Time;
469       else
470          Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
471       end if;
472
473       if Abs_Time > Check_Time then
474          Request := To_Timespec (Abs_Time);
475          Self_ID.Common.State := Delay_Sleep;
476
477          loop
478             if Self_ID.Pending_Priority_Change then
479                Self_ID.Pending_Priority_Change := False;
480                Self_ID.Common.Base_Priority := Self_ID.New_Base_Priority;
481                Set_Priority (Self_ID, Self_ID.Common.Base_Priority);
482             end if;
483
484             exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
485
486             if Single_Lock then
487                Result := pthread_cond_timedwait (Self_ID.Common.LL.CV'Access,
488                  Single_RTS_Lock'Access, Request'Access);
489             else
490                Result := pthread_cond_timedwait (Self_ID.Common.LL.CV'Access,
491                  Self_ID.Common.LL.L'Access, Request'Access);
492             end if;
493
494             exit when Abs_Time <= Monotonic_Clock;
495
496             pragma Assert (Result = 0 or else
497               Result = ETIMEDOUT or else
498               Result = EINTR);
499          end loop;
500
501          Self_ID.Common.State := Runnable;
502       end if;
503
504       Unlock (Self_ID);
505
506       if Single_Lock then
507          Unlock_RTS;
508       end if;
509
510       Result := sched_yield;
511       SSL.Abort_Undefer.all;
512    end Timed_Delay;
513
514    ---------------------
515    -- Monotonic_Clock --
516    ---------------------
517
518    function Monotonic_Clock return Duration is
519       TS     : aliased timespec;
520       Result : Interfaces.C.int;
521
522    begin
523       Result := Clock_Gettime (CLOCK_REALTIME, TS'Unchecked_Access);
524       pragma Assert (Result = 0);
525       return To_Duration (TS);
526    end Monotonic_Clock;
527
528    -------------------
529    -- RT_Resolution --
530    -------------------
531
532    function RT_Resolution return Duration is
533    begin
534       return 10#1.0#E-6;
535    end RT_Resolution;
536
537    ------------
538    -- Wakeup --
539    ------------
540
541    procedure Wakeup (T : Task_ID; Reason : System.Tasking.Task_States) is
542       Result : Interfaces.C.int;
543    begin
544       Result := pthread_cond_signal (T.Common.LL.CV'Access);
545       pragma Assert (Result = 0);
546    end Wakeup;
547
548    -----------
549    -- Yield --
550    -----------
551
552    procedure Yield (Do_Yield : Boolean := True) is
553       Result : Interfaces.C.int;
554    begin
555       if Do_Yield then
556          Result := sched_yield;
557       end if;
558    end Yield;
559
560    ------------------
561    -- Set_Priority --
562    ------------------
563
564    type Prio_Array_Type is array (System.Any_Priority) of Integer;
565    pragma Atomic_Components (Prio_Array_Type);
566
567    Prio_Array : Prio_Array_Type;
568    --  Global array containing the id of the currently running task for
569    --  each priority.
570    --
571    --  Note: we assume that we are on a single processor with run-til-blocked
572    --  scheduling.
573
574    procedure Set_Priority
575      (T : Task_ID;
576       Prio : System.Any_Priority;
577       Loss_Of_Inheritance : Boolean := False)
578    is
579       Result     : Interfaces.C.int;
580       Array_Item : Integer;
581       Param      : aliased struct_sched_param;
582
583    begin
584       Param.sched_priority  := Interfaces.C.int (Underlying_Priorities (Prio));
585
586       if Time_Slice_Val > 0 then
587          Result := pthread_setschedparam
588            (T.Common.LL.Thread, SCHED_RR, Param'Access);
589
590       elsif FIFO_Within_Priorities or else Time_Slice_Val = 0 then
591          Result := pthread_setschedparam
592            (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
593
594       else
595          Result := pthread_setschedparam
596            (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
597       end if;
598
599       pragma Assert (Result = 0);
600
601       if FIFO_Within_Priorities then
602
603          --  Annex D requirement [RM D.2.2 par. 9]:
604          --    If the task drops its priority due to the loss of inherited
605          --    priority, it is added at the head of the ready queue for its
606          --    new active priority.
607
608          if Loss_Of_Inheritance
609            and then Prio < T.Common.Current_Priority
610          then
611             Array_Item := Prio_Array (T.Common.Base_Priority) + 1;
612             Prio_Array (T.Common.Base_Priority) := Array_Item;
613
614             loop
615                --  Let some processes a chance to arrive
616
617                Yield;
618
619                --  Then wait for our turn to proceed
620
621                exit when Array_Item = Prio_Array (T.Common.Base_Priority)
622                  or else Prio_Array (T.Common.Base_Priority) = 1;
623             end loop;
624
625             Prio_Array (T.Common.Base_Priority) :=
626               Prio_Array (T.Common.Base_Priority) - 1;
627          end if;
628       end if;
629
630       T.Common.Current_Priority := Prio;
631    end Set_Priority;
632
633    ------------------
634    -- Get_Priority --
635    ------------------
636
637    function Get_Priority (T : Task_ID) return System.Any_Priority is
638    begin
639       return T.Common.Current_Priority;
640    end Get_Priority;
641
642    ----------------
643    -- Enter_Task --
644    ----------------
645
646    procedure Enter_Task (Self_ID : Task_ID) is
647       Result  : Interfaces.C.int;
648
649    begin
650       Self_ID.Common.LL.Thread := pthread_self;
651
652       Result := pthread_setspecific (ATCB_Key, To_Address (Self_ID));
653       pragma Assert (Result = 0);
654
655       Lock_RTS;
656
657       for J in Known_Tasks'Range loop
658          if Known_Tasks (J) = null then
659             Known_Tasks (J) := Self_ID;
660             Self_ID.Known_Tasks_Index := J;
661             exit;
662          end if;
663       end loop;
664
665       Unlock_RTS;
666    end Enter_Task;
667
668    --------------
669    -- New_ATCB --
670    --------------
671
672    function New_ATCB (Entry_Num : Task_Entry_Index) return Task_ID is
673    begin
674       return new Ada_Task_Control_Block (Entry_Num);
675    end New_ATCB;
676
677    --------------------
678    -- Initialize_TCB --
679    --------------------
680
681    procedure Initialize_TCB (Self_ID : Task_ID; Succeeded : out Boolean) is
682       Mutex_Attr : aliased pthread_mutexattr_t;
683       Result     : Interfaces.C.int;
684       Cond_Attr  : aliased pthread_condattr_t;
685
686    begin
687       if not Single_Lock then
688          Result := pthread_mutexattr_init (Mutex_Attr'Access);
689          pragma Assert (Result = 0 or else Result = ENOMEM);
690
691          if Result = 0 then
692             Result := pthread_mutex_init (Self_ID.Common.LL.L'Access,
693               Mutex_Attr'Access);
694             pragma Assert (Result = 0 or else Result = ENOMEM);
695          end if;
696
697          if Result /= 0 then
698             Succeeded := False;
699             return;
700          end if;
701
702          Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
703          pragma Assert (Result = 0);
704       end if;
705
706       Result := pthread_condattr_init (Cond_Attr'Access);
707       pragma Assert (Result = 0 or else Result = ENOMEM);
708
709       if Result = 0 then
710          Result := pthread_cond_init (Self_ID.Common.LL.CV'Access,
711            Cond_Attr'Access);
712          pragma Assert (Result = 0 or else Result = ENOMEM);
713       end if;
714
715       if Result = 0 then
716          Succeeded := True;
717       else
718          if not Single_Lock then
719             Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
720             pragma Assert (Result = 0);
721          end if;
722
723          Succeeded := False;
724       end if;
725
726       Result := pthread_condattr_destroy (Cond_Attr'Access);
727       pragma Assert (Result = 0);
728    end Initialize_TCB;
729
730    -----------------
731    -- Create_Task --
732    -----------------
733
734    procedure Create_Task
735      (T          : Task_ID;
736       Wrapper    : System.Address;
737       Stack_Size : System.Parameters.Size_Type;
738       Priority   : System.Any_Priority;
739       Succeeded  : out Boolean)
740    is
741       Attributes          : aliased pthread_attr_t;
742       Adjusted_Stack_Size : Interfaces.C.size_t;
743       Result              : Interfaces.C.int;
744
745       function Thread_Body_Access is new
746         Unchecked_Conversion (System.Address, Thread_Body);
747
748    begin
749       if Stack_Size = Unspecified_Size then
750          Adjusted_Stack_Size := Interfaces.C.size_t (Default_Stack_Size);
751
752       elsif Stack_Size < Minimum_Stack_Size then
753          Adjusted_Stack_Size := Interfaces.C.size_t (Minimum_Stack_Size);
754
755       else
756          Adjusted_Stack_Size := Interfaces.C.size_t (Stack_Size);
757       end if;
758
759       Result := pthread_attr_init (Attributes'Access);
760       pragma Assert (Result = 0 or else Result = ENOMEM);
761
762       if Result /= 0 then
763          Succeeded := False;
764          return;
765       end if;
766
767       Result := pthread_attr_setstacksize
768         (Attributes'Access, Adjusted_Stack_Size);
769       pragma Assert (Result = 0);
770
771       --  Since the initial signal mask of a thread is inherited from the
772       --  creator, and the Environment task has all its signals masked, we
773       --  do not need to manipulate caller's signal mask at this point.
774       --  All tasks in RTS will have All_Tasks_Mask initially.
775
776       Result := pthread_create
777         (T.Common.LL.Thread'Access,
778          Attributes'Access,
779          Thread_Body_Access (Wrapper),
780          To_Address (T));
781       pragma Assert (Result = 0 or else Result = EAGAIN);
782
783       Succeeded := Result = 0;
784
785       pthread_detach (T.Common.LL.Thread'Access);
786       --  Detach the thread using pthread_detach, sinc DCE threads do not have
787       --  pthread_attr_set_detachstate.
788
789       Result := pthread_attr_destroy (Attributes'Access);
790       pragma Assert (Result = 0);
791
792       Set_Priority (T, Priority);
793    end Create_Task;
794
795    ------------------
796    -- Finalize_TCB --
797    ------------------
798
799    procedure Finalize_TCB (T : Task_ID) is
800       Result : Interfaces.C.int;
801       Tmp    : Task_ID := T;
802
803       procedure Free is new
804         Unchecked_Deallocation (Ada_Task_Control_Block, Task_ID);
805
806    begin
807       if not Single_Lock then
808          Result := pthread_mutex_destroy (T.Common.LL.L'Access);
809          pragma Assert (Result = 0);
810       end if;
811
812       Result := pthread_cond_destroy (T.Common.LL.CV'Access);
813       pragma Assert (Result = 0);
814
815       if T.Known_Tasks_Index /= -1 then
816          Known_Tasks (T.Known_Tasks_Index) := null;
817       end if;
818
819       Free (Tmp);
820    end Finalize_TCB;
821
822    ---------------
823    -- Exit_Task --
824    ---------------
825
826    procedure Exit_Task is
827    begin
828       pthread_exit (System.Null_Address);
829    end Exit_Task;
830
831    ----------------
832    -- Abort_Task --
833    ----------------
834
835    procedure Abort_Task (T : Task_ID) is
836    begin
837       --
838       --  Interrupt Server_Tasks may be waiting on an "event" flag (signal)
839       --
840       if T.Common.State = Interrupt_Server_Blocked_On_Event_Flag then
841          System.Interrupt_Management.Operations.Interrupt_Self_Process
842            (System.Interrupt_Management.Interrupt_ID
843              (PIO.Get_Interrupt_ID (T)));
844       end if;
845    end Abort_Task;
846
847    ----------------
848    -- Check_Exit --
849    ----------------
850
851    --  Dummy versions.  The only currently working versions is for solaris
852    --  (native).
853
854    function Check_Exit (Self_ID : ST.Task_ID) return Boolean is
855    begin
856       return True;
857    end Check_Exit;
858
859    --------------------
860    -- Check_No_Locks --
861    --------------------
862
863    function Check_No_Locks (Self_ID : ST.Task_ID) return Boolean is
864    begin
865       return True;
866    end Check_No_Locks;
867
868    ----------------------
869    -- Environment_Task --
870    ----------------------
871
872    function Environment_Task return Task_ID is
873    begin
874       return Environment_Task_ID;
875    end Environment_Task;
876
877    --------------
878    -- Lock_RTS --
879    --------------
880
881    procedure Lock_RTS is
882    begin
883       Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
884    end Lock_RTS;
885
886    ----------------
887    -- Unlock_RTS --
888    ----------------
889
890    procedure Unlock_RTS is
891    begin
892       Unlock (Single_RTS_Lock'Access, Global_Lock => True);
893    end Unlock_RTS;
894
895    ------------------
896    -- Suspend_Task --
897    ------------------
898
899    function Suspend_Task
900      (T           : ST.Task_ID;
901       Thread_Self : Thread_Id) return Boolean is
902    begin
903       return False;
904    end Suspend_Task;
905
906    -----------------
907    -- Resume_Task --
908    -----------------
909
910    function Resume_Task
911      (T           : ST.Task_ID;
912       Thread_Self : Thread_Id) return Boolean is
913    begin
914       return False;
915    end Resume_Task;
916
917    ----------------
918    -- Initialize --
919    ----------------
920
921    procedure Initialize (Environment_Task : Task_ID) is
922       act       : aliased struct_sigaction;
923       old_act   : aliased struct_sigaction;
924       Tmp_Set   : aliased sigset_t;
925       Result    : Interfaces.C.int;
926
927    begin
928
929       Environment_Task_ID := Environment_Task;
930
931       Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
932       --  Initialize the lock used to synchronize chain of all ATCBs.
933
934       Enter_Task (Environment_Task);
935
936       --  Install the abort-signal handler
937
938       act.sa_flags := 0;
939       act.sa_handler := Abort_Handler'Address;
940
941       Result := sigemptyset (Tmp_Set'Access);
942       pragma Assert (Result = 0);
943       act.sa_mask := Tmp_Set;
944
945       Result :=
946         sigaction (
947           Signal (System.Interrupt_Management.Abort_Task_Interrupt),
948           act'Unchecked_Access,
949           old_act'Unchecked_Access);
950       pragma Assert (Result = 0);
951    end Initialize;
952
953    procedure do_nothing (arg : System.Address);
954
955    procedure do_nothing (arg : System.Address) is
956    begin
957       null;
958    end do_nothing;
959
960 begin
961    declare
962       Result : Interfaces.C.int;
963    begin
964       --  NOTE: Unlike other pthread implementations, we do *not* mask all
965       --  signals here since we handle signals using the process-wide primitive
966       --  signal, rather than using sigthreadmask and sigwait. The reason of
967       --  this difference is that sigwait doesn't work when some critical
968       --  signals (SIGABRT, SIGPIPE) are masked.
969
970       Result := pthread_key_create (ATCB_Key'Access, do_nothing'Access);
971       pragma Assert (Result = 0);
972    end;
973 end System.Task_Primitives.Operations;