OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc2/] [gcc/] [ada/] [s-taprop-vms.adb] - Blame information for rev 384

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