OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [s-taprop-posix.adb] - Blame information for rev 473

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                 GNAT 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
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
10
--                                                                          --
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 3,  or (at your option) any later ver- --
14
-- sion.  GNAT 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.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- GNARL was developed by the GNARL team at Florida State University.       --
28
-- Extensive contributions were provided by Ada Core Technologies, Inc.     --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
--  This is a POSIX-like version of this package
33
 
34
--  This package contains all the GNULL primitives that interface directly with
35
--  the underlying OS.
36
 
37
--  Note: this file can only be used for POSIX compliant systems that implement
38
--  SCHED_FIFO and Ceiling Locking correctly.
39
 
40
--  For configurations where SCHED_FIFO and priority ceiling are not a
41
--  requirement, this file can also be used (e.g AiX threads)
42
 
43
pragma Polling (Off);
44
--  Turn off polling, we do not want ATC polling to take place during tasking
45
--  operations. It causes infinite loops and other problems.
46
 
47
with Ada.Unchecked_Conversion;
48
with Ada.Unchecked_Deallocation;
49
 
50
with Interfaces.C;
51
 
52
with System.Tasking.Debug;
53
with System.Interrupt_Management;
54
with System.OS_Primitives;
55
with System.Task_Info;
56
 
57
with System.Soft_Links;
58
--  We use System.Soft_Links instead of System.Tasking.Initialization
59
--  because the later is a higher level package that we shouldn't depend on.
60
--  For example when using the restricted run time, it is replaced by
61
--  System.Tasking.Restricted.Stages.
62
 
63
package body System.Task_Primitives.Operations is
64
 
65
   package SSL renames System.Soft_Links;
66
 
67
   use System.Tasking.Debug;
68
   use System.Tasking;
69
   use Interfaces.C;
70
   use System.OS_Interface;
71
   use System.Parameters;
72
   use System.OS_Primitives;
73
 
74
   ----------------
75
   -- Local Data --
76
   ----------------
77
 
78
   --  The followings are logically constants, but need to be initialized
79
   --  at run time.
80
 
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
85
 
86
   ATCB_Key : aliased pthread_key_t;
87
   --  Key used to find the Ada Task_Id associated with a thread
88
 
89
   Environment_Task_Id : Task_Id;
90
   --  A variable to hold Task_Id for the environment task
91
 
92
   Locking_Policy : Character;
93
   pragma Import (C, Locking_Policy, "__gl_locking_policy");
94
   --  Value of the pragma Locking_Policy:
95
   --    'C' for Ceiling_Locking
96
   --    'I' for Inherit_Locking
97
   --    ' ' for none.
98
 
99
   Unblocked_Signal_Mask : aliased sigset_t;
100
   --  The set of signals that should unblocked in all tasks
101
 
102
   --  The followings are internal configuration constants needed
103
 
104
   Next_Serial_Number : Task_Serial_Number := 100;
105
   --  We start at 100, to reserve some special values for
106
   --  using in error checking.
107
 
108
   Time_Slice_Val : Integer;
109
   pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
110
 
111
   Dispatching_Policy : Character;
112
   pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
113
 
114
   Foreign_Task_Elaborated : aliased Boolean := True;
115
   --  Used to identified fake tasks (i.e., non-Ada Threads)
116
 
117
   Use_Alternate_Stack : constant Boolean := Alternate_Stack_Size /= 0;
118
   --  Whether to use an alternate signal stack for stack overflows
119
 
120
   Abort_Handler_Installed : Boolean := False;
121
   --  True if a handler for the abort signal is installed
122
 
123
   --------------------
124
   -- Local Packages --
125
   --------------------
126
 
127
   package Specific is
128
 
129
      procedure Initialize (Environment_Task : Task_Id);
130
      pragma Inline (Initialize);
131
      --  Initialize various data needed by this package
132
 
133
      function Is_Valid_Task return Boolean;
134
      pragma Inline (Is_Valid_Task);
135
      --  Does executing thread have a TCB?
136
 
137
      procedure Set (Self_Id : Task_Id);
138
      pragma Inline (Set);
139
      --  Set the self id for the current task
140
 
141
      function Self return Task_Id;
142
      pragma Inline (Self);
143
      --  Return a pointer to the Ada Task Control Block of the calling task
144
 
145
   end Specific;
146
 
147
   package body Specific is separate;
148
   --  The body of this package is target specific
149
 
150
   ---------------------------------
151
   -- Support for foreign threads --
152
   ---------------------------------
153
 
154
   function Register_Foreign_Thread (Thread : Thread_Id) return Task_Id;
155
   --  Allocate and Initialize a new ATCB for the current Thread
156
 
157
   function Register_Foreign_Thread
158
     (Thread : Thread_Id) return Task_Id is separate;
159
 
160
   -----------------------
161
   -- Local Subprograms --
162
   -----------------------
163
 
164
   procedure Abort_Handler (Sig : Signal);
165
   --  Signal handler used to implement asynchronous abort.
166
   --  See also comment before body, below.
167
 
168
   function To_Address is
169
     new Ada.Unchecked_Conversion (Task_Id, System.Address);
170
 
171
   -------------------
172
   -- Abort_Handler --
173
   -------------------
174
 
175
   --  Target-dependent binding of inter-thread Abort signal to the raising of
176
   --  the Abort_Signal exception.
177
 
178
   --  The technical issues and alternatives here are essentially the
179
   --  same as for raising exceptions in response to other signals
180
   --  (e.g. Storage_Error). See code and comments in the package body
181
   --  System.Interrupt_Management.
182
 
183
   --  Some implementations may not allow an exception to be propagated out of
184
   --  a handler, and others might leave the signal or interrupt that invoked
185
   --  this handler masked after the exceptional return to the application
186
   --  code.
187
 
188
   --  GNAT exceptions are originally implemented using setjmp()/longjmp(). On
189
   --  most UNIX systems, this will allow transfer out of a signal handler,
190
   --  which is usually the only mechanism available for implementing
191
   --  asynchronous handlers of this kind. However, some systems do not
192
   --  restore the signal mask on longjmp(), leaving the abort signal masked.
193
 
