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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [a-tasatt.adb] - Blame information for rev 292

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

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                        GNAT RUN-TIME COMPONENTS                          --
4
--                                                                          --
5
--                  A D A . T A S K _ A T T R I B U T E S                   --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--             Copyright (C) 1991-1994, Florida State University            --
10
--                     Copyright (C) 1995-2009, AdaCore                     --
11
--                                                                          --
12
-- GNARL is free software; you can  redistribute it  and/or modify it under --
13
-- terms of the  GNU General Public License as published  by the Free Soft- --
14
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
15
-- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
16
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
17
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
18
-- for  more details.  You should have  received  a copy of the GNU General --
19
-- Public License  distributed with GNARL; see file COPYING.  If not, write --
20
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
21
-- Boston, MA 02110-1301, USA.                                              --
22
--                                                                          --
23
-- As a special exception,  if other files  instantiate  generics from this --
24
-- unit, or you link  this unit with other files  to produce an executable, --
25
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
26
-- covered  by the  GNU  General  Public  License.  This exception does not --
27
-- however invalidate  any other reasons why  the executable file  might be --
28
-- covered by the  GNU Public License.                                      --
29
--                                                                          --
30
-- GNARL was developed by the GNARL team at Florida State University.       --
31
-- Extensive contributions were provided by Ada Core Technologies, Inc.     --
32
--                                                                          --
33
------------------------------------------------------------------------------
34
 
35
--  The following notes are provided in case someone decides the implementation
36
--  of this package is too complicated, or too slow. Please read this before
37
--  making any "simplifications".
38
 
39
--  Correct implementation of this package is more difficult than one might
40
--  expect. After considering (and coding) several alternatives, we settled on
41
--  the present compromise. Things we do not like about this implementation
42
--  include:
43
 
44
--  - It is vulnerable to bad Task_Id values, to the extent of possibly
45
--    trashing memory and crashing the runtime system.
46
 
47
--  - It requires dynamic storage allocation for each new attribute value,
48
--    except for types that happen to be the same size as System.Address, or
49
--    shorter.
50
 
51
--  - Instantiations at other than the library level rely on being able to
52
--    do down-level calls to a procedure declared in the generic package body.
53
--    This makes it potentially vulnerable to compiler changes.
54
 
55
--  The main implementation issue here is that the connection from task to
56
--  attribute is a potential source of dangling references.
57
 
58
--  When a task goes away, we want to be able to recover all the storage
59
--  associated with its attributes. The Ada mechanism for this is finalization,
60
--  via controlled attribute types. For this reason, the ARM requires
61
--  finalization of attribute values when the associated task terminates.
62
 
63
--  This finalization must be triggered by the tasking runtime system, during
64
--  termination of the task. Given the active set of instantiations of
65
--  Ada.Task_Attributes is dynamic, the number and types of attributes
66
--  belonging to a task will not be known until the task actually terminates.
67
--  Some of these types may be controlled and some may not. The RTS must find
68
--  some way to determine which of these attributes need finalization, and
69
--  invoke the appropriate finalization on them.
70
 
71
--  One way this might be done is to create a special finalization chain for
72
--  each task, similar to the finalization chain that is used for controlled
73
--  objects within the task. This would differ from the usual finalization
74
--  chain in that it would not have a LIFO structure, since attributes may be
75
--  added to a task at any time during its lifetime. This might be the right
76
--  way to go for the longer term, but at present this approach is not open,
77
--  since GNAT does not provide such special finalization support.
78
 
79
--  Lacking special compiler support, the RTS is limited to the normal ways an
80
--  application invokes finalization, i.e.
81
 
82
--  a) Explicit call to the procedure Finalize, if we know the type has this
83
--     operation defined on it. This is not sufficient, since we have no way
84
--     of determining whether a given generic formal Attribute type is
85
--     controlled, and no visibility of the associated Finalize procedure, in
86
--     the generic body.
87
 
88
--  b) Leaving the scope of a local object of a controlled type. This does not
89
--     help, since the lifetime of an instantiation of Ada.Task_Attributes
90
--     does not correspond to the lifetimes of the various tasks which may
91
--     have that attribute.
92
 
93
--  c) Assignment of another value to the object. This would not help, since
94
--     we then have to finalize the new value of the object.
95
 
