1 ------------------------------------------------------------------------------
3 -- GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- I N T E R F A C E S . V T H R E A D S --
9 -- Copyright (C) 2002-2003, Free Software Foundation, Inc. --
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 2, or (at your option) any later ver- --
14 -- sion. GNARL 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNARL; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNARL was developed by the GNARL team at Florida State University. --
30 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
32 ------------------------------------------------------------------------------
34 -- Implement APEX process registration for AE653
36 with Ada
.Exceptions
; use Ada
.Exceptions
;
37 with Ada
.Unchecked_Conversion
;
41 with System
.Secondary_Stack
;
42 with System
.Soft_Links
;
43 with System
.Task_Primitives
.Ae_653
;
44 with System
.Task_Primitives
.Operations
; use System
.Task_Primitives
.Operations
;
45 with System
.Tasking
; use System
.Tasking
;
46 with System
.Task_Info
;
47 with System
.Tasking
.Initialization
;
49 package body Interfaces
.Vthreads
is
51 use System
.OS_Interface
;
53 -----------------------
54 -- Local Subprograms --
55 -----------------------
57 procedure Enter_Task
(T
: Task_ID
; Thread
: Thread_Id
);
58 -- Duplicate and generalize
59 -- System.Task_Primitives.Operations.Enter_Task
61 procedure GNAT_Error_Handler
(Sig
: Signal
);
62 -- Signal handler for ARINC processes
65 pragma Import
(C
, Init_Float
, "__gnat_init_float");
66 -- Properly initializes the FPU for PPC systems.
68 procedure Install_Handler
;
69 -- Install signal handlers for the calling ARINC process
71 function Register_Foreign_Thread
(Thread
: Thread_Id
) return Task_ID
;
72 -- Duplicate and generalize
73 -- System.Task_Primitives.Operations.Register_Foreign_Thread
75 -----------------------------
76 -- Install_Signal_Handlers --
77 -----------------------------
79 function Install_Signal_Handlers
return Interfaces
.C
.int
is
84 end Install_Signal_Handlers
;
86 ----------------------
87 -- Register_Foreign --
88 ----------------------
90 -- Create Ada task data structures for an ARINC process. All dynamic
91 -- allocation of related data structures must be done via this routine.
93 function Register_Foreign
(T
: OSI
.Thread_Id
) return OSI
.STATUS
is
95 use System
.Task_Primitives
.Ae_653
;
97 pragma Assert
(taskVarGet
(T
, ATCB_Key_Addr
) = ERROR
);
98 -- "T" is not yet registered
100 Result
: OSI
.STATUS
:= taskIdVerify
(T
);
101 Status
: OSI
.STATUS
:= OK
;
106 Status
:= taskVarGet
(T
, ATCB_Key_Addr
);
108 -- Error of already registered
110 if Status
/= ERROR
then
117 -- Make sure the caller has a TCB, since it's possible to have
118 -- pure C APEX processes that create ones calling Ada code
123 Status
:= taskVarGet
(taskIdSelf
, ATCB_Key_Addr
);
125 if Status
= ERROR
then
126 Caller
:= Register_Foreign_Thread
(taskIdSelf
);
130 if taskIdSelf
/= T
then
131 Temp_Id
:= Register_Foreign_Thread
(T
);
139 end Register_Foreign
;
145 -- Reinitialize Ada task data structures. No dynamic allocation
146 -- may occur via this routine.
148 function Reset_Foreign
(T
: Thread_Id
) return STATUS
is
150 use System
.Secondary_Stack
;
151 use System
.Task_Primitives
.Ae_653
;
152 use type System
.Address
;
154 pragma Assert
(taskVarGet
(T
, ATCB_Key_Addr
) /= ERROR
);
155 -- "T" has already been registered
157 Result
: STATUS
:= taskVarGet
(T
, ATCB_Key_Addr
);
158 function To_Address
is new Ada
.Unchecked_Conversion
159 (Interfaces
.C
.int
, System
.Address
);
163 (To_Address
(Result
)).Common
.Compiler_Data
.Sec_Stack_Addr
164 /= System
.Null_Address
);
165 -- "T" already has a secondary stack
168 if Result
/= ERROR
then
170 -- Just reset the secondary stack pointer. The implementation here
171 -- assumes that the fixed secondary stack implementation is used.
172 -- If not, there will be a memory leak (along with allocation, which
173 -- is prohibited for ARINC processes once the system enters "normal"
178 (To_Address
(Result
)).Common
.Compiler_Data
.Sec_Stack_Addr
);
189 function Setup_Thread
return System
.Address
is
190 Result
: System
.Address
:= System
.Null_Address
;
194 if Is_Valid_Task
then
195 Status
:= Reset_Foreign
(taskIdSelf
);
197 To_Address
(System
.Task_Primitives
.Operations
.Self
);
199 Status
:= Register_Foreign
(taskIdSelf
);
203 To_Address
(System
.Task_Primitives
.Operations
.Self
);
213 procedure Enter_Task
(T
: Task_ID
; Thread
: Thread_Id
) is
214 use System
.Task_Primitives
.Ae_653
;
217 Set_Task_Thread
(T
, Thread
);
220 ------------------------
221 -- GNAT_Error_Handler --
222 ------------------------
224 procedure GNAT_Error_Handler
(Sig
: Signal
) is
225 Mask
: aliased sigset_t
;
229 -- This code is the Ada replacement for init.c in the
230 -- AE653 level B runtime.
232 -- VxWorks will always mask out the signal during the signal
233 -- handler and will reenable it on a longjmp. GNAT does not
234 -- generate a longjmp to return from a signal handler so the
235 -- signal will still be masked unless we unmask it.
237 Result
:= pthread_sigmask
(SIG_SETMASK
, null, Mask
'Unchecked_Access);
238 Result
:= sigdelset
(Mask
'Access, Sig
);
239 Result
:= pthread_sigmask
(SIG_SETMASK
, Mask
'Unchecked_Access, null);
243 Raise_Exception
(Constraint_Error
'Identity, "SIGFPE");
245 Raise_Exception
(Constraint_Error
'Identity, "SIGILL");
248 (Program_Error
'Identity,
249 "erroneous memory access");
251 -- SIGBUS indicates stack overflow when it occurs
252 -- in an application domain (but not in the Core
253 -- OS under AE653, or in the kernel domain under
256 (Storage_Error
'Identity,
257 "stack overflow or SIGBUS");
259 Raise_Exception
(Program_Error
'Identity, "unhandled signal");
261 end GNAT_Error_Handler
;
263 ---------------------
264 -- Install_Handler --
265 ---------------------
267 procedure Install_Handler
is
268 Mask
: aliased sigset_t
;
269 Signal_Action
: aliased struct_sigaction
;
270 Result
: Interfaces
.C
.int
;
273 -- Set up signal handler to map synchronous signals to appropriate
274 -- exceptions. Make sure that the handler isn't interrupted by
275 -- another signal that might cause a scheduling event!
277 -- This code is the Ada replacement for init.c in the
278 -- AE653 level B runtime.
279 Signal_Action
.sa_handler
:= GNAT_Error_Handler
'Address;
280 Signal_Action
.sa_flags
:= SA_ONSTACK
;
281 Result
:= sigemptyset
(Mask
'Access);
282 Signal_Action
.sa_mask
:= Mask
;
285 (Signal
(SIGFPE
), Signal_Action
'Unchecked_Access, null);
288 (Signal
(SIGILL
), Signal_Action
'Unchecked_Access, null);
291 (Signal
(SIGSEGV
), Signal_Action
'Unchecked_Access, null);
294 (Signal
(SIGBUS
), Signal_Action
'Unchecked_Access, null);
298 -----------------------------
299 -- Register_Foreign_Thread --
300 -----------------------------
302 Foreign_Task_Elaborated
: aliased Boolean := True;
304 function Register_Foreign_Thread
(Thread
: Thread_Id
) return Task_ID
is
305 pragma Assert
(Thread
= taskIdSelf
or else Is_Valid_Task
);
306 -- Ensure that allocation will work
308 Local_ATCB
: aliased Ada_Task_Control_Block
(0);
312 use type Interfaces
.C
.unsigned
;
313 use type System
.Address
;
314 use System
.Task_Info
;
315 use System
.Task_Primitives
.Ae_653
;
318 if taskIdSelf
= Thread
then
320 Self
: Task_ID
:= Local_ATCB
'Unchecked_Access;
321 -- Temporarily record this as the Task_ID for the thread
324 Set_Current_Priority
(Self
, System
.Priority
'First);
325 Set_Task_Thread
(Self
, Thread
);
329 pragma Assert
(Is_Valid_Task
);
330 -- It is now safe to use an allocator for the real TCB
332 New_Id
:= new Ada_Task_Control_Block
(0);
334 -- Finish initialization
336 System
.Tasking
.Initialize_ATCB
337 (New_Id
, null, System
.Null_Address
, Null_Task
,
338 Foreign_Task_Elaborated
'Access,
339 System
.Priority
'First,
340 System
.Task_Info
.Unspecified_Task_Info
, 0, New_Id
,
342 pragma Assert
(Succeeded
);
344 New_Id
.Master_of_Task
:= 0;
345 New_Id
.Master_Within
:= New_Id
.Master_of_Task
+ 1;
347 for L
in New_Id
.Entry_Calls
'Range loop
348 New_Id
.Entry_Calls
(L
).Self
:= New_Id
;
349 New_Id
.Entry_Calls
(L
).Level
:= L
;
352 New_Id
.Common
.State
:= Runnable
;
353 New_Id
.Awake_Count
:= 1;
355 -- Since this is not an ordinary Ada task, we will start out undeferred
357 New_Id
.Deferral_Level
:= 0;
359 System
.Soft_Links
.Create_TSD
(New_Id
.Common
.Compiler_Data
);
361 -- Allocate a fixed secondary stack
364 (New_Id
.Common
.Compiler_Data
.Sec_Stack_Addr
= System
.Null_Address
);
365 System
.Secondary_Stack
.SS_Init
366 (New_Id
.Common
.Compiler_Data
.Sec_Stack_Addr
);
368 Enter_Task
(New_Id
, Thread
);
371 end Register_Foreign_Thread
;
373 -- Force use of tasking versions of secondary stack routines:
375 procedure Force_Closure
renames
376 System
.Tasking
.Initialization
.Defer_Abortion
;
377 pragma Unreferenced
(Force_Closure
);
379 -- Package elaboration code
382 -- Register the exported routines with the vThreads ARINC API
384 procCreateHookAdd
(Register_Foreign
'Access);
385 procStartHookAdd
(Reset_Foreign
'Access);
386 end Interfaces
.Vthreads
;