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

Subversion Repositories openrisc

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

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 OpenVMS/Alpha 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.Tasking.Debug;
46
with System.OS_Primitives;
47
with System.Soft_Links;
48
with System.Aux_DEC;
49
 
50
package body System.Task_Primitives.Operations is
51
 
52
   use System.Tasking.Debug;
53
   use System.Tasking;
54
   use Interfaces.C;
55
   use System.OS_Interface;
56
   use System.Parameters;
57
   use System.OS_Primitives;
58
   use type System.OS_Primitives.OS_Time;
59
 
60
   package SSL renames System.Soft_Links;
61
 
62
   ----------------
63
   -- Local Data --
64
   ----------------
65
 
66
   --  The followings are logically constants, but need to be initialized
67
   --  at run time.
68
 
69
   Single_RTS_Lock : aliased RTS_Lock;
70
   --  This is a lock to allow only one thread of control in the RTS at
71
   --  a time; it is used to execute in mutual exclusion from all other tasks.
72
   --  Used mainly in Single_Lock mode, but also to protect All_Tasks_List
73
 
74
   ATCB_Key : aliased pthread_key_t;
75
   --  Key used to find the Ada Task_Id associated with a thread
76
 
77
   Environment_Task_Id : Task_Id;
78
   --  A variable to hold Task_Id for the environment task
79
 
80
   Time_Slice_Val : Integer;
81
   pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
82
 
83
   Dispatching_Policy : Character;
84
   pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
85
 
86
   Foreign_Task_Elaborated : aliased Boolean := True;
87
   --  Used to identified fake tasks (i.e., non-Ada Threads)
88
 
89
   --------------------
90
   -- Local Packages --
91
   --------------------
92
 
93
   package Specific is
94
 
95
      procedure Initialize (Environment_Task : Task_Id);
96
      pragma Inline (Initialize);
97
      --  Initialize various data needed by this package
98
 
99
      function Is_Valid_Task return Boolean;
100
      pragma Inline (Is_Valid_Task);
101
      --  Does executing thread have a TCB?
102
 
103
      procedure Set (Self_Id : Task_Id);
104
      pragma Inline (Set);
105
      --  Set the self id for the current task
106
 
107
      function Self return Task_Id;
108
      pragma Inline (Self);
109
      --  Return a pointer to the Ada Task Control Block of the calling task
110
 
111
   end Specific;
112
 
113
   package body Specific is separate;
114
   --  The body of this package is target specific
115
 
116
   ----------------------------------
117
   -- ATCB allocation/deallocation --
118
   ----------------------------------
119
 
120
   package body ATCB_Allocation is separate;
121
   --  The body of this package is shared across several targets
122
 
123
   ---------------------------------
124
   -- Support for foreign threads --
125
   ---------------------------------
126
 
127
   function Register_Foreign_Thread (Thread : Thread_Id) return Task_Id;
128
   --  Allocate and Initialize a new ATCB for the current Thread
129
 
130
   function Register_Foreign_Thread
131
     (Thread : Thread_Id) return Task_Id is separate;
132
 
133
   -----------------------
134
   -- Local Subprograms --
135
   -----------------------
136
 
137
   function To_Task_Id is
138
     new Ada.Unchecked_Conversion
139
       (System.Task_Primitives.Task_Address, Task_Id);
140
 
141
   function To_Address is
142
     new Ada.Unchecked_Conversion
143
       (Task_Id, System.Task_Primitives.Task_Address);
144
 
145
   procedure Timer_Sleep_AST (ID : Address);
146
   pragma Convention (C, Timer_Sleep_AST);
147
   --  Signal the condition variable when AST fires
148
 
149
   procedure Timer_Sleep_AST (ID : Address) is
150
      Result : Interfaces.C.int;
151
      pragma Warnings (Off, Result);
152
      Self_ID : constant Task_Id := To_Task_Id (ID);
153
   begin
154
      Self_ID.Common.LL.AST_Pending := False;