96
--  d) Unchecked deallocation of an object of a controlled type. This seems to
97
--     be the only mechanism available to the runtime system for finalization
98
--     of task attributes.
99
 
100
--  We considered two ways of using unchecked deallocation, both based on a
101
--  linked list of that would hang from the task control block.
102
 
103
--  In the first approach the objects on the attribute list are all derived
104
--  from one controlled type, say T, and are linked using an access type to
105
--  T'Class. The runtime system has an Ada.Unchecked_Deallocation for T'Class
106
--  with access type T'Class, and uses this to deallocate and finalize all the
107
--  items in the list. The limitation of this approach is that each
108
--  instantiation of the package Ada.Task_Attributes derives a new record
109
--  extension of T, and since T is controlled (RM 3.9.1 (3)), instantiation is
110
--  only allowed at the library level.
111
 
112
--  In the second approach the objects on the attribute list are of unrelated
113
--  but structurally similar types. Unchecked conversion is used to circument
114
--  Ada type checking. Each attribute-storage node contains not only the
115
--  attribute value and a link for chaining, but also a pointer to descriptor
116
--  for the corresponding instantiation of Task_Attributes. The instantiation
117
--  descriptor contains pointer to a procedure that can do the correct
118
--  deallocation and finalization for that type of attribute. On task
119
--  termination, the runtime system uses the pointer to call the appropriate
120
--  deallocator.
121
 
122
--  While this gets around the limitation that instantations be at the library
123
--  level, it relies on an implementation feature that may not always be safe,
124
--  i.e. that it is safe to call the Deallocate procedure for an instantiation
125
--  of Ada.Task_Attributes that no longer exists. In general, it seems this
126
--  might result in dangling references.
127
 
128
--  Another problem with instantiations deeper than the library level is that
129
--  there is risk of storage leakage, or dangling references to reused storage.
130
--  That is, if an instantiation of Ada.Task_Attributes is made within a
131
--  procedure, what happens to the storage allocated for attributes, when the
132
--  procedure call returns? Apparently (RM 7.6.1 (4)) any such objects must be
133
--  finalized, since they will no longer be accessible, and in general one
134
--  would expect that the storage they occupy would be recovered for later
135
--  reuse. (If not, we would have a case of storage leakage.) Assuming the
136
--  storage is recovered and later reused, we have potentially dangerous
137
--  dangling references. When the procedure containing the instantiation of
138
--  Ada.Task_Attributes returns, there may still be unterminated tasks with
139
--  associated attribute values for that instantiation. When such tasks
140
--  eventually terminate, the RTS will attempt to call the Deallocate procedure
141
--  on them. If the corresponding storage has already been deallocated, when
142
--  the master of the access type was left, we have a potential disaster. This
143
--  disaster is compounded since the pointer to Deallocate is probably through
144
--  a "trampoline" which will also have been destroyed.
145
 
146
--  For this reason, we arrange to remove all dangling references before
147
--  leaving the scope of an instantiation. This is ugly, since it requires
148
--  traversing the list of all tasks, but it is no more ugly than a similar
149
--  traversal that we must do at the point of instantiation in order to
150
--  initialize the attributes of all tasks. At least we only need to do these
151
--  traversals if the type is controlled.
152
 
153
--  We chose to defer allocation of storage for attributes until the Reference
154
--  function is called or the attribute is first set to a value different from
155
--  the default initial one. This allows a potential savings in allocation,
156
--  for attributes that are not used by all tasks.
157
 
158
--  For efficiency, we reserve space in the TCB for a fixed number of direct-
159
--  access attributes. These are required to be of a size that fits in the
160
--  space of an object of type System.Address. Because we must use unchecked
161
--  bitwise copy operations on these values, they cannot be of a controlled
162
--  type, but that is covered automatically since controlled objects are too
163
--  large to fit in the spaces.
164
 
165
--  We originally deferred initialization of these direct-access attributes,
166
--  just as we do for the indirect-access attributes, and used a per-task bit
167
--  vector to keep track of which attributes were currently defined for that
168
--  task. We found that the overhead of maintaining this bit-vector seriously
169
--  slowed down access to the attributes, and made the fetch operation non-
170
--  atomic, so that even to read an attribute value required locking the TCB.
171
--  Therefore, we now initialize such attributes for all existing tasks at the
172
--  time of the attribute instantiation, and initialize existing attributes for
173
--  each new task at the time it is created.
174
 
