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-2016, 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
);
96 type Unsigned
is mod 2 ** Integer'Size;
97 function To_Address
is new
98 Ada
.Unchecked_Conversion
(Attribute
, System
.Address
);
99 function To_Unsigned
is new
100 Ada
.Unchecked_Conversion
(Attribute
, Unsigned
);
102 pragma Warnings
(On
);
104 function To_Address
is new
105 Ada
.Unchecked_Conversion
(Real_Attribute_Access
, Atomic_Address
);
107 pragma Warnings
(Off
);
108 -- Kill warning about possible aliasing
110 function To_Handle
is new
111 Ada
.Unchecked_Conversion
(System
.Address
, Attribute_Handle
);
113 pragma Warnings
(On
);
115 function To_Task_Id
is new
116 Ada
.Unchecked_Conversion
(Task_Identification
.Task_Id
, Task_Id
);
117 -- To access TCB of identified task
119 procedure Free
is new
120 Ada
.Unchecked_Deallocation
(Real_Attribute
, Real_Attribute_Access
);
122 Fast_Path
: constant Boolean :=
123 (Attribute
'Size = Integer'Size
124 and then Attribute
'Alignment <= Atomic_Address
'Alignment
125 and then To_Unsigned
(Initial_Value
) = 0)
126 or else (Attribute
'Size = System
.Address
'Size
127 and then Attribute
'Alignment <= Atomic_Address
'Alignment
128 and then To_Address
(Initial_Value
) = System
.Null_Address
);
129 -- If the attribute fits in an Atomic_Address (both size and alignment)
130 -- and Initial_Value is 0 (or null), then we will map the attribute
131 -- directly into ATCB.Attributes (Index), otherwise we will create
132 -- a level of indirection and instead use Attributes (Index) as a
133 -- Real_Attribute_Access.
135 Index
: constant Integer :=
136 Next_Index
(Require_Finalization
=> not Fast_Path
);
137 -- Index in the task control block's Attributes array
143 procedure Finalize
(Cleanup
: in out Attribute_Cleanup
) is
144 pragma Unreferenced
(Cleanup
);
150 C
: System
.Tasking
.Task_Id
:= System
.Tasking
.All_Tasks_List
;
156 if C
.Attributes
(Index
) /= 0
157 and then Require_Finalization
(Index
)
159 Deallocate
(C
.Attributes
(Index
));
160 C
.Attributes
(Index
) := 0;
164 C
:= C
.Common
.All_Tasks_Link
;
176 procedure Deallocate
(Ptr
: Atomic_Address
) is
177 Obj
: Real_Attribute_Access
:= To_Real_Attribute
(Ptr
);
186 function New_Attribute
(Val
: Attribute
) return Atomic_Address
is
187 Tmp
: Real_Attribute_Access
;
189 Tmp
:= new Real_Attribute
'(Free => Deallocate'Unrestricted_Access,
191 return To_Address (Tmp);
199 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
200 return Attribute_Handle
203 TT : constant Task_Id := To_Task_Id (T);
204 Error_Message : constant String := "trying to get the reference of a ";
205 Result : Attribute_Handle;
209 raise Program_Error with Error_Message & "null task";
212 if TT.Common.State = Terminated then
213 raise Tasking_Error with Error_Message & "terminated task";
217 -- Kill warning about possible alignment mismatch. If this happens,
218 -- Fast_Path will be False anyway
219 pragma Warnings (Off);
220 return To_Handle (TT.Attributes (Index)'Address);
221 pragma Warnings (On);
223 Self_Id := STPO.Self;
226 if TT.Attributes (Index) = 0 then
227 TT.Attributes (Index) := New_Attribute (Initial_Value);
231 (To_Real_Attribute (TT.Attributes (Index)).Value'Address);
232 Task_Unlock (Self_Id);
242 procedure Reinitialize
243 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
246 TT : constant Task_Id := To_Task_Id (T);
247 Error_Message : constant String := "Trying to Reinitialize a ";
251 raise Program_Error with Error_Message & "null task";
254 if TT.Common.State = Terminated then
255 raise Tasking_Error with Error_Message & "terminated task";
260 -- No finalization needed, simply reset to Initial_Value
262 TT.Attributes (Index) := To_Address (Initial_Value);
265 Self_Id := STPO.Self;
269 Attr : Atomic_Address renames TT.Attributes (Index);
277 Task_Unlock (Self_Id);
287 T : Task_Identification.Task_Id := Task_Identification.Current_Task)
290 TT : constant Task_Id := To_Task_Id (T);
291 Error_Message : constant String := "trying to set the value of a ";
295 raise Program_Error with Error_Message & "null task";
298 if TT.Common.State = Terminated then
299 raise Tasking_Error with Error_Message & "terminated task";
304 -- No finalization needed, simply set to Val
306 if Attribute'Size = Integer'Size then
307 TT.Attributes (Index) := Atomic_Address (To_Unsigned (Val));
309 TT.Attributes (Index) := To_Address (Val);
313 Self_Id := STPO.Self;
317 Attr : Atomic_Address renames TT.Attributes (Index);
324 Attr := New_Attribute (Val);
327 Task_Unlock (Self_Id);
336 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
340 TT : constant Task_Id := To_Task_Id (T);
341 Error_Message : constant String := "trying to get the value of a ";
345 raise Program_Error with Error_Message & "null task";
348 if TT.Common.State = Terminated then
349 raise Tasking_Error with Error_Message & "terminated task";
353 return To_Attribute (TT.Attributes (Index));
356 Self_Id := STPO.Self;
360 Attr : Atomic_Address renames TT.Attributes (Index);
364 Task_Unlock (Self_Id);
365 return Initial_Value;
369 Result : constant Attribute :=
370 To_Real_Attribute (Attr).Value;
372 Task_Unlock (Self_Id);
380 end Ada.Task_Attributes;