194
   procedure Abort_Handler (Sig : Signal) is
195
      pragma Unreferenced (Sig);
196
 
197
      T       : constant Task_Id := Self;
198
      Old_Set : aliased sigset_t;
199
 
200
      Result : Interfaces.C.int;
201
      pragma Warnings (Off, Result);
202
 
203
   begin
204
      --  It's not safe to raise an exception when using GCC ZCX mechanism.
205
      --  Note that we still need to install a signal handler, since in some
206
      --  cases (e.g. shutdown of the Server_Task in System.Interrupts) we
207
      --  need to send the Abort signal to a task.
208
 
209
      if ZCX_By_Default and then GCC_ZCX_Support then
210
         return;
211
      end if;
212
 
213
      if T.Deferral_Level = 0
214
        and then T.Pending_ATC_Level < T.ATC_Nesting_Level and then
215
        not T.Aborting
216
      then
217
         T.Aborting := True;
218
 
219
         --  Make sure signals used for RTS internal purpose are unmasked
220
 
221
         Result := pthread_sigmask (SIG_UNBLOCK,
222
           Unblocked_Signal_Mask'Access, Old_Set'Access);
223
         pragma Assert (Result = 0);
224
 
225
         raise Standard'Abort_Signal;
226
      end if;
227
   end Abort_Handler;
228
 
229
   -----------------
230
   -- Stack_Guard --
231
   -----------------
232
 
233
   procedure Stack_Guard (T : ST.Task_Id; On : Boolean) is
234
      Stack_Base : constant Address := Get_Stack_Base (T.Common.LL.Thread);
235
      Guard_Page_Address : Address;
236
 
237
      Res : Interfaces.C.int;
238
 
239
   begin
240
      if Stack_Base_Available then
241
 
242
         --  Compute the guard page address
243
 
244
         Guard_Page_Address :=
245
           Stack_Base - (Stack_Base mod Get_Page_Size) + Get_Page_Size;
246
 
247
         Res :=
248
           mprotect (Guard_Page_Address, Get_Page_Size,
249
                     prot => (if On then PROT_ON else PROT_OFF));
250
         pragma Assert (Res = 0);
251
      end if;
252
   end Stack_Guard;
253
 
254
   --------------------
255
   -- Get_Thread_Id  --
256
   --------------------
257
 
258
   function Get_Thread_Id (T : ST.Task_Id) return OSI.Thread_Id is
259
   begin
260
      return T.Common.LL.Thread;
261
   end Get_Thread_Id;
262
 
263
   ----------
264
   -- Self --
265
   ----------
266
 
267
   function Self return Task_Id renames Specific.Self;
268
 
269
   ---------------------
270
   -- Initialize_Lock --
271
   ---------------------
272
 
273
   --  Note: mutexes and cond_variables needed per-task basis are
274
   --        initialized in Initialize_TCB and the Storage_Error is
275
   --        handled. Other mutexes (such as RTS_Lock, Memory_Lock...)
276
   --        used in RTS is initialized before any status change of RTS.
277
   --        Therefore raising Storage_Error in the following routines
278
   --        should be able to be handled safely.
279
 
280
   procedure Initialize_Lock
281
     (Prio : System.Any_Priority;
282
      L    : not null access Lock)
283
   is
284
      Attributes : aliased pthread_mutexattr_t;
285
      Result : Interfaces.C.int;
286
 
287
   begin