175
--  The latter initialization requires a list of all the instantiation
176
--  descriptors. Updates to this list, as well as the bit-vector that is used
177
--  to reserve slots for attributes in the TCB, require mutual exclusion. That
178
--  is provided by the Lock/Unlock_RTS.
179
 
180
--  One special problem that added complexity to the design is that the per-
181
--  task list of indirect attributes contains objects of different types. We
182
--  use unchecked pointer conversion to link these nodes together and access
183
--  them, but the records may not have identical internal structure. Initially,
184
--  we thought it would be enough to allocate all the common components of
185
--  the records at the front of each record, so that their positions would
186
--  correspond. Unfortunately, GNAT adds "dope" information at the front
187
--  of a record, if the record contains any controlled-type components.
188
--
189
--  This means that the offset of the fields we use to link the nodes is at
190
--  different positions on nodes of different types. To get around this, each
191
--  attribute storage record consists of a core node and wrapper. The core
192
--  nodes are all of the same type, and it is these that are linked together
193
--  and generally "seen" by the RTS. Each core node contains a pointer to its
194
--  own wrapper, which is a record that contains the core node along with an
195
--  attribute value, approximately as follows:
196
 
197
--    type Node;
198
--    type Node_Access is access all Node;
199
--    type Wrapper;
200
--    type Access_Wrapper is access all Wrapper;
201
--    type Node is record
202
--       Next    : Node_Access;
203
--       ...
204
--       Wrapper : Access_Wrapper;
205
--    end record;
206
--    type Wrapper is record
207
--       Dummy_Node : aliased Node;
208
--       Value      : aliased Attribute;  --  the generic formal type
209
--    end record;
210
 
211
--  Another interesting problem is with the initialization of the instantiation
212
--  descriptors. Originally, we did this all via the Initialize procedure of
213
--  the descriptor type and code in the package body. It turned out that the
214
--  Initialize procedure needed quite a bit of information, including the size
215
--  of the attribute type, the initial value of the attribute (if it fits in
216
--  the TCB), and a pointer to the deallocator procedure. These needed to be
217
--  "passed" in via access discriminants. GNAT was having trouble with access
218
--  discriminants, so all this work was moved to the package body.
219
 
220
--  Note that references to objects declared in this package body must in
221
--  general use 'Unchecked_Access instead of 'Access as the package can be
222
--  instantiated from within a local context.
223
 
224
with System.Storage_Elements;
225
with System.Task_Primitives.Operations;
226
with System.Tasking;
227
with System.Tasking.Initialization;
228
with System.Tasking.Task_Attributes;
229
 
230
with Ada.Exceptions;
231
with Ada.Unchecked_Conversion;
232
with Ada.Unchecked_Deallocation;
233
 
234
pragma Elaborate_All (System.Tasking.Task_Attributes);
235
--  To ensure the initialization of object Local (below) will work
236
 
237
package body Ada.Task_Attributes is
238
 
239
   use System.Tasking.Initialization,
240
       System.Tasking,
241
       System.Tasking.Task_Attributes,
242
       Ada.Exceptions;
243
 
244
   package POP renames System.Task_Primitives.Operations;
245
 
246
   ---------------------------
247
   -- Unchecked Conversions --
248
   ---------------------------
249
 
250
   --  The following type corresponds to Dummy_Wrapper, declared in
251
   --  System.Tasking.Task_Attributes.
252
 
253
   type Wrapper;
254
   type Access_Wrapper is access all Wrapper;
255
 
256
   pragma Warnings (Off);
257
   --  We turn warnings off for the following To_Attribute_Handle conversions,
258
   --  since these are used only for small attributes where we know that there
259
   --  are no problems with alignment, but the compiler will generate warnings
260
   --  for the occurrences in the large attribute case, even though they will
261
   --  not actually be used.
262
 
263
   function To_Attribute_Handle is new Ada.Unchecked_Conversion
264
     (System.Address, Attribute_Handle);
265
   function To_Direct_Attribute_Element is new Ada.Unchecked_Conversion
266
     (System.Address, Direct_Attribute_Element);
267
   --  For reference to directly addressed task attributes
268
 
