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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [ada/] [s-tarest.adb] - Blame information for rev 847

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

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                 GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                 --
4
--                                                                          --
5
--     S Y S T E M . T A S K I N G . R E S T R I C T E D . S T A G E S      --
6
--                                                                          --
7
--                                  B o d y                                 --
8
--                                                                          --
9
--         Copyright (C) 1999-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
pragma Style_Checks (All_Checks);
33
--  Turn off subprogram alpha order check, since we group soft link
34
--  bodies and also separate off subprograms for restricted GNARLI.
35
 
36
--  This is a simplified version of the System.Tasking.Stages package,
37
--  intended to be used in a restricted run time.
38
 
39
--  This package represents the high level tasking interface used by the
40
--  compiler to expand Ada 95 tasking constructs into simpler run time calls.
41
 
42
pragma Polling (Off);
43
--  Turn off polling, we do not want ATC polling to take place during
44
--  tasking operations. It causes infinite loops and other problems.
45
 
46
with Ada.Exceptions;
47
 
48
with System.Task_Primitives.Operations;
49
with System.Soft_Links.Tasking;
50
with System.Secondary_Stack;
51
with System.Storage_Elements;
52
 
53
with System.Soft_Links;
54
--  Used for the non-tasking routines (*_NT) that refer to global data. They
55
--  are needed here before the tasking run time has been elaborated. used for
56
--  Create_TSD This package also provides initialization routines for task
57
--  specific data. The GNARL must call these to be sure that all non-tasking
58
--  Ada constructs will work.
59
 
60
package body System.Tasking.Restricted.Stages is
61
 
62
   package STPO renames System.Task_Primitives.Operations;
63
   package SSL  renames System.Soft_Links;
64
   package SSE  renames System.Storage_Elements;
65
   package SST  renames System.Secondary_Stack;
66
 
67
   use Ada.Exceptions;
68
 
69
   use Parameters;
70
   use Task_Primitives.Operations;
71
   use Task_Info;
72
 
73
   Global_Task_Lock : aliased System.Task_Primitives.RTS_Lock;
74
   --  This is a global lock; it is used to execute in mutual exclusion
75
   --  from all other tasks. It is only used by Task_Lock and Task_Unlock.
76
 
77
   -----------------------------------------------------------------
78
   -- Tasking versions of services needed by non-tasking programs --
79
   -----------------------------------------------------------------
80
 
81
   function Get_Current_Excep return SSL.EOA;
82
   --  Task-safe version of SSL.Get_Current_Excep
83
 
84
   procedure Task_Lock;
85
   --  Locks out other tasks. Preceding a section of code by Task_Lock and
86
   --  following it by Task_Unlock creates a critical region. This is used
87
   --  for ensuring that a region of non-tasking code (such as code used to
88
   --  allocate memory) is tasking safe. Note that it is valid for calls to
89
   --  Task_Lock/Task_Unlock to be nested, and this must work properly, i.e.
90
   --  only the corresponding outer level Task_Unlock will actually unlock.
91
 
92
   procedure Task_Unlock;
93
   --  Releases lock previously set by call to Task_Lock. In the nested case,
94
   --  all nested locks must be released before other tasks competing for the
95
   --  tasking lock are released.
96
 
97
   -----------------------
98
   -- Local Subprograms --
99
   -----------------------
100
 
101
   procedure Task_Wrapper (Self_ID : Task_Id);
102
   --  This is the procedure that is called by the GNULL from the
103
   --  new context when a task is created. It waits for activation
104
   --  and then calls the task body procedure. When the task body
105
   --  procedure completes, it terminates the task.
106
 
107
   procedure Terminate_Task (Self_ID : Task_Id);
108
   --  Terminate the calling task.
109
   --  This should only be called by the Task_Wrapper procedure.
110
 
111
   procedure Init_RTS;
112
   --  This procedure performs the initialization of the GNARL.
113
   --  It consists of initializing the environment task, global locks, and
114
   --  installing tasking versions of certain operations used by the compiler.
115
   --  Init_RTS is called during elaboration.
116
 
117
   -----------------------
118
   -- Get_Current_Excep --
119
   -----------------------
120
 
121
   function Get_Current_Excep return SSL.EOA is
122
   begin
123
      return STPO.Self.Common.Compiler_Data.Current_Excep'Access;
124
   end Get_Current_Excep;
125
 
126
   ---------------
127
   -- Task_Lock --
128
   ---------------
129
 
130
   procedure Task_Lock is
131
      Self_ID : constant Task_Id := STPO.Self;
132
 
133
   begin
