1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . T A S K _ A T T R I B U T E S --
9 -- Copyright (C) 2014, Free Software Foundation, Inc. --
11 -- GNAT 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. --
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. --
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/>. --
27 -- GNARL was developed by the GNARL team at Florida State University. --
28 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
30 ------------------------------------------------------------------------------
33 with System
.Tasking
.Initialization
;
34 with System
.Tasking
.Task_Attributes
;
35 pragma Elaborate_All
(System
.Tasking
.Task_Attributes
);
37 with System
.Task_Primitives
.Operations
;
39 with Ada
.Finalization
; use Ada
.Finalization
;
40 with Ada
.Unchecked_Conversion
;
41 with Ada
.Unchecked_Deallocation
;
43 package body Ada
.Task_Attributes
is
46 System
.Tasking
.Initialization
,
48 System
.Tasking
.Task_Attributes
;
50 package STPO
renames System
.Task_Primitives
.Operations
;
52 type Attribute_Cleanup
is new Limited_Controlled
with null record;
53 procedure Finalize
(Cleanup
: in out Attribute_Cleanup
);
54 -- Finalize all tasks' attributes for this package
56 Cleanup
: Attribute_Cleanup
;
57 pragma Unreferenced
(Cleanup
);
58 -- Will call Finalize when this instantiation gets out of scope
60 ---------------------------
61 -- Unchecked Conversions --
62 ---------------------------
64 type Real_Attribute
is record
68 type Real_Attribute_Access
is access all Real_Attribute
;
69 pragma No_Strict_Aliasing
(Real_Attribute_Access
);
70 -- Each value in the task control block's Attributes array is either
71 -- mapped to the attribute value directly if Fast_Path is True, or
72 -- is in effect a Real_Attribute_Access.
74 -- Note: the Deallocator field must be first, for compatibility with
75 -- System.Tasking.Task_Attributes.Attribute_Record and to allow unchecked
76 -- conversions between Attribute_Access and Real_Attribute_Access.
78 function New_Attribute
(Val
: Attribute
) return Atomic_Address
;
79 -- Create a new Real_Attribute using Val, and return its address. The
80 -- returned value can be converted via To_Real_Attribute.
82 procedure Deallocate
(Ptr
: Atomic_Address
);
83 -- Free memory associated with Ptr, a Real_Attribute_Access in reality
85 function To_Real_Attribute
is new
86 Ada
.Unchecked_Conversion
(Atomic_Address
, Real_Attribute_Access
);
88 pragma Warnings
(Off
);
89 -- Kill warning about possible size mismatch
91 function To_Address
is new
92 Ada
.Unchecked_Conversion
(Attribute
, Atomic_Address
);
93 function To_Attribute
is new
94 Ada
.Unchecked_Conversion
(Atomic_Address
, Attribute
);
98 function To_Address
is new
99 Ada
.Unchecked_Conversion
(Real_Attribute_Access
, Atomic_Address
);
101 pragma Warnings
(Off
);
102 -- Kill warning about possible aliasing
104 function To_Handle
is new
105 Ada
.Unchecked_Conversion
(System
.Address
, Attribute_Handle
);
107 pragma Warnings
(On
);
109 function To_Task_Id
is new
110 Ada
.Unchecked_Conversion
(Task_Identification
.Task_Id
, Task_Id
);
111 -- To access TCB of identified task
113 procedure Free
is new
114 Ada
.Unchecked_Deallocation
(Real_Attribute
, Real_Attribute_Access
);
116 Fast_Path
: constant Boolean :=
117 Attribute
'Size <= Atomic_Address
'Size
118 and then Attribute
'Alignment <= Atomic_Address
'Alignment
119 and then To_Address
(Initial_Value
) = 0;
120 -- If the attribute fits in an Atomic_Address (both size and alignment)
121 -- and Initial_Value is 0 (or null), then we will map the attribute
122 -- directly into ATCB.Attributes (Index), otherwise we will create
123 -- a level of indirection and instead use Attributes (Index) as a
124 -- Real_Attribute_Access.
126 Index
: constant Integer :=
127 Next_Index
(Require_Finalization
=> not Fast_Path
);
128 -- Index in the task control block's Attributes array
134 procedure Finalize
(Cleanup
: in out Attribute_Cleanup
) is
135 pragma Unreferenced
(Cleanup
);
141 C
: System
.Tasking
.Task_Id
:= System
.Tasking
.All_Tasks_List
;
147 if C
.Attributes
(Index
) /= 0
148 and then Require_Finalization
(Index
)
150 Deallocate
(C
.Attributes
(Index
));
151 C
.Attributes
(Index
) := 0;
155 C
:= C
.Common
.All_Tasks_Link
;
167 procedure Deallocate
(Ptr
: Atomic_Address
) is
168 Obj
: Real_Attribute_Access
:= To_Real_Attribute
(Ptr
);
177 function New_Attribute
(Val
: Attribute
) return Atomic_Address
is
178 Tmp
: Real_Attribute_Access
;
180 Tmp
:= new Real_Attribute
'(Free => Deallocate'Unrestricted_Access,
182 return To_Address (Tmp);
190 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
191 return Attribute_Handle
194 TT : constant Task_Id := To_Task_Id (T);
195 Error_Message : constant String := "trying to get the reference of a ";
196 Result : Attribute_Handle;
200 raise Program_Error with Error_Message & "null task";
203 if TT.Common.State = Terminated then
204 raise Tasking_Error with Error_Message & "terminated task";
208 -- Kill warning about possible alignment mismatch. If this happens,
209 -- Fast_Path will be False anyway
210 pragma Warnings (Off);
211 return To_Handle (TT.Attributes (Index)'Address);
212 pragma Warnings (On);
214 Self_Id := STPO.Self;
217 if TT.Attributes (Index) = 0 then
218 TT.Attributes (Index) := New_Attribute (Initial_Value);
222 (To_Real_Attribute (TT.Attributes (Index)).Value'Address);
223 Task_Unlock (Self_Id);
233 procedure Reinitialize
234 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
237 TT : constant Task_Id := To_Task_Id (T);
238 Error_Message : constant String := "Trying to Reinitialize a ";
242 raise Program_Error with Error_Message & "null task";
245 if TT.Common.State = Terminated then
246 raise Tasking_Error with Error_Message & "terminated task";
251 -- No finalization needed, simply reset to Initial_Value
253 TT.Attributes (Index) := To_Address (Initial_Value);
256 Self_Id := STPO.Self;
260 Attr : Atomic_Address renames TT.Attributes (Index);
268 Task_Unlock (Self_Id);
278 T : Task_Identification.Task_Id := Task_Identification.Current_Task)
281 TT : constant Task_Id := To_Task_Id (T);
282 Error_Message : constant String := "trying to set the value of a ";
286 raise Program_Error with Error_Message & "null task";
289 if TT.Common.State = Terminated then
290 raise Tasking_Error with Error_Message & "terminated task";
295 -- No finalization needed, simply set to Val
297 TT.Attributes (Index) := To_Address (Val);
300 Self_Id := STPO.Self;
304 Attr : Atomic_Address renames TT.Attributes (Index);
311 Attr := New_Attribute (Val);
314 Task_Unlock (Self_Id);
323 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
327 TT : constant Task_Id := To_Task_Id (T);
328 Error_Message : constant String := "trying to get the value of a ";
332 raise Program_Error with Error_Message & "null task";
335 if TT.Common.State = Terminated then
336 raise Tasking_Error with Error_Message & "terminated task";
340 return To_Attribute (TT.Attributes (Index));
343 Self_Id := STPO.Self;
347 Attr : Atomic_Address renames TT.Attributes (Index);
351 Task_Unlock (Self_Id);
352 return Initial_Value;
356 Result : constant Attribute :=
357 To_Real_Attribute (Attr).Value;
359 Task_Unlock (Self_Id);
367 end Ada.Task_Attributes;