269
   type Access_Integer_Address is access all
270
     System.Storage_Elements.Integer_Address;
271
 
272
   function To_Attribute_Handle is new Ada.Unchecked_Conversion
273
     (Access_Integer_Address, Attribute_Handle);
274
   --  For reference to directly addressed task attributes
275
 
276
   pragma Warnings (On);
277
   --  End warnings off region for directly addressed attribute conversions
278
 
279
   function To_Access_Address is new Ada.Unchecked_Conversion
280
     (Access_Node, Access_Address);
281
   --  To store pointer to list of indirect attributes
282
 
283
   pragma Warnings (Off);
284
   function To_Access_Wrapper is new Ada.Unchecked_Conversion
285
     (Access_Dummy_Wrapper, Access_Wrapper);
286
   pragma Warnings (On);
287
   --  To fetch pointer to actual wrapper of attribute node. We turn off
288
   --  warnings since this may generate an alignment warning. The warning can
289
   --  be ignored since Dummy_Wrapper is only a non-generic standin for the
290
   --  real wrapper type (we never actually allocate objects of type
291
   --  Dummy_Wrapper).
292
 
293
   function To_Access_Dummy_Wrapper is new Ada.Unchecked_Conversion
294
     (Access_Wrapper, Access_Dummy_Wrapper);
295
   --  To store pointer to actual wrapper of attribute node
296
 
297
   function To_Task_Id is new Ada.Unchecked_Conversion
298
     (Task_Identification.Task_Id, Task_Id);
299
   --  To access TCB of identified task
300
 
301
   type Local_Deallocator is access procedure (P : in out Access_Node);
302
 
303
   function To_Lib_Level_Deallocator is new Ada.Unchecked_Conversion
304
     (Local_Deallocator, Deallocator);
305
   --  To defeat accessibility check
306
 
307
   ------------------------
308
   -- Storage Management --
309
   ------------------------
310
 
311
   procedure Deallocate (P : in out Access_Node);
312
   --  Passed to the RTS via unchecked conversion of a pointer to permit
313
   --  finalization and deallocation of attribute storage nodes.
314
 
315
   --------------------------
316
   -- Instantiation Record --
317
   --------------------------
318
 
319
   Local : aliased Instance;
320
   --  Initialized in package body
321
 
322
   type Wrapper is record
323
      Dummy_Node : aliased Node;
324
 
325
      Value : aliased Attribute := Initial_Value;
326
      --  The generic formal type, may be controlled
327
   end record;
328
 
329
   --  A number of unchecked conversions involving Wrapper_Access sources are
330
   --  performed in this unit. We have to ensure that the designated object is
331
   --  always strictly enough aligned.
332
 
333
   for Wrapper'Alignment use Standard'Maximum_Alignment;
334
 
335
   procedure Free is
336
      new Ada.Unchecked_Deallocation (Wrapper, Access_Wrapper);
337
 
338
   procedure Deallocate (P : in out Access_Node) is
339
      T : Access_Wrapper := To_Access_Wrapper (P.Wrapper);
340
   begin
341
      Free (T);
342
   end Deallocate;
343
 
344
   ---------------
345
   -- Reference --
346
   ---------------
347
 
348
   function Reference
349
     (T    : Task_Identification.Task_Id := Task_Identification.Current_Task)
350
      return Attribute_Handle
351
   is
352
      TT            : constant Task_Id := To_Task_Id (T);
353
      Error_Message : constant String  := "Trying to get the reference of a ";
354
 
355
   begin
356
      if TT = null then