288
      Result := pthread_mutexattr_init (Attributes'Access);
289
      pragma Assert (Result = 0 or else Result = ENOMEM);
290
 
291
      if Result = ENOMEM then
292
         raise Storage_Error;
293
      end if;
294
 
295
      if Locking_Policy = 'C' then
296
         Result := pthread_mutexattr_setprotocol
297
           (Attributes'Access, PTHREAD_PRIO_PROTECT);
298
         pragma Assert (Result = 0);
299
 
300
         Result := pthread_mutexattr_setprioceiling
301
            (Attributes'Access, Interfaces.C.int (Prio));
302
         pragma Assert (Result = 0);
303
 
304
      elsif Locking_Policy = 'I' then
305
         Result := pthread_mutexattr_setprotocol
306
           (Attributes'Access, PTHREAD_PRIO_INHERIT);
307
         pragma Assert (Result = 0);
308
      end if;
309
 
310
      Result := pthread_mutex_init (L, Attributes'Access);
311
      pragma Assert (Result = 0 or else Result = ENOMEM);
312
 
313
      if Result = ENOMEM then
314
         Result := pthread_mutexattr_destroy (Attributes'Access);
315
         raise Storage_Error;
316
      end if;
317
 
318
      Result := pthread_mutexattr_destroy (Attributes'Access);
319
      pragma Assert (Result = 0);
320
   end Initialize_Lock;
321
 
322
   procedure Initialize_Lock
323
     (L : not null access RTS_Lock; Level : Lock_Level)
324
   is
325
      pragma Unreferenced (Level);
326
 
327
      Attributes : aliased pthread_mutexattr_t;
328
      Result     : Interfaces.C.int;
329
 
330
   begin
331
      Result := pthread_mutexattr_init (Attributes'Access);
332
      pragma Assert (Result = 0 or else Result = ENOMEM);
333
 
334
      if Result = ENOMEM then
335
         raise Storage_Error;
336
      end if;
337
 
338
      if Locking_Policy = 'C' then
339
         Result := pthread_mutexattr_setprotocol
340
           (Attributes'Access, PTHREAD_PRIO_PROTECT);
341
         pragma Assert (Result = 0);
342
 
343
         Result := pthread_mutexattr_setprioceiling
344
            (Attributes'Access, Interfaces.C.int (System.Any_Priority'Last));
345
         pragma Assert (Result = 0);
346
 
347
      elsif Locking_Policy = 'I' then
348
         Result := pthread_mutexattr_setprotocol
349
           (Attributes'Access, PTHREAD_PRIO_INHERIT);
350
         pragma Assert (Result = 0);
351
      end if;
352
 
353
      Result := pthread_mutex_init (L, Attributes'Access);
354
      pragma Assert (Result = 0 or else Result = ENOMEM);
355
 
356
      if Result = ENOMEM then
357
         Result := pthread_mutexattr_destroy (Attributes'Access);
358
         raise Storage_Error;
359
      end if;
360
 
361
      Result := pthread_mutexattr_destroy (Attributes'Access);
362
      pragma Assert (Result = 0);
363
   end Initialize_Lock;
364
 
365
   -------------------
366
   -- Finalize_Lock --
367
   -------------------
368
 
369
   procedure Finalize_Lock (L : not null access Lock) is
370
      Result : Interfaces.C.int;
371
   begin
372
      Result := pthread_mutex_destroy (L);
373
      pragma Assert (Result = 0);
374
   end Finalize_Lock;
375
 
376
   procedure Finalize_Lock (L : not null access RTS_Lock) is
377
      Result : Interfaces.C.int;
378
   begin
379
      Result := pthread_mutex_destroy (L);
380
      pragma Assert (Result = 0);
381
   end Finalize_Lock;
382
 
383
   ----------------
384
   -- Write_Lock --
385
   ----------------
386
 
387
   procedure Write_Lock
388
     (L : not null access Lock; Ceiling_Violation : out Boolean)
389
   is
390
      Result : Interfaces.C.int;
391
 
392
   begin
393
      Result := pthread_mutex_lock (L);
394
 
395
      --  Assume that the cause of EINVAL is a priority ceiling violation
396
 
397
      Ceiling_Violation := (Result = EINVAL);
398
      pragma Assert (Result = 0 or else Result = EINVAL);
399
   end Write_Lock;
400
 
401
   procedure Write_Lock
402
     (L           : not null access RTS_Lock;
403
      Global_Lock : Boolean := False)
404
   is
405
      Result : Interfaces.C.int;
406
   begin
407
      if not Single_Lock or else Global_Lock then
408
         Result := pthread_mutex_lock (L);
409
         pragma Assert (Result = 0);
410
      end if;
411
   end Write_Lock;
412
 
413
   procedure Write_Lock (T : Task_Id) is
414
      Result : Interfaces.C.int;
415
   begin
416
      if not Single_Lock then
417
         Result := pthread_mutex_lock (T.Common.LL.L'Access);
418
         pragma Assert (Result = 0);
419
      end if;
420
   end Write_Lock;
421
 
422
   ---------------
423
   -- Read_Lock --
424
   ---------------
425
 
426
   procedure Read_Lock
427
     (L : not null access Lock; Ceiling_Violation : out Boolean) is
428
   begin
429
      Write_Lock (L, Ceiling_Violation);
430
   end Read_Lock;
431
 
432
   ------------
433
   -- Unlock --
434
   ------------
435
 
436
   procedure Unlock (L : not null access Lock) is
437
      Result : Interfaces.C.int;
438
   begin
439
      Result := pthread_mutex_unlock (L);
440
      pragma Assert (Result = 0);
441
   end Unlock;
442
 
443
   procedure Unlock
444
     (L : not null access RTS_Lock; Global_Lock : Boolean := False)
445
   is
446
      Result : Interfaces.C.int;
447
   begin
448
      if not Single_Lock or else Global_Lock then
449
         Result := pthread_mutex_unlock (L);
450
         pragma Assert (Result = 0);
451
      end if;
452
   end Unlock;
453
 
454
   procedure Unlock (T : Task_Id) is
455
      Result : Interfaces.C.int;
456
   begin
457
      if not Single_Lock then
458
         Result := pthread_mutex_unlock (T.Common.LL.L'Access);
459
         pragma Assert (Result = 0);
460
      end if;
461
   end Unlock;
462
 
463
   -----------------
464
   -- Set_Ceiling --
465
   -----------------
466
 
467
   --  Dynamic priority ceilings are not supported by the underlying system
468
 
469
   procedure Set_Ceiling
470
     (L    : not null access Lock;
471
      Prio : System.Any_Priority)
472
   is
473
      pragma Unreferenced (L, Prio);
474
   begin
475
      null;
476
   end Set_Ceiling;
477
 
478
   -----------
479
   -- Sleep --
480
   -----------
481
 
482
   procedure Sleep
483
     (Self_ID : Task_Id;
484
      Reason  : System.Tasking.Task_States)
485
   is
486
      pragma Unreferenced (Reason);
487
 
488
      Result : Interfaces.C.int;
489
 
490
   begin
491
      Result :=
492
        pthread_cond_wait
493
          (cond  => Self_ID.Common.LL.CV'Access,
494
           mutex => (if Single_Lock
495
                     then Single_RTS_Lock'Access
496
                     else Self_ID.Common.LL.L'Access));
497
 
498
      --  EINTR is not considered a failure
499
 
500
      pragma Assert (Result = 0 or else Result = EINTR);
501
   end Sleep;
502
 
503
   -----------------
504
   -- Timed_Sleep --
505
   -----------------
506
 
507
   --  This is for use within the run-time system, so abort is
508
   --  assumed to be already deferred, and the caller should be
509
   --  holding its own ATCB lock.
510
 
511
   procedure Timed_Sleep
512
     (Self_ID  : Task_Id;
513
      Time     : Duration;
514
      Mode     : ST.Delay_Modes;
515
      Reason   : Task_States;
516
      Timedout : out Boolean;
517
      Yielded  : out Boolean)
518
   is
519
      pragma Unreferenced (Reason);
520
 
521
      Base_Time  : constant Duration := Monotonic_Clock;
522
      Check_Time : Duration := Base_Time;
523
      Rel_Time   : Duration;
524
      Abs_Time   : Duration;
525
      Request    : aliased timespec;
526
      Result     : Interfaces.C.int;
527
 
528
   begin
529
      Timedout := True;
530
      Yielded := False;
531
 
532
      if Mode = Relative then
533
         Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
534
 
535
         if Relative_Timed_Wait then
536
            Rel_Time := Duration'Min (Max_Sensible_Delay, Time);
537
         end if;
538
 
539
      else
540
         Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
541
 
542
         if Relative_Timed_Wait then
543
            Rel_Time := Duration'Min (Max_Sensible_Delay, Time - Check_Time);
544
         end if;
545
      end if;
546
 
547
      if Abs_Time > Check_Time then
548
         Request :=
549
           To_Timespec (if Relative_Timed_Wait then Rel_Time else Abs_Time);
550
 
551
         loop
552
            exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
553
 
554
            Result :=
555
              pthread_cond_timedwait
556
                (cond    => Self_ID.Common.LL.CV'Access,
557
                 mutex   => (if Single_Lock
558
                             then Single_RTS_Lock'Access
559
                             else Self_ID.Common.LL.L'Access),
560
                 abstime => Request'Access);
561
 
562
            Check_Time := Monotonic_Clock;
563
            exit when Abs_Time <= Check_Time or else Check_Time < Base_Time;
564
 
565
            if Result = 0 or Result = EINTR then
566
 
567
               --  Somebody may have called Wakeup for us
568
 
569
               Timedout := False;
570
               exit;
571
            end if;
572
 
573
            pragma Assert (Result = ETIMEDOUT);
574
         end loop;
575
      end if;
576
   end Timed_Sleep;
577
 
578
   -----------------
579
   -- Timed_Delay --
580
   -----------------
581
 
582
   --  This is for use in implementing delay statements, so we assume the
583
   --  caller is abort-deferred but is holding no locks.
584
 
585
   procedure Timed_Delay
586
     (Self_ID : Task_Id;
587
      Time    : Duration;
588
      Mode    : ST.Delay_Modes)
589
   is
590
      Base_Time  : constant Duration := Monotonic_Clock;
591
      Check_Time : Duration := Base_Time;
592
      Abs_Time   : Duration;
593
      Rel_Time   : Duration;
594
      Request    : aliased timespec;
595
 
596
      Result : Interfaces.C.int;
597
      pragma Warnings (Off, Result);
598
 
599
   begin
600
      if Single_Lock then
601
         Lock_RTS;
602
      end if;
603
 
604
      Write_Lock (Self_ID);
605
 
606
      if Mode = Relative then
607
         Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
608
 
609
         if Relative_Timed_Wait then
610
            Rel_Time := Duration'Min (Max_Sensible_Delay, Time);
611
         end if;
612
 
613
      else
614
         Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
615
 
616
         if Relative_Timed_Wait then
617
            Rel_Time := Duration'Min (Max_Sensible_Delay, Time - Check_Time);
618
         end if;
619
      end if;
620
 
621
      if Abs_Time > Check_Time then
622
         Request :=
623
           To_Timespec (if Relative_Timed_Wait then Rel_Time else Abs_Time);
624
         Self_ID.Common.State := Delay_Sleep;
625
 
626
         loop
627
            exit when Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
628
 
629
            Result :=
630
              pthread_cond_timedwait
631
                (cond    => Self_ID.Common.LL.CV'Access,
632
                 mutex   => (if Single_Lock
633
                             then Single_RTS_Lock'Access
634
                             else Self_ID.Common.LL.L'Access),
635
                 abstime => Request'Access);
636
 
637
            Check_Time := Monotonic_Clock;
638
            exit when Abs_Time <= Check_Time or else Check_Time < Base_Time;
639
 
640
            pragma Assert (Result = 0
641
                             or else Result = ETIMEDOUT
642
                             or else Result = EINTR);
643
         end loop;
644
 
645
         Self_ID.Common.State := Runnable;
646
      end if;
647
 
648
      Unlock (Self_ID);
649
 
650
      if Single_Lock then
651
         Unlock_RTS;
652
      end if;
653
 
654
      Result := sched_yield;
655
   end Timed_Delay;
656
 
657
   ---------------------
658
   -- Monotonic_Clock --
659
   ---------------------
660
 
661
   function Monotonic_Clock return Duration is
662
      TS     : aliased timespec;
663
      Result : Interfaces.C.int;
664
   begin
665
      Result := clock_gettime
666
        (clock_id => CLOCK_REALTIME, tp => TS'Unchecked_Access);
667
      pragma Assert (Result = 0);
668
      return To_Duration (TS);
669
   end Monotonic_Clock;
670
 
671
   -------------------
672
   -- RT_Resolution --
673
   -------------------
674
 
675
   function RT_Resolution return Duration is
676
   begin
677
      return 10#1.0#E-6;
678
   end RT_Resolution;
679
 
680
   ------------
681
   -- Wakeup --
682
   ------------
683
 
684
   procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
685
      pragma Unreferenced (Reason);
686
      Result : Interfaces.C.int;
687
   begin
688
      Result := pthread_cond_signal (T.Common.LL.CV'Access);
689
      pragma Assert (Result = 0);
690
   end Wakeup;
691
 
692
   -----------
693
   -- Yield --
694
   -----------
695
 
696
   procedure Yield (Do_Yield : Boolean := True) is
697
      Result : Interfaces.C.int;
698
      pragma Unreferenced (Result);
699
   begin
700
      if Do_Yield then
701
         Result := sched_yield;
702
      end if;
703
   end Yield;
704
 
705
   ------------------
706
   -- Set_Priority --
707
   ------------------
708
 
709
   procedure Set_Priority
710
     (T                   : Task_Id;
711
      Prio                : System.Any_Priority;
712
      Loss_Of_Inheritance : Boolean := False)
713
   is
714
      pragma Unreferenced (Loss_Of_Inheritance);
715
 
716
      Result : Interfaces.C.int;
717
      Param  : aliased struct_sched_param;
718
 
719
      function Get_Policy (Prio : System.Any_Priority) return Character;
720
      pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
721
      --  Get priority specific dispatching policy
722
 
723
      Priority_Specific_Policy : constant Character := Get_Policy (Prio);
724
      --  Upper case first character of the policy name corresponding to the
725
      --  task as set by a Priority_Specific_Dispatching pragma.
726
 
727
   begin
728
      T.Common.Current_Priority := Prio;
729
      Param.sched_priority := To_Target_Priority (Prio);
730
 
731
      if Time_Slice_Supported
732
        and then (Dispatching_Policy = 'R'
733
                  or else Priority_Specific_Policy = 'R'
734
                  or else Time_Slice_Val > 0)
735
      then
736
         Result := pthread_setschedparam
737
           (T.Common.LL.Thread, SCHED_RR, Param'Access);
738
 
739
      elsif Dispatching_Policy = 'F'
740
        or else Priority_Specific_Policy = 'F'
741
        or else Time_Slice_Val = 0
742
      then
743
         Result := pthread_setschedparam
744
           (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
745
 
746
      else
747
         Result := pthread_setschedparam
748
           (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
749
      end if;
750
 
751
      pragma Assert (Result = 0);
752
   end Set_Priority;
753
 
754
   ------------------
755
   -- Get_Priority --
756
   ------------------
757
 
758
   function Get_Priority (T : Task_Id) return System.Any_Priority is
759
   begin
760
      return T.Common.Current_Priority;
761
   end Get_Priority;
762
 
763
   ----------------
764
   -- Enter_Task --
765
   ----------------
766
 
767
   procedure Enter_Task (Self_ID : Task_Id) is
768
   begin
769
      Self_ID.Common.LL.Thread := pthread_self;
770
      Self_ID.Common.LL.LWP := lwp_self;
771
 
772
      Specific.Set (Self_ID);
773
 
774
      if Use_Alternate_Stack then
775
         declare
776
            Stack  : aliased stack_t;
777
            Result : Interfaces.C.int;
778
         begin
779
            Stack.ss_sp    := Self_ID.Common.Task_Alternate_Stack;
780
            Stack.ss_size  := Alternate_Stack_Size;
781
            Stack.ss_flags := 0;
782
            Result := sigaltstack (Stack'Access, null);
783
            pragma Assert (Result = 0);
784
         end;
785
      end if;
786
   end Enter_Task;
787
 
788
   --------------
789
   -- New_ATCB --
790
   --------------
791
 
792
   function New_ATCB (Entry_Num : Task_Entry_Index) return Task_Id is
793
   begin
794
      return new Ada_Task_Control_Block (Entry_Num);
795
   end New_ATCB;
796
 
797
   -------------------
798
   -- Is_Valid_Task --
799
   -------------------
800
 
801
   function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
802
 
803
   -----------------------------
804
   -- Register_Foreign_Thread --
805
   -----------------------------
806
 
807
   function Register_Foreign_Thread return Task_Id is
808
   begin
809
      if Is_Valid_Task then
810
         return Self;
811
      else
812
         return Register_Foreign_Thread (pthread_self);
813
      end if;
814
   end Register_Foreign_Thread;
815
 
816
   --------------------
817
   -- Initialize_TCB --
818
   --------------------
819
 
820
   procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
821
      Mutex_Attr : aliased pthread_mutexattr_t;
822
      Result     : Interfaces.C.int;
823
      Cond_Attr  : aliased pthread_condattr_t;
824
 
825
   begin
826
      --  Give the task a unique serial number
827
 
828
      Self_ID.Serial_Number := Next_Serial_Number;
829
      Next_Serial_Number := Next_Serial_Number + 1;
830
      pragma Assert (Next_Serial_Number /= 0);
831
 
832
      if not Single_Lock then
833
         Result := pthread_mutexattr_init (Mutex_Attr'Access);
834
         pragma Assert (Result = 0 or else Result = ENOMEM);
835
 
836
         if Result = 0 then
837
            if Locking_Policy = 'C' then
838
               Result :=
839
                 pthread_mutexattr_setprotocol
840
                   (Mutex_Attr'Access,
841
                    PTHREAD_PRIO_PROTECT);
842
               pragma Assert (Result = 0);
843
 
844
               Result :=
845
                 pthread_mutexattr_setprioceiling
846
                   (Mutex_Attr'Access,
847
                    Interfaces.C.int (System.Any_Priority'Last));
848
               pragma Assert (Result = 0);
849
 
850
            elsif Locking_Policy = 'I' then
851
               Result :=
852
                 pthread_mutexattr_setprotocol
853
                   (Mutex_Attr'Access,
854
                    PTHREAD_PRIO_INHERIT);
855
               pragma Assert (Result = 0);
856
            end if;
857
 
858
            Result :=
859
              pthread_mutex_init
860
                (Self_ID.Common.LL.L'Access,
861
                 Mutex_Attr'Access);
862
            pragma Assert (Result = 0 or else Result = ENOMEM);
863
         end if;
864
 
865
         if Result /= 0 then
866
            Succeeded := False;
867
            return;
868
         end if;
869
 
870
         Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
871
         pragma Assert (Result = 0);
872
      end if;
873
 
874
      Result := pthread_condattr_init (Cond_Attr'Access);
875
      pragma Assert (Result = 0 or else Result = ENOMEM);
876
 
877
      if Result = 0 then
878
         Result :=
879
           pthread_cond_init
880
             (Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
881
         pragma Assert (Result = 0 or else Result = ENOMEM);
882
      end if;
883
 
884
      if Result = 0 then
885
         Succeeded := True;
886
      else
887
         if not Single_Lock then
888
            Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
889
            pragma Assert (Result = 0);
890
         end if;
891
 
892
         Succeeded := False;
893
      end if;
894
 
895
      Result := pthread_condattr_destroy (Cond_Attr'Access);
896
      pragma Assert (Result = 0);
897
   end Initialize_TCB;
898
 
899
   -----------------
900
   -- Create_Task --
901
   -----------------
902
 
903
   procedure Create_Task
904
     (T          : Task_Id;
905
      Wrapper    : System.Address;
906
      Stack_Size : System.Parameters.Size_Type;
907
      Priority   : System.Any_Priority;
908
      Succeeded  : out Boolean)
909
   is
910
      Attributes          : aliased pthread_attr_t;
911
      Adjusted_Stack_Size : Interfaces.C.size_t;
912
      Page_Size           : constant Interfaces.C.size_t := Get_Page_Size;
913
      Result              : Interfaces.C.int;
914
 
915
      function Thread_Body_Access is new
916
        Ada.Unchecked_Conversion (System.Address, Thread_Body);
917
 
918
      use System.Task_Info;
919
 
920
   begin
921
      Adjusted_Stack_Size :=
922
         Interfaces.C.size_t (Stack_Size + Alternate_Stack_Size);
923
 
924
      if Stack_Base_Available then
925
 
926
         --  If Stack Checking is supported then allocate 2 additional pages:
927
 
928
         --  In the worst case, stack is allocated at something like
929
         --  N * Get_Page_Size - epsilon, we need to add the size for 2 pages
930
         --  to be sure the effective stack size is greater than what
931
         --  has been asked.
932
 
933
         Adjusted_Stack_Size := Adjusted_Stack_Size + 2 * Page_Size;
934
      end if;
935
 
936
      --  Round stack size as this is required by some OSes (Darwin)
937
 
938
      Adjusted_Stack_Size := Adjusted_Stack_Size + Page_Size - 1;
939
      Adjusted_Stack_Size :=
940
        Adjusted_Stack_Size - Adjusted_Stack_Size mod Page_Size;
941
 
942
      Result := pthread_attr_init (Attributes'Access);
943
      pragma Assert (Result = 0 or else Result = ENOMEM);
944
 
945
      if Result /= 0 then
946
         Succeeded := False;
947
         return;
948
      end if;
949
 
950
      Result :=
951
        pthread_attr_setdetachstate
952
          (Attributes'Access, PTHREAD_CREATE_DETACHED);
953
      pragma Assert (Result = 0);
954
 
955
      Result :=
956
        pthread_attr_setstacksize
957
          (Attributes'Access, Adjusted_Stack_Size);
958
      pragma Assert (Result = 0);
959
 
960
      if T.Common.Task_Info /= Default_Scope then
961
         case T.Common.Task_Info is
962
            when System.Task_Info.Process_Scope =>
963
               Result :=
964
                 pthread_attr_setscope
965
                   (Attributes'Access, PTHREAD_SCOPE_PROCESS);
966
 
967
            when System.Task_Info.System_Scope =>
968
               Result :=
969
                 pthread_attr_setscope
970
                   (Attributes'Access, PTHREAD_SCOPE_SYSTEM);
971
 
972
            when System.Task_Info.Default_Scope =>
973
               Result := 0;
974
         end case;
975
 
976
         pragma Assert (Result = 0);
977
      end if;
978
 
979
      --  Since the initial signal mask of a thread is inherited from the
980
      --  creator, and the Environment task has all its signals masked, we
981
      --  do not need to manipulate caller's signal mask at this point.
982
      --  All tasks in RTS will have All_Tasks_Mask initially.
983
 
984
      Result := pthread_create
985
        (T.Common.LL.Thread'Access,
986
         Attributes'Access,
987
         Thread_Body_Access (Wrapper),
988
         To_Address (T));
989
      pragma Assert (Result = 0 or else Result = EAGAIN);
990
 
991
      Succeeded := Result = 0;
992
 
993
      Result := pthread_attr_destroy (Attributes'Access);
994
      pragma Assert (Result = 0);
995
 
996
      if Succeeded then
997
         Set_Priority (T, Priority);
998
      end if;
999
   end Create_Task;
1000
 
1001
   ------------------
1002
   -- Finalize_TCB --
1003
   ------------------
1004
 
1005
   procedure Finalize_TCB (T : Task_Id) is
1006
      Result  : Interfaces.C.int;
1007
      Tmp     : Task_Id := T;
1008
      Is_Self : constant Boolean := T = Self;
1009
 
1010
      procedure Free is new
1011
        Ada.Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
1012
 
1013
   begin
1014
      if not Single_Lock then
1015
         Result := pthread_mutex_destroy (T.Common.LL.L'Access);
1016
         pragma Assert (Result = 0);
1017
      end if;
1018
 
1019
      Result := pthread_cond_destroy (T.Common.LL.CV'Access);
1020
      pragma Assert (Result = 0);
1021
 
1022
      if T.Known_Tasks_Index /= -1 then
1023
         Known_Tasks (T.Known_Tasks_Index) := null;
1024
      end if;
1025
 
1026
      Free (Tmp);
1027
 
1028
      if Is_Self then
1029
         Specific.Set (null);
1030
      end if;
1031
   end Finalize_TCB;
1032
 
1033
   ---------------
1034
   -- Exit_Task --
1035
   ---------------
1036
 
1037
   procedure Exit_Task is
1038
   begin
1039
      --  Mark this task as unknown, so that if Self is called, it won't
1040
      --  return a dangling pointer.
1041
 
1042
      Specific.Set (null);
1043
   end Exit_Task;
1044
 
1045
   ----------------
1046
   -- Abort_Task --
1047
   ----------------
1048
 
1049
   procedure Abort_Task (T : Task_Id) is
1050
      Result : Interfaces.C.int;
1051
   begin
1052
      if Abort_Handler_Installed then
1053
         Result :=
1054
           pthread_kill
1055
             (T.Common.LL.Thread,
1056
              Signal (System.Interrupt_Management.Abort_Task_Interrupt));
1057
         pragma Assert (Result = 0);
1058
      end if;
1059
   end Abort_Task;
1060
 
1061
   ----------------
1062
   -- Initialize --
1063
   ----------------
1064
 
1065
   procedure Initialize (S : in out Suspension_Object) is
1066
      Mutex_Attr : aliased pthread_mutexattr_t;
1067
      Cond_Attr  : aliased pthread_condattr_t;
1068
      Result     : Interfaces.C.int;
1069
 
1070
   begin
1071
      --  Initialize internal state (always to False (RM D.10 (6)))
1072
 
1073
      S.State := False;
1074
      S.Waiting := False;
1075
 
1076
      --  Initialize internal mutex
1077
 
1078
      Result := pthread_mutexattr_init (Mutex_Attr'Access);
1079
      pragma Assert (Result = 0 or else Result = ENOMEM);
1080
 
1081
      if Result = ENOMEM then
1082
         raise Storage_Error;
1083
      end if;
1084
 
1085
      Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
1086
      pragma Assert (Result = 0 or else Result = ENOMEM);
1087
 
1088
      if Result = ENOMEM then
1089
         Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
1090
         pragma Assert (Result = 0);
1091
 
1092
         raise Storage_Error;
1093
      end if;
1094
 
1095
      Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
1096
      pragma Assert (Result = 0);
1097
 
1098
      --  Initialize internal condition variable
1099
 
1100
      Result := pthread_condattr_init (Cond_Attr'Access);
1101
      pragma Assert (Result = 0 or else Result = ENOMEM);
1102
 
1103
      if Result /= 0 then
1104
         Result := pthread_mutex_destroy (S.L'Access);
1105
         pragma Assert (Result = 0);
1106
 
1107
         if Result = ENOMEM then
1108
            raise Storage_Error;
1109
         end if;
1110
      end if;
1111
 
1112
      Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
1113
      pragma Assert (Result = 0 or else Result = ENOMEM);
1114
 
1115
      if Result /= 0 then
1116
         Result := pthread_mutex_destroy (S.L'Access);
1117
         pragma Assert (Result = 0);
1118
 
1119
         if Result = ENOMEM then
1120
            Result := pthread_condattr_destroy (Cond_Attr'Access);
1121
            pragma Assert (Result = 0);
1122
            raise Storage_Error;
1123
         end if;
1124
      end if;
1125
 
1126
      Result := pthread_condattr_destroy (Cond_Attr'Access);
1127
      pragma Assert (Result = 0);
1128
   end Initialize;
1129
 
1130
   --------------
1131
   -- Finalize --
1132
   --------------
1133
 
1134
   procedure Finalize (S : in out Suspension_Object) is
1135
      Result : Interfaces.C.int;
1136
 
1137
   begin
1138
      --  Destroy internal mutex
1139
 
1140
      Result := pthread_mutex_destroy (S.L'Access);
1141
      pragma Assert (Result = 0);
1142
 
1143
      --  Destroy internal condition variable
1144
 
1145
      Result := pthread_cond_destroy (S.CV'Access);
1146
      pragma Assert (Result = 0);
1147
   end Finalize;
1148
 
1149
   -------------------
1150
   -- Current_State --
1151
   -------------------
1152
 
1153
   function Current_State (S : Suspension_Object) return Boolean is
1154
   begin
1155
      --  We do not want to use lock on this read operation. State is marked
1156
      --  as Atomic so that we ensure that the value retrieved is correct.
1157
 
1158
      return S.State;
1159
   end Current_State;
1160
 
1161
   ---------------
1162
   -- Set_False --
1163
   ---------------
1164
 
1165
   procedure Set_False (S : in out Suspension_Object) is
1166
      Result : Interfaces.C.int;
1167
 
1168
   begin
1169
      SSL.Abort_Defer.all;
1170
 
1171
      Result := pthread_mutex_lock (S.L'Access);
1172
      pragma Assert (Result = 0);
1173
 
1174
      S.State := False;
1175
 
1176
      Result := pthread_mutex_unlock (S.L'Access);
1177
      pragma Assert (Result = 0);
1178
 
1179
      SSL.Abort_Undefer.all;
1180
   end Set_False;
1181
 
1182
   --------------
1183
   -- Set_True --
1184
   --------------
1185
 
1186
   procedure Set_True (S : in out Suspension_Object) is
1187
      Result : Interfaces.C.int;
1188
 
1189
   begin
1190
      SSL.Abort_Defer.all;
1191
 
1192
      Result := pthread_mutex_lock (S.L'Access);
1193
      pragma Assert (Result = 0);
1194
 
1195
      --  If there is already a task waiting on this suspension object then
1196
      --  we resume it, leaving the state of the suspension object to False,
1197
      --  as it is specified in (RM D.10(9)). Otherwise, it just leaves
1198
      --  the state to True.
1199
 
1200
      if S.Waiting then
1201
         S.Waiting := False;
1202
         S.State := False;
1203
 
1204
         Result := pthread_cond_signal (S.CV'Access);
1205
         pragma Assert (Result = 0);
1206
 
1207
      else
1208
         S.State := True;
1209
      end if;
1210
 
1211
      Result := pthread_mutex_unlock (S.L'Access);
1212
      pragma Assert (Result = 0);
1213
 
1214
      SSL.Abort_Undefer.all;
1215
   end Set_True;
1216
 
1217
   ------------------------
1218
   -- Suspend_Until_True --
1219
   ------------------------
1220
 
1221
   procedure Suspend_Until_True (S : in out Suspension_Object) is
1222
      Result : Interfaces.C.int;
1223
 
1224
   begin
1225
      SSL.Abort_Defer.all;
1226
 
1227
      Result := pthread_mutex_lock (S.L'Access);
1228
      pragma Assert (Result = 0);
1229
 
1230
      if S.Waiting then
1231
 
1232
         --  Program_Error must be raised upon calling Suspend_Until_True
1233
         --  if another task is already waiting on that suspension object
1234
         --  (RM D.10(10)).
1235
 
1236
         Result := pthread_mutex_unlock (S.L'Access);
1237
         pragma Assert (Result = 0);
1238
 
1239
         SSL.Abort_Undefer.all;
1240
 
1241
         raise Program_Error;
1242
 
1243
      else
1244
         --  Suspend the task if the state is False. Otherwise, the task
1245
         --  continues its execution, and the state of the suspension object
1246
         --  is set to False (ARM D.10 par. 9).
1247
 
1248
         if S.State then
1249
            S.State := False;
1250
         else
1251
            S.Waiting := True;
1252
 
1253
            loop
1254
               --  Loop in case pthread_cond_wait returns earlier than expected
1255
               --  (e.g. in case of EINTR caused by a signal).
1256
 
1257
               Result := pthread_cond_wait (S.CV'Access, S.L'Access);
1258
               pragma Assert (Result = 0 or else Result = EINTR);
1259
 
1260
               exit when not S.Waiting;
1261
            end loop;
1262
         end if;
1263
 
1264
         Result := pthread_mutex_unlock (S.L'Access);
1265
         pragma Assert (Result = 0);
1266
 
1267
         SSL.Abort_Undefer.all;
1268
      end if;
1269
   end Suspend_Until_True;
1270
 
1271
   ----------------
1272
   -- Check_Exit --
1273
   ----------------
1274
 
1275
   --  Dummy version
1276
 
1277
   function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
1278
      pragma Unreferenced (Self_ID);
1279
   begin
1280
      return True;
1281
   end Check_Exit;
1282
 
1283
   --------------------
1284
   -- Check_No_Locks --
1285
   --------------------
1286
 
1287
   function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
1288
      pragma Unreferenced (Self_ID);
1289
   begin
1290
      return True;
1291
   end Check_No_Locks;
1292
 
1293
   ----------------------
1294
   -- Environment_Task --
1295
   ----------------------
1296
 
1297
   function Environment_Task return Task_Id is
1298
   begin
1299
      return Environment_Task_Id;
1300
   end Environment_Task;
1301
 
1302
   --------------
1303
   -- Lock_RTS --
1304
   --------------
1305
 
1306
   procedure Lock_RTS is
1307
   begin
1308
      Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
1309
   end Lock_RTS;
1310
 
1311
   ----------------
1312
   -- Unlock_RTS --
1313
   ----------------
1314
 
1315
   procedure Unlock_RTS is
1316
   begin
1317
      Unlock (Single_RTS_Lock'Access, Global_Lock => True);
1318
   end Unlock_RTS;
1319
 
1320
   ------------------
1321
   -- Suspend_Task --
1322
   ------------------
1323
 
1324
   function Suspend_Task
1325
     (T           : ST.Task_Id;
1326
      Thread_Self : Thread_Id) return Boolean
1327
   is
1328
      pragma Unreferenced (T, Thread_Self);
1329
   begin
1330
      return False;
1331
   end Suspend_Task;
1332
 
1333
   -----------------
1334
   -- Resume_Task --
1335
   -----------------
1336
 
1337
   function Resume_Task
1338
     (T           : ST.Task_Id;
1339
      Thread_Self : Thread_Id) return Boolean
1340
   is
1341
      pragma Unreferenced (T, Thread_Self);
1342
   begin
1343
      return False;
1344
   end Resume_Task;
1345
 
1346
   --------------------
1347
   -- Stop_All_Tasks --
1348
   --------------------
1349
 
1350
   procedure Stop_All_Tasks is
1351
   begin
1352
      null;
1353
   end Stop_All_Tasks;
1354
 
1355
   ---------------
1356
   -- Stop_Task --
1357
   ---------------
1358
 
1359
   function Stop_Task (T : ST.Task_Id) return Boolean is
1360
      pragma Unreferenced (T);
1361
   begin
1362
      return False;
1363
   end Stop_Task;
1364
 
1365
   -------------------
1366
   -- Continue_Task --
1367
   -------------------
1368
 
1369
   function Continue_Task (T : ST.Task_Id) return Boolean is
1370
      pragma Unreferenced (T);
1371
   begin
1372
      return False;
1373
   end Continue_Task;
1374
 
1375
   ----------------
1376
   -- Initialize --
1377
   ----------------
1378
 
1379
   procedure Initialize (Environment_Task : Task_Id) is
1380
      act     : aliased struct_sigaction;
1381
      old_act : aliased struct_sigaction;
1382
      Tmp_Set : aliased sigset_t;
1383
      Result  : Interfaces.C.int;
1384
 
1385
      function State
1386
        (Int : System.Interrupt_Management.Interrupt_ID) return Character;
1387
      pragma Import (C, State, "__gnat_get_interrupt_state");
1388
      --  Get interrupt state.  Defined in a-init.c
1389
      --  The input argument is the interrupt number,
1390
      --  and the result is one of the following:
1391
 
1392
      Default : constant Character := 's';
1393
      --    'n'   this interrupt not set by any Interrupt_State pragma
1394
      --    'u'   Interrupt_State pragma set state to User
1395
      --    'r'   Interrupt_State pragma set state to Runtime
1396
      --    's'   Interrupt_State pragma set state to System (use "default"
1397
      --           system handler)
1398
 
1399
   begin
1400
      Environment_Task_Id := Environment_Task;
1401
 
1402
      Interrupt_Management.Initialize;
1403
 
1404
      --  Prepare the set of signals that should unblocked in all tasks
1405
 
1406
      Result := sigemptyset (Unblocked_Signal_Mask'Access);
1407
      pragma Assert (Result = 0);
1408
 
1409
      for J in Interrupt_Management.Interrupt_ID loop
1410
         if System.Interrupt_Management.Keep_Unmasked (J) then
1411
            Result := sigaddset (Unblocked_Signal_Mask'Access, Signal (J));
1412
            pragma Assert (Result = 0);
1413
         end if;
1414
      end loop;
1415
 
1416
      --  Initialize the lock used to synchronize chain of all ATCBs
1417
 
1418
      Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
1419
 
1420
      Specific.Initialize (Environment_Task);
1421
 
1422
      if Use_Alternate_Stack then
1423
         Environment_Task.Common.Task_Alternate_Stack :=
1424
           Alternate_Stack'Address;
1425
      end if;
1426
 
1427
      --  Make environment task known here because it doesn't go through
1428
      --  Activate_Tasks, which does it for all other tasks.
1429
 
1430
      Known_Tasks (Known_Tasks'First) := Environment_Task;
1431
      Environment_Task.Known_Tasks_Index := Known_Tasks'First;
1432
 
1433
      Enter_Task (Environment_Task);
1434
 
1435
      if State
1436
          (System.Interrupt_Management.Abort_Task_Interrupt) /= Default
1437
      then
1438
         act.sa_flags := 0;
1439
         act.sa_handler := Abort_Handler'Address;
1440
 
1441
         Result := sigemptyset (Tmp_Set'Access);
1442
         pragma Assert (Result = 0);
1443
         act.sa_mask := Tmp_Set;
1444
 
1445
         Result :=
1446
           sigaction
1447
             (Signal (System.Interrupt_Management.Abort_Task_Interrupt),
1448
              act'Unchecked_Access,
1449
              old_act'Unchecked_Access);
1450
         pragma Assert (Result = 0);
1451
         Abort_Handler_Installed := True;
1452
      end if;
1453
   end Initialize;
1454
 
1455
end System.Task_Primitives.Operations;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.