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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [s-taprop-irix.adb] - Blame information for rev 801

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

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