357
         Raise_Exception (Program_Error'Identity, Error_Message & "null task");
358
      end if;
359
 
360
      if TT.Common.State = Terminated then
361
         Raise_Exception (Tasking_Error'Identity,
362
           Error_Message & "terminated task");
363
      end if;
364
 
365
      --  Directly addressed case
366
 
367
      if Local.Index /= 0 then
368
 
369
         --  Return the attribute handle. Warnings off because this return
370
         --  statement generates alignment warnings for large attributes
371
         --  (but will never be executed in this case anyway).
372
 
373
         pragma Warnings (Off);
374
         return
375
           To_Attribute_Handle (TT.Direct_Attributes (Local.Index)'Address);
376
         pragma Warnings (On);
377
 
378
      --  Not directly addressed
379
 
380
      else
381
         declare
382
            P       : Access_Node := To_Access_Node (TT.Indirect_Attributes);
383
            W       : Access_Wrapper;
384
            Self_Id : constant Task_Id := POP.Self;
385
 
386
         begin
387
            Defer_Abort (Self_Id);
388
            POP.Lock_RTS;
389
 
390
            while P /= null loop
391
               if P.Instance = Access_Instance'(Local'Unchecked_Access) then
392
                  POP.Unlock_RTS;
393
                  Undefer_Abort (Self_Id);
394
                  return To_Access_Wrapper (P.Wrapper).Value'Access;
395
               end if;
396
 
397
               P := P.Next;
398
            end loop;
399
 
400
            --  Unlock the RTS here to follow the lock ordering rule that
401
            --  prevent us from using new (i.e the Global_Lock) while holding
402
            --  any other lock.
403
 
404
            POP.Unlock_RTS;
405
            W := new Wrapper'
406
                  ((null, Local'Unchecked_Access, null), Initial_Value);
407
            POP.Lock_RTS;
408
 
409
            P := W.Dummy_Node'Unchecked_Access;
410
            P.Wrapper := To_Access_Dummy_Wrapper (W);
411
            P.Next := To_Access_Node (TT.Indirect_Attributes);
412
            TT.Indirect_Attributes := To_Access_Address (P);
413
            POP.Unlock_RTS;
414
            Undefer_Abort (Self_Id);
415
            return W.Value'Access;
416
 
417
         exception
418
            when others =>
419
               POP.Unlock_RTS;
420
               Undefer_Abort (Self_Id);
421
               raise;
422
         end;
423
      end if;
424
 
425
   exception
426
      when Tasking_Error | Program_Error =>
427
         raise;
428
 
429
      when others =>
430
         raise Program_Error;
431
   end Reference;
432
 
433
   ------------------
434
   -- Reinitialize --
435
   ------------------
436
 
437
   procedure Reinitialize
438
     (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
439
   is
440
      TT            : constant Task_Id := To_Task_Id (T);
441
      Error_Message : constant String  := "Trying to Reinitialize a ";
442
 
443
   begin
444
      if TT = null then
445
         Raise_Exception (Program_Error'Identity, Error_Message & "null task");
446
      end if;
447
 
448
      if TT.Common.State = Terminated then
449
         Raise_Exception (Tasking_Error'Identity,
450
           Error_Message & "terminated task");
451
      end if;
452
 
453
      if Local.Index /= 0 then
454
         Set_Value (Initial_Value, T);
455
      else
456
         declare
457
            P, Q    : Access_Node;
458
            W       : Access_Wrapper;
459
            Self_Id : constant Task_Id := POP.Self;
460
 
461
         begin
462
            Defer_Abort (Self_Id);
463
            POP.Lock_RTS;
464
            Q := To_Access_Node (TT.Indirect_Attributes);
465
 
466
            while Q /= null loop
467
               if Q.Instance = Access_Instance'(Local'Unchecked_Access) then
468
                  if P = null then
469
                     TT.Indirect_Attributes := To_Access_Address (Q.Next);
470
                  else
471
                     P.Next := Q.Next;
472
                  end if;
473
 
474
                  W := To_Access_Wrapper (Q.Wrapper);
475
                  Free (W);
476
                  POP.Unlock_RTS;
477
                  Undefer_Abort (Self_Id);
478
                  return;
479
               end if;
480
 
481
               P := Q;
482
               Q := Q.Next;
483
            end loop;
484
 
485
            POP.Unlock_RTS;
486
            Undefer_Abort (Self_Id);
487
 
488
         exception
489
            when others =>
490
               POP.Unlock_RTS;
491
               Undefer_Abort (Self_Id);
492
               raise;
493
         end;
494
      end if;
495
 
496
   exception
497
      when Tasking_Error | Program_Error =>
498
         raise;
499
 
500
      when others =>
501
         raise Program_Error;
502
   end Reinitialize;
503
 
504
   ---------------
505
   -- Set_Value --
506
   ---------------
507
 
508
   procedure Set_Value
509
     (Val : Attribute;
510
      T   : Task_Identification.Task_Id := Task_Identification.Current_Task)
511
   is
512
      TT            : constant Task_Id := To_Task_Id (T);
513
      Error_Message : constant String  := "Trying to Set the Value of a ";
514
 
515
   begin
516
      if TT = null then
517
         Raise_Exception (Program_Error'Identity, Error_Message & "null task");
518
      end if;
519
 
520
      if TT.Common.State = Terminated then
521
         Raise_Exception (Tasking_Error'Identity,
522
           Error_Message & "terminated task");
523
      end if;
524
 
525
      --  Directly addressed case
526
 
527
      if Local.Index /= 0 then
528
 
529
         --  Set attribute handle, warnings off, because this code can generate
530
         --  alignment warnings with large attributes (but of course will not
531
         --  be executed in this case, since we never have direct addressing in
532
         --  such cases).
533
 
534
         pragma Warnings (Off);
535
         To_Attribute_Handle
536
            (TT.Direct_Attributes (Local.Index)'Address).all := Val;
537
         pragma Warnings (On);
538
         return;
539
      end if;
540
 
541
      --  Not directly addressed
542
 
543
      declare
544
         P       : Access_Node := To_Access_Node (TT.Indirect_Attributes);
545
         W       : Access_Wrapper;
546
         Self_Id : constant Task_Id := POP.Self;
547
 
548
      begin
549
         Defer_Abort (Self_Id);
550
         POP.Lock_RTS;
551
 
552
         while P /= null loop
553
 
554
            if P.Instance = Access_Instance'(Local'Unchecked_Access) then
555
               To_Access_Wrapper (P.Wrapper).Value := Val;
556
               POP.Unlock_RTS;
557
               Undefer_Abort (Self_Id);
558
               return;
559
            end if;
560
 
561
            P := P.Next;
562
         end loop;
563
 
564
         --  Unlock RTS here to follow the lock ordering rule that prevent us
565
         --  from using new (i.e the Global_Lock) while holding any other lock.
566
 
567
         POP.Unlock_RTS;
568
         W := new Wrapper'((null, Local'Unchecked_Access, null), Val);
569
         POP.Lock_RTS;
570
         P := W.Dummy_Node'Unchecked_Access;
571
         P.Wrapper := To_Access_Dummy_Wrapper (W);
572
         P.Next := To_Access_Node (TT.Indirect_Attributes);
573
         TT.Indirect_Attributes := To_Access_Address (P);
574
 
575
         POP.Unlock_RTS;
576
         Undefer_Abort (Self_Id);
577
 
578
      exception
579
         when others =>
580
            POP.Unlock_RTS;
581
            Undefer_Abort (Self_Id);
582
            raise;
583
      end;
584
 
585
   exception
586
      when Tasking_Error | Program_Error =>
587
         raise;
588
 
589
      when others =>
590
         raise Program_Error;
591
   end Set_Value;
592
 
593
   -----------
594
   -- Value --
595
   -----------
596
 
597
   function Value
598
     (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
599
      return Attribute
600
   is
601
      TT            : constant Task_Id := To_Task_Id (T);
602
      Error_Message : constant String  := "Trying to get the Value of a ";
603
 
604
   begin
605
      if TT = null then
606
         Raise_Exception (Program_Error'Identity, Error_Message & "null task");
607
      end if;
608
 
609
      if TT.Common.State = Terminated then
610
         Raise_Exception
611
           (Program_Error'Identity, Error_Message & "terminated task");
612
      end if;
613
 
614
      --  Directly addressed case
615
 
616
      if Local.Index /= 0 then
617
 
618
         --  Get value of attribute. We turn Warnings off, because for large
619
         --  attributes, this code can generate alignment warnings. But of
620
         --  course large attributes are never directly addressed so in fact
621
         --  we will never execute the code in this case.
622
 
623
         pragma Warnings (Off);
624
         return To_Attribute_Handle
625
           (TT.Direct_Attributes (Local.Index)'Address).all;
626
         pragma Warnings (On);
627
      end if;
628
 
629
      --  Not directly addressed
630
 
631
      declare
632
         P       : Access_Node;
633
         Result  : Attribute;
634
         Self_Id : constant Task_Id := POP.Self;
635
 
636
      begin
637
         Defer_Abort (Self_Id);
638
         POP.Lock_RTS;
639
         P := To_Access_Node (TT.Indirect_Attributes);
640
 
641
         while P /= null loop
642
            if P.Instance = Access_Instance'(Local'Unchecked_Access) then
643
               Result := To_Access_Wrapper (P.Wrapper).Value;
644
               POP.Unlock_RTS;
645
               Undefer_Abort (Self_Id);
646
               return Result;
647
            end if;
648
 
649
            P := P.Next;
650
         end loop;
651
 
652
         POP.Unlock_RTS;
653
         Undefer_Abort (Self_Id);
654
         return Initial_Value;
655
 
656
      exception
657
         when others =>
658
            POP.Unlock_RTS;
659
            Undefer_Abort (Self_Id);
660
            raise;
661
      end;
662
 
663
   exception
664
      when Tasking_Error | Program_Error =>
665
         raise;
666
 
667
      when others =>
668
         raise Program_Error;
669
   end Value;
670
 
671
--  Start of elaboration code for package Ada.Task_Attributes
672
 
673
begin
674
   --  This unchecked conversion can give warnings when alignments are
675
   --  incorrect, but they will not be used in such cases anyway, so the
676
   --  warnings can be safely ignored.
677
 
678
   pragma Warnings (Off);
679
   Local.Deallocate := To_Lib_Level_Deallocator (Deallocate'Access);
680
   pragma Warnings (On);
681
 
682
   declare
683
      Two_To_J : Direct_Index_Vector;
684
      Self_Id  : constant Task_Id := POP.Self;
685
   begin
686
      Defer_Abort (Self_Id);
687
 
688
      --  Need protection for updating links to per-task initialization and
689
      --  finalization routines, in case some task is being created or
690
      --  terminated concurrently.
691
 
692
      POP.Lock_RTS;
693
 
694
      --  Add this instantiation to the list of all instantiations
695
 
696
      Local.Next := System.Tasking.Task_Attributes.All_Attributes;
697
      System.Tasking.Task_Attributes.All_Attributes :=
698
        Local'Unchecked_Access;
699
 
700
      --  Try to find space for the attribute in the TCB
701
 
702
      Local.Index := 0;
703
      Two_To_J := 1;
704
 
705
      if Attribute'Size <= System.Address'Size then
706
         for J in Direct_Index_Range loop
707
            if (Two_To_J and In_Use) = 0 then
708
 
709
               --  Reserve location J for this attribute
710
 
711
               In_Use := In_Use or Two_To_J;
712
               Local.Index := J;
713
 
714
               --  This unchecked conversion can give a warning when the
715
               --  alignment is incorrect, but it will not be used in such
716
               --  a case anyway, so the warning can be safely ignored.
717
 
718
               pragma Warnings (Off);
719
               To_Attribute_Handle (Local.Initial_Value'Access).all :=
720
                 Initial_Value;
721
               pragma Warnings (On);
722
 
723
               exit;
724
            end if;
725
 
726
            Two_To_J := Two_To_J * 2;
727
         end loop;
728
      end if;
729
 
730
      --  Attribute goes directly in the TCB
731
 
732
      if Local.Index /= 0 then
733
         --  Replace stub for initialization routine that is called at task
734
         --  creation.
735
 
736
         Initialization.Initialize_Attributes_Link :=
737
           System.Tasking.Task_Attributes.Initialize_Attributes'Access;
738
 
739
         --  Initialize the attribute, for all tasks
740
 
741
         declare
742
            C : System.Tasking.Task_Id := System.Tasking.All_Tasks_List;
743
         begin
744
            while C /= null loop
745
               C.Direct_Attributes (Local.Index) :=
746
                 To_Direct_Attribute_Element
747
                   (System.Storage_Elements.To_Address (Local.Initial_Value));
748
               C := C.Common.All_Tasks_Link;
749
            end loop;
750
         end;
751
 
752
      --  Attribute goes into a node onto a linked list
753
 
754
      else
755
         --  Replace stub for finalization routine called at task termination
756
 
757
         Initialization.Finalize_Attributes_Link :=
758
           System.Tasking.Task_Attributes.Finalize_Attributes'Access;
759
      end if;
760
 
761
      POP.Unlock_RTS;
762
      Undefer_Abort (Self_Id);
763
   end;
764
end Ada.Task_Attributes;

powered by: WebSVN 2.1.0

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