155
      Result := pthread_cond_signal_int_np (Self_ID.Common.LL.CV'Access);
156
      pragma Assert (Result = 0);
157
   end Timer_Sleep_AST;
158
 
159
   -----------------
160
   -- Stack_Guard --
161
   -----------------
162
 
163
   --  The underlying thread system sets a guard page at the bottom of a thread
164
   --  stack, so nothing is needed.
165
   --  ??? Check the comment above
166
 
167
   procedure Stack_Guard (T : ST.Task_Id; On : Boolean) is
168
      pragma Unreferenced (T);
169
      pragma Unreferenced (On);
170
   begin
171
      null;
172
   end Stack_Guard;
173
 
174
   --------------------
175
   -- Get_Thread_Id  --
176
   --------------------
177
 
178
   function Get_Thread_Id (T : ST.Task_Id) return OSI.Thread_Id is
179
   begin
180
      return T.Common.LL.Thread;
181
   end Get_Thread_Id;
182
 
183
   ----------
184
   -- Self --
185
   ----------
186
 
187
   function Self return Task_Id renames Specific.Self;
188
 
189
   ---------------------
190
   -- Initialize_Lock --
191
   ---------------------
192
 
193
   --  Note: mutexes and cond_variables needed per-task basis are initialized
194
   --  in Initialize_TCB and the Storage_Error is handled. Other mutexes (such
195
   --  as RTS_Lock, Memory_Lock...) used in RTS is initialized before any
196
   --  status change of RTS. Therefore raising Storage_Error in the following
197
   --  routines should be able to be handled safely.
198
 
199
   procedure Initialize_Lock
200
     (Prio : System.Any_Priority;
201
      L    : not null access Lock)
202
   is
203
      Attributes : aliased pthread_mutexattr_t;
204
      Result     : Interfaces.C.int;
205
 
206
   begin
207
      Result := pthread_mutexattr_init (Attributes'Access);
208
      pragma Assert (Result = 0 or else Result = ENOMEM);
209
 
210
      if Result = ENOMEM then
211
         raise Storage_Error;
212
      end if;
213
 
214
      L.Prio_Save := 0;
215
      L.Prio := Interfaces.C.int (Prio);
216
 
217
      Result := pthread_mutex_init (L.L'Access, Attributes'Access);
218
      pragma Assert (Result = 0 or else Result = ENOMEM);
219
 
220
      if Result = ENOMEM then
221
         raise Storage_Error;
222
      end if;
223
 
224
      Result := pthread_mutexattr_destroy (Attributes'Access);
225
      pragma Assert (Result = 0);
226
   end Initialize_Lock;
227
 
228
   procedure Initialize_Lock
229
     (L     : not null access RTS_Lock;
230
      Level : Lock_Level)
231
   is
232
      pragma Unreferenced (Level);
233
 
234
      Attributes : aliased pthread_mutexattr_t;
235
      Result : Interfaces.C.int;
236
 
237
   begin
238
      Result := pthread_mutexattr_init (Attributes'Access);
239
      pragma Assert (Result = 0 or else Result = ENOMEM);
240
 
241
      if Result = ENOMEM then
242
         raise Storage_Error;
243
      end if;
244
 
245
--      Don't use, see comment in s-osinte.ads about ERRORCHECK mutexes???
246
--      Result := pthread_mutexattr_settype_np
247
--        (Attributes'Access, PTHREAD_MUTEX_ERRORCHECK_NP);
248
--      pragma Assert (Result = 0);
249
 
250
--      Result := pthread_mutexattr_setprotocol
251
--        (Attributes'Access, PTHREAD_PRIO_PROTECT);
252
--      pragma Assert (Result = 0);
253
 
254
--      Result := pthread_mutexattr_setprioceiling
255
--         (Attributes'Access, Interfaces.C.int (System.Any_Priority'Last));
256
--      pragma Assert (Result = 0);
257
 
258
      Result := pthread_mutex_init (L, Attributes'Access);
259
 
260
      pragma Assert (Result = 0 or else Result = ENOMEM);
261
 
262
      if Result = ENOMEM then
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
   -------------------
271
   -- Finalize_Lock --
272
   -------------------
273
 
274
   procedure Finalize_Lock (L : not null access Lock) is
275
      Result : Interfaces.C.int;
276
   begin
277
      Result := pthread_mutex_destroy (L.L'Access);
278
      pragma Assert (Result = 0);
279
   end Finalize_Lock;
280
 
281
   procedure Finalize_Lock (L : not null access RTS_Lock) is
282
      Result : Interfaces.C.int;
283
   begin
284
      Result := pthread_mutex_destroy (L);
285
      pragma Assert (Result = 0);
286
   end Finalize_Lock;
287
 
288
   ----------------
289
   -- Write_Lock --
290
   ----------------
291
 
292
   procedure Write_Lock
293
     (L                 : not null access Lock;
294
      Ceiling_Violation : out Boolean)
295
   is
296
      Self_ID        : constant Task_Id := Self;
297
      All_Tasks_Link : constant Task_Id := Self.Common.All_Tasks_Link;
298
      Current_Prio   : System.Any_Priority;
299
      Result         : Interfaces.C.int;
300
 
301
   begin
302
      Current_Prio := Get_Priority (Self_ID);
303
 
304
      --  If there is no other tasks, no need to check priorities
305
 
306
      if All_Tasks_Link /= Null_Task
307
        and then L.Prio < Interfaces.C.int (Current_Prio)
308
      then
309
         Ceiling_Violation := True;
310
         return;
311
      end if;
312
 
313
      Result := pthread_mutex_lock (L.L'Access);
314
      pragma Assert (Result = 0);
315
 
316
      Ceiling_Violation := False;
317
--  Why is this commented out ???
318
--      L.Prio_Save := Interfaces.C.int (Current_Prio);
319
--      Set_Priority (Self_ID, System.Any_Priority (L.Prio));
320
   end Write_Lock;
321
 
322
   procedure Write_Lock
323
     (L           : not null access RTS_Lock;
324
      Global_Lock : Boolean := False)
325
   is
326
      Result : Interfaces.C.int;
327
   begin
328
      if not Single_Lock or else Global_Lock then
329
         Result := pthread_mutex_lock (L);
330
         pragma Assert (Result = 0);
331
      end if;
332
   end Write_Lock;
333
 
334
   procedure Write_Lock (T : Task_Id) is
335
      Result : Interfaces.C.int;
336
   begin
337
      if not Single_Lock then
338
         Result := pthread_mutex_lock (T.Common.LL.L'Access);
339
         pragma Assert (Result = 0);
340
      end if;
341
   end Write_Lock;
342
 
343
   ---------------
344
   -- Read_Lock --
345
   ---------------
346
 
347
   procedure Read_Lock
348
     (L                 : not null access Lock;
349
      Ceiling_Violation : out Boolean)
350
   is
351
   begin
352
      Write_Lock (L, Ceiling_Violation);
353
   end Read_Lock;
354
 
355
   ------------
356
   -- Unlock --
357
   ------------
358
 
359
   procedure Unlock (L : not null access Lock) is
360
      Result : Interfaces.C.int;
361
   begin
362
      Result := pthread_mutex_unlock (L.L'Access);
363
      pragma Assert (Result = 0);
364
   end Unlock;
365
 
366
   procedure Unlock
367
     (L           : not null access RTS_Lock;
368
      Global_Lock : Boolean := False)
369
   is
370
      Result : Interfaces.C.int;
371
   begin
372
      if not Single_Lock or else Global_Lock then
373
         Result := pthread_mutex_unlock (L);
374
         pragma Assert (Result = 0);
375
      end if;
376
   end Unlock;
377
 
378
   procedure Unlock (T : Task_Id) is
379
      Result : Interfaces.C.int;
380
   begin
381
      if not Single_Lock then
382
         Result := pthread_mutex_unlock (T.Common.LL.L'Access);
383
         pragma Assert (Result = 0);
384
      end if;
385
   end Unlock;
386
 
387
   -----------------
388
   -- Set_Ceiling --
389
   -----------------
390
 
391
   --  Dynamic priority ceilings are not supported by the underlying system
392
 
393
   procedure Set_Ceiling
394
     (L    : not null access Lock;
395
      Prio : System.Any_Priority)
396
   is
397
      pragma Unreferenced (L, Prio);
398
   begin
399
      null;
400
   end Set_Ceiling;
401
 
402
   -----------
403
   -- Sleep --
404
   -----------
405
 
406
   procedure Sleep
407
     (Self_ID : Task_Id;
408
      Reason  : System.Tasking.Task_States)
409
   is
410
      pragma Unreferenced (Reason);
411
      Result : Interfaces.C.int;
412
 
413
   begin
414
      Result :=
415
        pthread_cond_wait
416
          (cond  => Self_ID.Common.LL.CV'Access,
417
           mutex => (if Single_Lock
418
                     then Single_RTS_Lock'Access
419
                     else Self_ID.Common.LL.L'Access));
420
 
421
      --  EINTR is not considered a failure
422
 
423
      pragma Assert (Result = 0 or else Result = EINTR);
424
 
425
      if Self_ID.Deferral_Level = 0
426
        and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
427
      then
428
         Unlock (Self_ID);
429
         raise Standard'Abort_Signal;
430
      end if;
431
   end Sleep;
432
 
433
   -----------------
434
   -- Timed_Sleep --
435
   -----------------
436
 
437
   procedure Timed_Sleep
438
     (Self_ID  : Task_Id;
439
      Time     : Duration;
440
      Mode     : ST.Delay_Modes;
441
      Reason   : System.Tasking.Task_States;
442
      Timedout : out Boolean;
443
      Yielded  : out Boolean)
444
   is
445
      pragma Unreferenced (Reason);
446
 
447
      Sleep_Time : OS_Time;
448
      Result     : Interfaces.C.int;
449
      Status     : Cond_Value_Type;
450
 
451
      --  The body below requires more comments ???
452
 
453
   begin
454
      Timedout := False;
455
      Yielded := False;
456
 
457
      Sleep_Time := To_OS_Time (Time, Mode);
458
 
459
      if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
460
         return;
461
      end if;
462
 
463
      Self_ID.Common.LL.AST_Pending := True;
464
 
465
      Sys_Setimr
466
       (Status, 0, Sleep_Time,
467
        Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
468
 
469
      if (Status and 1) /= 1 then
470
         raise Storage_Error;
471
      end if;
472
 
473
      if Single_Lock then
474
         Result :=
475
           pthread_cond_wait
476
             (Self_ID.Common.LL.CV'Access, Single_RTS_Lock'Access);
477
         pragma Assert (Result = 0);
478
 
479
      else
480
         Result :=
481
           pthread_cond_wait
482
             (Self_ID.Common.LL.CV'Access, Self_ID.Common.LL.L'Access);
483
         pragma Assert (Result = 0);
484
      end if;
485
 
486
      Yielded := True;
487
 
488
      if not Self_ID.Common.LL.AST_Pending then
489
         Timedout := True;
490
      else
491
         Sys_Cantim (Status, To_Address (Self_ID), 0);
492
         pragma Assert ((Status and 1) = 1);
493
      end if;
494
   end Timed_Sleep;
495
 
496
   -----------------
497
   -- Timed_Delay --
498
   -----------------
499
 
500
   procedure Timed_Delay
501
     (Self_ID : Task_Id;
502
      Time    : Duration;
503
      Mode    : ST.Delay_Modes)
504
   is
505
      Sleep_Time : OS_Time;
506
      Result     : Interfaces.C.int;
507
      Status     : Cond_Value_Type;
508
      Yielded    : Boolean := False;
509
 
510
   begin
511
      if Single_Lock then
512
         Lock_RTS;
513
      end if;
514
 
515
      --  More comments required in body below ???
516
 
517
      Write_Lock (Self_ID);
518
 
519
      if Time /= 0.0 or else Mode /= Relative then
520
         Sleep_Time := To_OS_Time (Time, Mode);
521
 
522
         if Mode = Relative or else OS_Clock <= Sleep_Time then
523
            Self_ID.Common.State := Delay_Sleep;
524
            Self_ID.Common.LL.AST_Pending := True;
525
 
526
            Sys_Setimr
527
             (Status, 0, Sleep_Time,
528
              Timer_Sleep_AST'Access, To_Address (Self_ID), 0);
529
 
530
            --  Comment following test
531
 
532
            if (Status and 1) /= 1 then
533
               raise Storage_Error;
534
            end if;
535
 
536
            loop
537
               if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
538
                  Sys_Cantim (Status, To_Address (Self_ID), 0);
539
                  pragma Assert ((Status and 1) = 1);
540
                  exit;
541
               end if;
542
 
543
               Result :=
544
                 pthread_cond_wait
545
                   (cond  => Self_ID.Common.LL.CV'Access,
546
                    mutex => (if Single_Lock
547
                              then Single_RTS_Lock'Access
548
                              else Self_ID.Common.LL.L'Access));
549
               pragma Assert (Result = 0);
550
 
551
               Yielded := True;
552
 
553
               exit when not Self_ID.Common.LL.AST_Pending;
554
            end loop;
555
 
556
            Self_ID.Common.State := Runnable;
557
         end if;
558
      end if;
559
 
560
      Unlock (Self_ID);
561
 
562
      if Single_Lock then
563
         Unlock_RTS;
564
      end if;
565
 
566
      if not Yielded then
567
         Result := sched_yield;
568
         pragma Assert (Result = 0);
569
      end if;
570
   end Timed_Delay;
571
 
572
   ---------------------
573
   -- Monotonic_Clock --
574
   ---------------------
575
 
576
   function Monotonic_Clock return Duration
577
     renames System.OS_Primitives.Monotonic_Clock;
578
 
579
   -------------------
580
   -- RT_Resolution --
581
   -------------------
582
 
583
   function RT_Resolution return Duration is
584
   begin
585
      --  Document origin of this magic constant ???
586
      return 10#1.0#E-3;
587
   end RT_Resolution;
588
 
589
   ------------
590
   -- Wakeup --
591
   ------------
592
 
593
   procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
594
      pragma Unreferenced (Reason);
595
      Result : Interfaces.C.int;
596
   begin
597
      Result := pthread_cond_signal (T.Common.LL.CV'Access);
598
      pragma Assert (Result = 0);
599
   end Wakeup;
600
 
601
   -----------
602
   -- Yield --
603
   -----------
604
 
605
   procedure Yield (Do_Yield : Boolean := True) is
606
      Result : Interfaces.C.int;
607
      pragma Unreferenced (Result);
608
   begin
609
      if Do_Yield then
610
         Result := sched_yield;
611
      end if;
612
   end Yield;
613
 
614
   ------------------
615
   -- Set_Priority --
616
   ------------------
617
 
618
   procedure Set_Priority
619
     (T                   : Task_Id;
620
      Prio                : System.Any_Priority;
621
      Loss_Of_Inheritance : Boolean := False)
622
   is
623
      pragma Unreferenced (Loss_Of_Inheritance);
624
 
625
      Result : Interfaces.C.int;
626
      Param  : aliased struct_sched_param;
627
 
628
      function Get_Policy (Prio : System.Any_Priority) return Character;
629
      pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
630
      --  Get priority specific dispatching policy
631
 
632
      Priority_Specific_Policy : constant Character := Get_Policy (Prio);
633
      --  Upper case first character of the policy name corresponding to the
634
      --  task as set by a Priority_Specific_Dispatching pragma.
635
 
636
   begin
637
      T.Common.Current_Priority := Prio;
638
      Param.sched_priority := Interfaces.C.int (Underlying_Priorities (Prio));
639
 
640
      if Dispatching_Policy = 'R'
641
        or else Priority_Specific_Policy = 'R'
642
        or else Time_Slice_Val > 0
643
      then
644
         Result :=
645
           pthread_setschedparam
646
             (T.Common.LL.Thread, SCHED_RR, Param'Access);
647
 
648
      elsif Dispatching_Policy = 'F'
649
        or else Priority_Specific_Policy = 'F'
650
        or else Time_Slice_Val = 0
651
      then
652
         Result :=
653
           pthread_setschedparam
654
             (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
655
 
656
      else
657
         --  SCHED_OTHER priorities are restricted to the range 8 - 15.
658
         --  Since the translation from Underlying priorities results
659
         --  in a range of 16 - 31, dividing by 2 gives the correct result.
660
 
661
         Param.sched_priority := Param.sched_priority / 2;
662
         Result :=
663
           pthread_setschedparam
664
             (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
665
      end if;
666
 
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
   begin
685
      Self_ID.Common.LL.Thread := pthread_self;
686
      Specific.Set (Self_ID);
687
   end Enter_Task;
688
 
689
   -------------------
690
   -- Is_Valid_Task --
691
   -------------------
692
 
693
   function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
694
 
695
   -----------------------------
696
   -- Register_Foreign_Thread --
697
   -----------------------------
698
 
699
   function Register_Foreign_Thread return Task_Id is
700
   begin
701
      if Is_Valid_Task then
702
         return Self;
703
      else
704
         return Register_Foreign_Thread (pthread_self);
705
      end if;
706
   end Register_Foreign_Thread;
707
 
708
   --------------------
709
   -- Initialize_TCB --
710
   --------------------
711
 
712
   procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
713
      Mutex_Attr : aliased pthread_mutexattr_t;
714
      Result     : Interfaces.C.int;
715
      Cond_Attr  : aliased pthread_condattr_t;
716
 
717
   begin
718
      --  More comments required in body below ???
719
 
720
      if not Single_Lock then
721
         Result := pthread_mutexattr_init (Mutex_Attr'Access);
722
         pragma Assert (Result = 0 or else Result = ENOMEM);
723
 
724
         if Result = 0 then
725
            Result :=
726
              pthread_mutex_init
727
                (Self_ID.Common.LL.L'Access, Mutex_Attr'Access);
728
            pragma Assert (Result = 0 or else Result = ENOMEM);
729
         end if;
730
 
731
         if Result /= 0 then
732
            Succeeded := False;
733
            return;
734
         end if;
735
 
736
         Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
737
         pragma Assert (Result = 0);
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
746
             (Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
747
         pragma Assert (Result = 0 or else Result = ENOMEM);
748
      end if;
749
 
750
      if Result = 0 then
751
         Succeeded := True;
752
 
753
      else
754
         if not Single_Lock then
755
            Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
756
            pragma Assert (Result = 0);
757
         end if;
758
 
759
         Succeeded := False;
760
      end if;
761
 
762
      Result := pthread_condattr_destroy (Cond_Attr'Access);
763
      pragma Assert (Result = 0);
764
   end Initialize_TCB;
765
 
766
   -----------------
767
   -- Create_Task --
768
   -----------------
769
 
770
   procedure Create_Task
771
     (T          : Task_Id;
772
      Wrapper    : System.Address;
773
      Stack_Size : System.Parameters.Size_Type;
774
      Priority   : System.Any_Priority;
775
      Succeeded  : out Boolean)
776
   is
777
      Attributes : aliased pthread_attr_t;
778
      Result     : Interfaces.C.int;
779
 
780
      function Thread_Body_Access is new
781
        Ada.Unchecked_Conversion (System.Aux_DEC.Short_Address, Thread_Body);
782
 
783
   begin
784
      --  Since the initial signal mask of a thread is inherited from the
785
      --  creator, we need to set our local signal mask to mask all signals
786
      --  during the creation operation, to make sure the new thread is
787
      --  not disturbed by signals before it has set its own Task_Id.
788
 
789
      Result := pthread_attr_init (Attributes'Access);
790
      pragma Assert (Result = 0 or else Result = ENOMEM);
791
 
792
      if Result /= 0 then
793
         Succeeded := False;
794
         return;
795
      end if;
796
 
797
      Result := pthread_attr_setdetachstate
798
        (Attributes'Access, PTHREAD_CREATE_DETACHED);
799
      pragma Assert (Result = 0);
800
 
801
      Result := pthread_attr_setstacksize
802
        (Attributes'Access, Interfaces.C.size_t (Stack_Size));
803
      pragma Assert (Result = 0);
804
 
805
      --  This call may be unnecessary, not sure. ???
806
 
807
      Result :=
808
        pthread_attr_setinheritsched
809
          (Attributes'Access, PTHREAD_EXPLICIT_SCHED);
810
      pragma Assert (Result = 0);
811
 
812
      --  Note: the use of Unrestricted_Access in the following call is needed
813
      --  because otherwise we have an error of getting a access-to-volatile
814
      --  value which points to a non-volatile object. But in this case it is
815
      --  safe to do this, since we know we have no problems with aliasing and
816
      --  Unrestricted_Access bypasses this check.
817
 
818
      Result :=
819
        pthread_create
820
          (T.Common.LL.Thread'Unrestricted_Access,
821
           Attributes'Access,
822
           Thread_Body_Access (Wrapper),
823
           To_Address (T));
824
 
825
      --  ENOMEM is a valid run-time error -- do not shut down
826
 
827
      pragma Assert (Result = 0
828
        or else Result = EAGAIN or else Result = ENOMEM);
829
 
830
      Succeeded := Result = 0;
831
 
832
      Result := pthread_attr_destroy (Attributes'Access);
833
      pragma Assert (Result = 0);
834
 
835
      if Succeeded then
836
         Set_Priority (T, Priority);
837
      end if;
838
   end Create_Task;
839
 
840
   ------------------
841
   -- Finalize_TCB --
842
   ------------------
843
 
844
   procedure Finalize_TCB (T : Task_Id) is
845
      Result : Interfaces.C.int;
846
 
847
   begin
848
      if not Single_Lock then
849
         Result := pthread_mutex_destroy (T.Common.LL.L'Access);
850
         pragma Assert (Result = 0);
851
      end if;
852
 
853
      Result := pthread_cond_destroy (T.Common.LL.CV'Access);
854
      pragma Assert (Result = 0);
855
 
856
      if T.Known_Tasks_Index /= -1 then
857
         Known_Tasks (T.Known_Tasks_Index) := null;
858
      end if;
859
 
860
      ATCB_Allocation.Free_ATCB (T);
861
   end Finalize_TCB;
862
 
863
   ---------------
864
   -- Exit_Task --
865
   ---------------
866
 
867
   procedure Exit_Task is
868
   begin
869
      null;
870
   end Exit_Task;
871
 
872
   ----------------
873
   -- Abort_Task --
874
   ----------------
875
 
876
   procedure Abort_Task (T : Task_Id) is
877
   begin
878
      --  Interrupt Server_Tasks may be waiting on an event flag
879
 
880
      if T.Common.State = Interrupt_Server_Blocked_On_Event_Flag then
881
         Wakeup (T, Interrupt_Server_Blocked_On_Event_Flag);
882
      end if;
883
   end Abort_Task;
884
 
885
   ----------------
886
   -- Initialize --
887
   ----------------
888
 
889
   procedure Initialize (S : in out Suspension_Object) is
890
      Mutex_Attr : aliased pthread_mutexattr_t;
891
      Cond_Attr  : aliased pthread_condattr_t;
892
      Result     : Interfaces.C.int;
893
   begin
894
      --  Initialize internal state (always to False (D.10 (6)))
895
 
896
      S.State := False;
897
      S.Waiting := False;
898
 
899
      --  Initialize internal mutex
900
 
901
      Result := pthread_mutexattr_init (Mutex_Attr'Access);
902
      pragma Assert (Result = 0 or else Result = ENOMEM);
903
 
904
      if Result = ENOMEM then
905
         raise Storage_Error;
906
      end if;
907
 
908
      Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
909
      pragma Assert (Result = 0 or else Result = ENOMEM);
910
 
911
      if Result = ENOMEM then
912
         Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
913
         pragma Assert (Result = 0);
914
 
915
         raise Storage_Error;
916
      end if;
917
 
918
      Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
919
      pragma Assert (Result = 0);
920
 
921
      --  Initialize internal condition variable
922
 
923
      Result := pthread_condattr_init (Cond_Attr'Access);
924
      pragma Assert (Result = 0 or else Result = ENOMEM);
925
 
926
      if Result /= 0 then
927
         Result := pthread_mutex_destroy (S.L'Access);
928
         pragma Assert (Result = 0);
929
 
930
         if Result = ENOMEM then
931
            raise Storage_Error;
932
         end if;
933
      end if;
934
 
935
      Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
936
      pragma Assert (Result = 0 or else Result = ENOMEM);
937
 
938
      if Result /= 0 then
939
         Result := pthread_mutex_destroy (S.L'Access);
940
         pragma Assert (Result = 0);
941
 
942
         if Result = ENOMEM then
943
            Result := pthread_condattr_destroy (Cond_Attr'Access);
944
            pragma Assert (Result = 0);
945
 
946
            raise Storage_Error;
947
         end if;
948
      end if;
949
 
950
      Result := pthread_condattr_destroy (Cond_Attr'Access);
951
      pragma Assert (Result = 0);
952
   end Initialize;
953
 
954
   --------------
955
   -- Finalize --
956
   --------------
957
 
958
   procedure Finalize (S : in out Suspension_Object) is
959
      Result : Interfaces.C.int;
960
 
961
   begin
962
      --  Destroy internal mutex
963
 
964
      Result := pthread_mutex_destroy (S.L'Access);
965
      pragma Assert (Result = 0);
966
 
967
      --  Destroy internal condition variable
968
 
969
      Result := pthread_cond_destroy (S.CV'Access);
970
      pragma Assert (Result = 0);
971
   end Finalize;
972
 
973
   -------------------
974
   -- Current_State --
975
   -------------------
976
 
977
   function Current_State (S : Suspension_Object) return Boolean is
978
   begin
979
      --  We do not want to use lock on this read operation. State is marked
980
      --  as Atomic so that we ensure that the value retrieved is correct.
981
 
982
      return S.State;
983
   end Current_State;
984
 
985
   ---------------
986
   -- Set_False --
987
   ---------------
988
 
989
   procedure Set_False (S : in out Suspension_Object) is
990
      Result : Interfaces.C.int;
991
 
992
   begin
993
      SSL.Abort_Defer.all;
994
 
995
      Result := pthread_mutex_lock (S.L'Access);
996
      pragma Assert (Result = 0);
997
 
998
      S.State := False;
999
 
1000
      Result := pthread_mutex_unlock (S.L'Access);
1001
      pragma Assert (Result = 0);
1002
 
1003
      SSL.Abort_Undefer.all;
1004
   end Set_False;
1005
 
1006
   --------------
1007
   -- Set_True --
1008
   --------------
1009
 
1010
   procedure Set_True (S : in out Suspension_Object) is
1011
      Result : Interfaces.C.int;
1012
 
1013
   begin
1014
      SSL.Abort_Defer.all;
1015
 
1016
      Result := pthread_mutex_lock (S.L'Access);
1017
      pragma Assert (Result = 0);
1018
 
1019
      --  If there is already a task waiting on this suspension object then
1020
      --  we resume it, leaving the state of the suspension object to False,
1021
      --  as specified in (RM D.10(9)), otherwise leave state set to True.
1022
 
1023
      if S.Waiting then
1024
         S.Waiting := False;
1025
         S.State := False;
1026
 
1027
         Result := pthread_cond_signal (S.CV'Access);
1028
         pragma Assert (Result = 0);
1029
 
1030
      else
1031
         S.State := True;
1032
      end if;
1033
 
1034
      Result := pthread_mutex_unlock (S.L'Access);
1035
      pragma Assert (Result = 0);
1036
 
1037
      SSL.Abort_Undefer.all;
1038
   end Set_True;
1039
 
1040
   ------------------------
1041
   -- Suspend_Until_True --
1042
   ------------------------
1043
 
1044
   procedure Suspend_Until_True (S : in out Suspension_Object) is
1045
      Result : Interfaces.C.int;
1046
 
1047
   begin
1048
      SSL.Abort_Defer.all;
1049
 
1050
      Result := pthread_mutex_lock (S.L'Access);
1051
      pragma Assert (Result = 0);
1052
 
1053
      if S.Waiting then
1054
 
1055
         --  Program_Error must be raised upon calling Suspend_Until_True
1056
         --  if another task is already waiting on that suspension object
1057
         --  (RM D.10(10)).
1058
 
1059
         Result := pthread_mutex_unlock (S.L'Access);
1060
         pragma Assert (Result = 0);
1061
 
1062
         SSL.Abort_Undefer.all;
1063
 
1064
         raise Program_Error;
1065
 
1066
      else
1067
         --  Suspend the task if the state is False. Otherwise, the task
1068
         --  continues its execution, and the state of the suspension object
1069
         --  is set to False (ARM D.10 par. 9).
1070
 
1071
         if S.State then
1072
            S.State := False;
1073
         else
1074
            S.Waiting := True;
1075
 
1076
            loop
1077
               --  Loop in case pthread_cond_wait returns earlier than expected
1078
               --  (e.g. in case of EINTR caused by a signal).
1079
 
1080
               Result := pthread_cond_wait (S.CV'Access, S.L'Access);
1081
               pragma Assert (Result = 0 or else Result = EINTR);
1082
 
1083
               exit when not S.Waiting;
1084
            end loop;
1085
         end if;
1086
 
1087
         Result := pthread_mutex_unlock (S.L'Access);
1088
         pragma Assert (Result = 0);
1089
 
1090
         SSL.Abort_Undefer.all;
1091
      end if;
1092
   end Suspend_Until_True;
1093
 
1094
   ----------------
1095
   -- Check_Exit --
1096
   ----------------
1097
 
1098
   --  Dummy version
1099
 
1100
   function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
1101
      pragma Unreferenced (Self_ID);
1102
   begin
1103
      return True;
1104
   end Check_Exit;
1105
 
1106
   --------------------
1107
   -- Check_No_Locks --
1108
   --------------------
1109
 
1110
   function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
1111
      pragma Unreferenced (Self_ID);
1112
   begin
1113
      return True;
1114
   end Check_No_Locks;
1115
 
1116
   ----------------------
1117
   -- Environment_Task --
1118
   ----------------------
1119
 
1120
   function Environment_Task return Task_Id is
1121
   begin
1122
      return Environment_Task_Id;
1123
   end Environment_Task;
1124
 
1125
   --------------
1126
   -- Lock_RTS --
1127
   --------------
1128
 
1129
   procedure Lock_RTS is
1130
   begin
1131
      Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
1132
   end Lock_RTS;
1133
 
1134
   ----------------
1135
   -- Unlock_RTS --
1136
   ----------------
1137
 
1138
   procedure Unlock_RTS is
1139
   begin
1140
      Unlock (Single_RTS_Lock'Access, Global_Lock => True);
1141
   end Unlock_RTS;
1142
 
1143
   ------------------
1144
   -- Suspend_Task --
1145
   ------------------
1146
 
1147
   function Suspend_Task
1148
     (T           : ST.Task_Id;
1149
      Thread_Self : Thread_Id) return Boolean
1150
   is
1151
      pragma Unreferenced (T);
1152
      pragma Unreferenced (Thread_Self);
1153
   begin
1154
      return False;
1155
   end Suspend_Task;
1156
 
1157
   -----------------
1158
   -- Resume_Task --
1159
   -----------------
1160
 
1161
   function Resume_Task
1162
     (T           : ST.Task_Id;
1163
      Thread_Self : Thread_Id) return Boolean
1164
   is
1165
      pragma Unreferenced (T);
1166
      pragma Unreferenced (Thread_Self);
1167
   begin
1168
      return False;
1169
   end Resume_Task;
1170
 
1171
   --------------------
1172
   -- Stop_All_Tasks --
1173
   --------------------
1174
 
1175
   procedure Stop_All_Tasks is
1176
   begin
1177
      null;
1178
   end Stop_All_Tasks;
1179
 
1180
   ---------------
1181
   -- Stop_Task --
1182
   ---------------
1183
 
1184
   function Stop_Task (T : ST.Task_Id) return Boolean is
1185
      pragma Unreferenced (T);
1186
   begin
1187
      return False;
1188
   end Stop_Task;
1189
 
1190
   -------------------
1191
   -- Continue_Task --
1192
   -------------------
1193
 
1194
   function Continue_Task (T : ST.Task_Id) return Boolean is
1195
      pragma Unreferenced (T);
1196
   begin
1197
      return False;
1198
   end Continue_Task;
1199
 
1200
   ----------------
1201
   -- Initialize --
1202
   ----------------
1203
 
1204
   procedure Initialize (Environment_Task : Task_Id) is
1205
 
1206
      --  The DEC Ada facility code defined in Starlet
1207
      Ada_Facility : constant := 49;
1208
 
1209
      function DBGEXT (Control_Block : System.Address)
1210
        return System.Aux_DEC.Unsigned_Word;
1211
      --  DBGEXT is imported  from s-tasdeb.adb and its parameter re-typed
1212
      --  as Address to avoid having a VMS specific s-tasdeb.ads.
1213
      pragma Interface (C, DBGEXT);
1214
      pragma Import_Function (DBGEXT, "GNAT$DBGEXT");
1215
 
1216
      type Facility_Type is range 0 .. 65535;
1217
 
1218
      procedure Debug_Register
1219
        (ADBGEXT    : System.Address;
1220
         ATCB_Key   : pthread_key_t;
1221
         Facility   : Facility_Type;
1222
         Std_Prolog : Integer);
1223
      pragma Import (C, Debug_Register, "CMA$DEBUG_REGISTER");
1224
   begin
1225
      Environment_Task_Id := Environment_Task;
1226
 
1227
      --  Initialize the lock used to synchronize chain of all ATCBs
1228
 
1229
      Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
1230
 
1231
      Specific.Initialize (Environment_Task);
1232
 
1233
      --  Pass the context key on to CMA along with the other parameters
1234
      Debug_Register
1235
       (
1236
        DBGEXT'Address,    --  Our DEBUG handling entry point
1237
        ATCB_Key,          --  CMA context key for our Ada TCB's
1238
        Ada_Facility,      --  Out facility code
1239
 
1240
       );
1241
 
1242
      --  Make environment task known here because it doesn't go through
1243
      --  Activate_Tasks, which does it for all other tasks.
1244
 
1245
      Known_Tasks (Known_Tasks'First) := Environment_Task;
1246
      Environment_Task.Known_Tasks_Index := Known_Tasks'First;
1247
 
1248
      Enter_Task (Environment_Task);
1249
   end Initialize;
1250
 
1251
   -----------------------
1252
   -- Set_Task_Affinity --
1253
   -----------------------
1254
 
1255
   procedure Set_Task_Affinity (T : ST.Task_Id) is
1256
      pragma Unreferenced (T);
1257
 
1258
   begin
1259
      --  Setting task affinity is not supported by the underlying system
1260
 
1261
      null;
1262
   end Set_Task_Affinity;
1263
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.