134
      Self_ID.Common.Global_Task_Lock_Nesting :=
135
        Self_ID.Common.Global_Task_Lock_Nesting + 1;
136
 
137
      if Self_ID.Common.Global_Task_Lock_Nesting = 1 then
138
         STPO.Write_Lock (Global_Task_Lock'Access, Global_Lock => True);
139
      end if;
140
   end Task_Lock;
141
 
142
   -----------------
143
   -- Task_Unlock --
144
   -----------------
145
 
146
   procedure Task_Unlock is
147
      Self_ID : constant Task_Id := STPO.Self;
148
 
149
   begin
150
      pragma Assert (Self_ID.Common.Global_Task_Lock_Nesting > 0);
151
      Self_ID.Common.Global_Task_Lock_Nesting :=
152
        Self_ID.Common.Global_Task_Lock_Nesting - 1;
153
 
154
      if Self_ID.Common.Global_Task_Lock_Nesting = 0 then
155
         STPO.Unlock (Global_Task_Lock'Access, Global_Lock => True);
156
      end if;
157
   end Task_Unlock;
158
 
159
   ------------------
160
   -- Task_Wrapper --
161
   ------------------
162
 
163
   --  The task wrapper is a procedure that is called first for each task
164
   --  task body, and which in turn calls the compiler-generated task body
165
   --  procedure. The wrapper's main job is to do initialization for the task.
166
 
167
   --  The variable ID in the task wrapper is used to implement the Self
168
   --  function on targets where there is a fast way to find the stack base
169
   --  of the current thread, since it should be at a fixed offset from the
170
   --  stack base.
171
 
172
   procedure Task_Wrapper (Self_ID : Task_Id) is
173
      ID : Task_Id := Self_ID;
174
      pragma Volatile (ID);
175
      pragma Warnings (Off, ID);
176
      --  Variable used on some targets to implement a fast self. We turn off
177
      --  warnings because a stand alone volatile constant has to be imported,
178
      --  so we don't want warnings about ID not being referenced, and volatile
179
      --  having no effect.
180
      --
181
      --  DO NOT delete ID. As noted, it is needed on some targets.
182
 
183
      use type SSE.Storage_Offset;
184
 
185
      Secondary_Stack : aliased SSE.Storage_Array
186
        (1 .. Self_ID.Common.Compiler_Data.Pri_Stack_Info.Size *
187
                SSE.Storage_Offset (Parameters.Sec_Stack_Ratio) / 100);
188
 
189
      pragma Warnings (Off);
190
      Secondary_Stack_Address : System.Address := Secondary_Stack'Address;
191
      pragma Warnings (On);
192
      --  Address of secondary stack. In the fixed secondary stack case, this
193
      --  value is not modified, causing a warning, hence the bracketing with
194
      --  Warnings (Off/On).
195
 
196
      Cause : Cause_Of_Termination := Normal;
197
      --  Indicates the reason why this task terminates. Normal corresponds to
198
      --  a task terminating due to completing the last statement of its body.
199
      --  If the task terminates because of an exception raised by the
200
      --  execution of its task body, then Cause is set to Unhandled_Exception.
201
      --  Aborts are not allowed in the restricted profile to which this file
202
      --  belongs.
203
 
204
      EO : Exception_Occurrence;
205
      --  If the task terminates because of an exception raised by the
206
      --  execution of its task body, then EO will contain the associated
207
      --  exception occurrence. Otherwise, it will contain Null_Occurrence.
208
 
209
   begin
210
      if not Parameters.Sec_Stack_Dynamic then
211
         Self_ID.Common.Compiler_Data.Sec_Stack_Addr :=
212
           Secondary_Stack'Address;
213
         SST.SS_Init (Secondary_Stack_Address, Integer (Secondary_Stack'Last));
214
      end if;
215
 
216
      --  Initialize low-level TCB components, that
217
      --  cannot be initialized by the creator.
218
 
219
      Enter_Task (Self_ID);
220
 
221
      --  Call the task body procedure
222
 
223
      begin
224
         --  We are separating the following portion of the code in order to
225
         --  place the exception handlers in a different block. In this way we
226
         --  do not call Set_Jmpbuf_Address (which needs Self) before we set
227
         --  Self in Enter_Task.
228
 
229
         --  Note that in the case of Ravenscar HI-E where there are no
230
         --  exception handlers, the exception handler is suppressed.
231
 
232
         --  Call the task body procedure
233
 
234
         Self_ID.Common.Task_Entry_Point (Self_ID.Common.Task_Arg);
235
 
236
         --  Normal task termination
237
 
238
         Cause := Normal;
239
         Save_Occurrence (EO, Ada.Exceptions.Null_Occurrence);
240
 
241
      exception
242
         when E : others =>
243
 
244
            --  Task terminating because of an unhandled exception
245
 
246
            Cause := Unhandled_Exception;
247
            Save_Occurrence (EO, E);
248
      end;
249
 
250
      --  Look for a fall-back handler. It can be either in the task itself
251
      --  or in the environment task. Note that this code is always executed
252
      --  by a task whose master is the environment task. The task termination
253
      --  code for the environment task is executed by
254
      --  SSL.Task_Termination_Handler.
255
 
256
      --  This package is part of the restricted run time which supports
257
      --  neither task hierarchies (No_Task_Hierarchy) nor specific task
258
      --  termination handlers (No_Specific_Termination_Handlers).
259
 
260
      --  There is no need for explicit protection against race conditions
261
      --  for Self_ID.Common.Fall_Back_Handler because this procedure can
262
      --  only be executed by Self, and the Fall_Back_Handler can only be
263
      --  modified by Self.
264
 
265
      if Self_ID.Common.Fall_Back_Handler /= null then
266
         Self_ID.Common.Fall_Back_Handler (Cause, Self_ID, EO);
267
      else
268
         declare
269
            TH : Termination_Handler := null;
270
 
271
         begin
272
            if Single_Lock then
273
               Lock_RTS;
274
            end if;
275
 
276
            Write_Lock (Self_ID.Common.Parent);
277
 
278
            TH := Self_ID.Common.Parent.Common.Fall_Back_Handler;
279
 
280
            Unlock (Self_ID.Common.Parent);
281
 
282
            if Single_Lock then
283
               Unlock_RTS;
284
            end if;
285
 
286
            --  Execute the task termination handler if we found it
287
 
288
            if TH /= null then
289
               TH.all (Cause, Self_ID, EO);
290
            end if;
291
         end;
292
      end if;
293
 
294
      Terminate_Task (Self_ID);
295
   end Task_Wrapper;
296
 
297
   -----------------------
298
   -- Restricted GNARLI --
299
   -----------------------
300
 
301
   -------------------------------
302
   -- Activate_Restricted_Tasks --
303
   -------------------------------
304
 
305
   --  Note that locks of activator and activated task are both locked here.
306
   --  This is necessary because C.State and Self.Wait_Count have to be
307
   --  synchronized. This is safe from deadlock because the activator is always
308
   --  created before the activated task. That satisfies our
309
   --  in-order-of-creation ATCB locking policy.
310
 
311
   procedure Activate_Restricted_Tasks
312
     (Chain_Access : Activation_Chain_Access)
313
   is
314
      Self_ID       : constant Task_Id := STPO.Self;
315
      C             : Task_Id;
316
      Activate_Prio : System.Any_Priority;
317
      Success       : Boolean;
318
 
319
   begin
320
      pragma Assert (Self_ID = Environment_Task);
321
      pragma Assert (Self_ID.Common.Wait_Count = 0);
322
 
323
      if Single_Lock then
324
         Lock_RTS;
325
      end if;
326
 
327
      --  Lock self, to prevent activated tasks from racing ahead before we
328
      --  finish activating the chain.
329
 
330
      Write_Lock (Self_ID);
331
 
332
      --  Activate all the tasks in the chain. Creation of the thread of
333
      --  control was deferred until activation. So create it now.
334
 
335
      C := Chain_Access.T_ID;
336
 
337
      while C /= null loop
338
         if C.Common.State /= Terminated then
339
            pragma Assert (C.Common.State = Unactivated);
340
 
341
            Write_Lock (C);
342
 
343
            Activate_Prio :=
344
              (if C.Common.Base_Priority < Get_Priority (Self_ID)
345
               then Get_Priority (Self_ID)
346
               else C.Common.Base_Priority);
347
 
348
            STPO.Create_Task
349
              (C, Task_Wrapper'Address,
350
               Parameters.Size_Type
351
                 (C.Common.Compiler_Data.Pri_Stack_Info.Size),
352
               Activate_Prio, Success);
353
 
354
            Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1;
355
 
356
            if Success then
357
               C.Common.State := Runnable;
358
            else
359
               raise Program_Error;
360
            end if;
361
 
362
            Unlock (C);
363
         end if;
364
 
365
         C := C.Common.Activation_Link;
366
      end loop;
367
 
368
      Self_ID.Common.State := Activator_Sleep;
369
 
370
      --  Wait for the activated tasks to complete activation. It is unsafe to
371
      --  abort any of these tasks until the count goes to zero.
372
 
373
      loop
374
         exit when Self_ID.Common.Wait_Count = 0;
375
         Sleep (Self_ID, Activator_Sleep);
376
      end loop;
377
 
378
      Self_ID.Common.State := Runnable;
379
      Unlock (Self_ID);
380
 
381
      if Single_Lock then
382
         Unlock_RTS;
383
      end if;
384
 
385
      --  Remove the tasks from the chain
386
 
387
      Chain_Access.T_ID := null;
388
   end Activate_Restricted_Tasks;
389
 
390
   ------------------------------------
391
   -- Complete_Restricted_Activation --
392
   ------------------------------------
393
 
394
   --  As in several other places, the locks of the activator and activated
395
   --  task are both locked here. This follows our deadlock prevention lock
396
   --  ordering policy, since the activated task must be created after the
397
   --  activator.
398
 
399
   procedure Complete_Restricted_Activation is
400
      Self_ID   : constant Task_Id := STPO.Self;
401
      Activator : constant Task_Id := Self_ID.Common.Activator;
402
 
403
   begin
404
      if Single_Lock then
405
         Lock_RTS;
406
      end if;
407
 
408
      Write_Lock (Activator);
409
      Write_Lock (Self_ID);
410
 
411
      --  Remove dangling reference to Activator, since a task may outlive its
412
      --  activator.
413
 
414
      Self_ID.Common.Activator := null;
415
 
416
      --  Wake up the activator, if it is waiting for a chain of tasks to
417
      --  activate, and we are the last in the chain to complete activation
418
 
419
      if Activator.Common.State = Activator_Sleep then
420
         Activator.Common.Wait_Count := Activator.Common.Wait_Count - 1;
421
 
422
         if Activator.Common.Wait_Count = 0 then
423
            Wakeup (Activator, Activator_Sleep);
424
         end if;
425
      end if;
426
 
427
      Unlock (Self_ID);
428
      Unlock (Activator);
429
 
430
      if Single_Lock then
431
         Unlock_RTS;
432
      end if;
433
 
434
      --  After the activation, active priority should be the same as base
435
      --  priority. We must unlock the Activator first, though, since it should
436
      --  not wait if we have lower priority.
437
 
438
      if Get_Priority (Self_ID) /= Self_ID.Common.Base_Priority then
439
         Set_Priority (Self_ID, Self_ID.Common.Base_Priority);
440
      end if;
441
   end Complete_Restricted_Activation;
442
 
443
   ------------------------------
444
   -- Complete_Restricted_Task --
445
   ------------------------------
446
 
447
   procedure Complete_Restricted_Task is
448
   begin
449
      STPO.Self.Common.State := Terminated;
450
   end Complete_Restricted_Task;
451
 
452
   ----------------------------
453
   -- Create_Restricted_Task --
454
   ----------------------------
455
 
456
   procedure Create_Restricted_Task
457
     (Priority      : Integer;
458
      Stack_Address : System.Address;
459
      Size          : System.Parameters.Size_Type;
460
      Task_Info     : System.Task_Info.Task_Info_Type;
461
      State         : Task_Procedure_Access;
462
      Discriminants : System.Address;
463
      Elaborated    : Access_Boolean;
464
      Chain         : in out Activation_Chain;
465
      Task_Image    : String;
466
      Created_Task  : Task_Id)
467
   is
468
      Self_ID       : constant Task_Id := STPO.Self;
469
      Base_Priority : System.Any_Priority;
470
      Success       : Boolean;
471
      Len           : Integer;
472
 
473
   begin
474
      --  Stack is not preallocated on this target, so that Stack_Address must
475
      --  be null.
476
 
477
      pragma Assert (Stack_Address = Null_Address);
478
 
479
      Base_Priority :=
480
        (if Priority = Unspecified_Priority
481
         then Self_ID.Common.Base_Priority
482
         else System.Any_Priority (Priority));
483
 
484
      if Single_Lock then
485
         Lock_RTS;
486
      end if;
487
 
488
      Write_Lock (Self_ID);
489
 
490
      --  With no task hierarchy, the parent of all non-Environment tasks that
491
      --  are created must be the Environment task
492
 
493
      Initialize_ATCB
494
        (Self_ID, State, Discriminants, Self_ID, Elaborated, Base_Priority,
495
         Task_Info, Size, Created_Task, Success);
496
 
497
      --  If we do our job right then there should never be any failures, which
498
      --  was probably said about the Titanic; so just to be safe, let's retain
499
      --  this code for now
500
 
501
      if not Success then
502
         Unlock (Self_ID);
503
 
504
         if Single_Lock then
505
            Unlock_RTS;
506
         end if;
507
 
508
         raise Program_Error;
509
      end if;
510
 
511
      Created_Task.Entry_Calls (1).Self := Created_Task;
512
 
513
      Len :=
514
        Integer'Min (Created_Task.Common.Task_Image'Length, Task_Image'Length);
515
      Created_Task.Common.Task_Image_Len := Len;
516
      Created_Task.Common.Task_Image (1 .. Len) :=
517
        Task_Image (Task_Image'First .. Task_Image'First + Len - 1);
518
 
519
      Unlock (Self_ID);
520
 
521
      if Single_Lock then
522
         Unlock_RTS;
523
      end if;
524
 
525
      --  Create TSD as early as possible in the creation of a task, since it
526
      --  may be used by the operation of Ada code within the task.
527
 
528
      SSL.Create_TSD (Created_Task.Common.Compiler_Data);
529
      Created_Task.Common.Activation_Link := Chain.T_ID;
530
      Chain.T_ID := Created_Task;
531
   end Create_Restricted_Task;
532
 
533
   ---------------------------
534
   -- Finalize_Global_Tasks --
535
   ---------------------------
536
 
537
   --  This is needed to support the compiler interface; it will only be called
538
   --  by the Environment task. Instead, it will cause the Environment to block
539
   --  forever, since none of the dependent tasks are expected to terminate
540
 
541
   procedure Finalize_Global_Tasks is
542
      Self_ID : constant Task_Id := STPO.Self;
543
 
544
   begin
545
      pragma Assert (Self_ID = STPO.Environment_Task);
546
 
547
      if Single_Lock then
548
         Lock_RTS;
549
      end if;
550
 
551
      --  Handle normal task termination by the environment task, but only for
552
      --  the normal task termination. In the case of Abnormal and
553
      --  Unhandled_Exception they must have been handled before, and the task
554
      --  termination soft link must have been changed so the task termination
555
      --  routine is not executed twice.
556
 
557
      --  Note that in the "normal" implementation in s-tassta.adb the task
558
      --  termination procedure for the environment task should be executed
559
      --  after termination of library-level tasks. However, this
560
      --  implementation is to be used when the Ravenscar restrictions are in
561
      --  effect, and AI-394 says that if there is a fall-back handler set for
562
      --  the partition it should be called when the first task (including the
563
      --  environment task) attempts to terminate.
564
 
565
      SSL.Task_Termination_Handler.all (Ada.Exceptions.Null_Occurrence);
566
 
567
      Write_Lock (Self_ID);
568
      Sleep (Self_ID, Master_Completion_Sleep);
569
      Unlock (Self_ID);
570
 
571
      if Single_Lock then
572
         Unlock_RTS;
573
      end if;
574
 
575
      --  Should never return from Master Completion Sleep
576
 
577
      raise Program_Error;
578
   end Finalize_Global_Tasks;
579
 
580
   ---------------------------
581
   -- Restricted_Terminated --
582
   ---------------------------
583
 
584
   function Restricted_Terminated (T : Task_Id) return Boolean is
585
   begin
586
      return T.Common.State = Terminated;
587
   end Restricted_Terminated;
588
 
589
   --------------------
590
   -- Terminate_Task --
591
   --------------------
592
 
593
   procedure Terminate_Task (Self_ID : Task_Id) is
594
   begin
595
      Self_ID.Common.State := Terminated;
596
   end Terminate_Task;
597
 
598
   --------------
599
   -- Init_RTS --
600
   --------------
601
 
602
   procedure Init_RTS is
603
   begin
604
      Tasking.Initialize;
605
 
606
      --  Initialize lock used to implement mutual exclusion between all tasks
607
 
608
      STPO.Initialize_Lock (Global_Task_Lock'Access, STPO.Global_Task_Level);
609
 
610
      --  Notify that the tasking run time has been elaborated so that
611
      --  the tasking version of the soft links can be used.
612
 
613
      SSL.Lock_Task         := Task_Lock'Access;
614
      SSL.Unlock_Task       := Task_Unlock'Access;
615
      SSL.Adafinal          := Finalize_Global_Tasks'Access;
616
      SSL.Get_Current_Excep := Get_Current_Excep'Access;
617
 
618
      --  Initialize the tasking soft links (if not done yet) that are common
619
      --  to the full and the restricted run times.
620
 
621
      SSL.Tasking.Init_Tasking_Soft_Links;
622
   end Init_RTS;
623
 
624
begin
625
   Init_RTS;
626
end System.Tasking.Restricted.Stages;

powered by: WebSVN 2.1.0

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