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 function To_Address
is new
97 Ada
.Unchecked_Conversion
(Attribute
, System
.Address
);
98 function To_Int
is new
99 Ada
.Unchecked_Conversion
(Attribute
, Integer);
101 pragma Warnings
(On
);
103 function To_Address
is new
104 Ada
.Unchecked_Conversion
(Real_Attribute_Access
, Atomic_Address
);
106 pragma Warnings
(Off
);
107 -- Kill warning about possible aliasing
109 function To_Handle
is new
110 Ada
.Unchecked_Conversion
(System
.Address
, Attribute_Handle
);
112 pragma Warnings
(On
);
114 function To_Task_Id
is new
115 Ada
.Unchecked_Conversion
(Task_Identification
.Task_Id
, Task_Id
);
116 -- To access TCB of identified task
118 procedure Free
is new
119 Ada
.Unchecked_Deallocation
(Real_Attribute
, Real_Attribute_Access
);
121 Fast_Path
: constant Boolean :=
122 (Attribute
'Size = Integer'Size
123 and then Attribute
'Alignment <= Atomic_Address
'Alignment
124 and then To_Int
(Initial_Value
) = 0)
125 or else (Attribute
'Size = System
.Address
'Size
126 and then Attribute
'Alignment <= Atomic_Address
'Alignment
127 and then To_Address
(Initial_Value
) = System
.Null_Address
);
128 -- If the attribute fits in an Atomic_Address (both size and alignment)
129 -- and Initial_Value is 0 (or null), then we will map the attribute
130 -- directly into ATCB.Attributes (Index), otherwise we will create
131 -- a level of indirection and instead use Attributes (Index) as a
132 -- Real_Attribute_Access.
134 Index
: constant Integer :=
135 Next_Index
(Require_Finalization
=> not Fast_Path
);
136 -- Index in the task control block's Attributes array
142 procedure Finalize
(Cleanup
: in out Attribute_Cleanup
) is
143 pragma Unreferenced
(Cleanup
);
149 C
: System
.Tasking
.Task_Id
:= System
.Tasking
.All_Tasks_List
;
155 if C
.Attributes
(Index
) /= 0
156 and then Require_Finalization
(Index
)
158 Deallocate
(C
.Attributes
(Index
));
159 C
.Attributes
(Index
) := 0;
163 C
:= C
.Common
.All_Tasks_Link
;
175 procedure Deallocate
(Ptr
: Atomic_Address
) is
176 Obj
: Real_Attribute_Access
:= To_Real_Attribute
(Ptr
);
185 function New_Attribute
(Val
: Attribute
) return Atomic_Address
is
186 Tmp
: Real_Attribute_Access
;
188 Tmp
:= new Real_Attribute
'(Free => Deallocate'Unrestricted_Access,
190 return To_Address (Tmp);
198 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
199 return Attribute_Handle
202 TT : constant Task_Id := To_Task_Id (T);
203 Error_Message : constant String := "trying to get the reference of a ";
204 Result : Attribute_Handle;
208 raise Program_Error with Error_Message & "null task";
211 if TT.Common.State = Terminated then
212 raise Tasking_Error with Error_Message & "terminated task";
216 -- Kill warning about possible alignment mismatch. If this happens,
217 -- Fast_Path will be False anyway
218 pragma Warnings (Off);
219 return To_Handle (TT.Attributes (Index)'Address);
220 pragma Warnings (On);
222 Self_Id := STPO.Self;
225 if TT.Attributes (Index) = 0 then
226 TT.Attributes (Index) := New_Attribute (Initial_Value);
230 (To_Real_Attribute (TT.Attributes (Index)).Value'Address);
231 Task_Unlock (Self_Id);
241 procedure Reinitialize
242 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
245 TT : constant Task_Id := To_Task_Id (T);
246 Error_Message : constant String := "Trying to Reinitialize a ";
250 raise Program_Error with Error_Message & "null task";
253 if TT.Common.State = Terminated then
254 raise Tasking_Error with Error_Message & "terminated task";
259 -- No finalization needed, simply reset to Initial_Value
261 TT.Attributes (Index) := To_Address (Initial_Value);
264 Self_Id := STPO.Self;
268 Attr : Atomic_Address renames TT.Attributes (Index);
276 Task_Unlock (Self_Id);
286 T : Task_Identification.Task_Id := Task_Identification.Current_Task)
289 TT : constant Task_Id := To_Task_Id (T);
290 Error_Message : constant String := "trying to set the value of a ";
294 raise Program_Error with Error_Message & "null task";
297 if TT.Common.State = Terminated then
298 raise Tasking_Error with Error_Message & "terminated task";
303 -- No finalization needed, simply set to Val
305 TT.Attributes (Index) := To_Address (Val);
308 Self_Id := STPO.Self;
312 Attr : Atomic_Address renames TT.Attributes (Index);
319 Attr := New_Attribute (Val);
322 Task_Unlock (Self_Id);
331 (T : Task_Identification.Task_Id := Task_Identification.Current_Task)
335 TT : constant Task_Id := To_Task_Id (T);
336 Error_Message : constant String := "trying to get the value of a ";
340 raise Program_Error with Error_Message & "null task";
343 if TT.Common.State = Terminated then
344 raise Tasking_Error with Error_Message & "terminated task";
348 return To_Attribute (TT.Attributes (Index));
351 Self_Id := STPO.Self;
355 Attr : Atomic_Address renames TT.Attributes (Index);
359 Task_Unlock (Self_Id);
360 return Initial_Value;
364 Result : constant Attribute :=
365 To_Real_Attribute (Attr).Value;
367 Task_Unlock (Self_Id);
375 end Ada.Task_Attributes;