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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [ada/] [s-taprop-irix.adb] - Blame information for rev 826

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