1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- S Y S T E M . I N T E R R U P T _ M A N A G E M E N T . --
6 -- O P E R A T I O N S --
10 -- Copyright (C) 1991-1994, Florida State University --
11 -- Copyright (C) 1995-2007, AdaCore --
13 -- GNARL is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNARL; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
22 -- Boston, MA 02110-1301, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNARL was developed by the GNARL team at Florida State University. --
32 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
34 ------------------------------------------------------------------------------
36 -- This is a POSIX-like version of this package.
37 -- Note: this file can only be used for POSIX compliant systems.
44 with System
.OS_Interface
;
45 -- used for various type, constant, and operations
47 with System
.Storage_Elements
;
48 -- used for To_Address
51 package body System
.Interrupt_Management
.Operations
is
54 use System
.OS_Interface
;
60 Initial_Action
: array (Signal
) of aliased struct_sigaction
;
62 Default_Action
: aliased struct_sigaction
;
63 pragma Warnings
(Off
, Default_Action
);
65 Ignore_Action
: aliased struct_sigaction
;
67 ----------------------------
68 -- Thread_Block_Interrupt --
69 ----------------------------
71 procedure Thread_Block_Interrupt
72 (Interrupt
: Interrupt_ID
)
74 Result
: Interfaces
.C
.int
;
75 Mask
: aliased sigset_t
;
77 Result
:= sigemptyset
(Mask
'Access);
78 pragma Assert
(Result
= 0);
79 Result
:= sigaddset
(Mask
'Access, Signal
(Interrupt
));
80 pragma Assert
(Result
= 0);
81 Result
:= pthread_sigmask
(SIG_BLOCK
, Mask
'Access, null);
82 pragma Assert
(Result
= 0);
83 end Thread_Block_Interrupt
;
85 ------------------------------
86 -- Thread_Unblock_Interrupt --
87 ------------------------------
89 procedure Thread_Unblock_Interrupt
90 (Interrupt
: Interrupt_ID
)
92 Mask
: aliased sigset_t
;
93 Result
: Interfaces
.C
.int
;
95 Result
:= sigemptyset
(Mask
'Access);
96 pragma Assert
(Result
= 0);
97 Result
:= sigaddset
(Mask
'Access, Signal
(Interrupt
));
98 pragma Assert
(Result
= 0);
99 Result
:= pthread_sigmask
(SIG_UNBLOCK
, Mask
'Access, null);
100 pragma Assert
(Result
= 0);
101 end Thread_Unblock_Interrupt
;
103 ------------------------
104 -- Set_Interrupt_Mask --
105 ------------------------
107 procedure Set_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
108 Result
: Interfaces
.C
.int
;
110 Result
:= pthread_sigmask
(SIG_SETMASK
, Mask
, null);
111 pragma Assert
(Result
= 0);
112 end Set_Interrupt_Mask
;
114 procedure Set_Interrupt_Mask
115 (Mask
: access Interrupt_Mask
;
116 OMask
: access Interrupt_Mask
)
118 Result
: Interfaces
.C
.int
;
120 Result
:= pthread_sigmask
(SIG_SETMASK
, Mask
, OMask
);
121 pragma Assert
(Result
= 0);
122 end Set_Interrupt_Mask
;
124 ------------------------
125 -- Get_Interrupt_Mask --
126 ------------------------
128 procedure Get_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
129 Result
: Interfaces
.C
.int
;
131 Result
:= pthread_sigmask
(SIG_SETMASK
, null, Mask
);
132 pragma Assert
(Result
= 0);
133 end Get_Interrupt_Mask
;
139 function Interrupt_Wait
140 (Mask
: access Interrupt_Mask
) return Interrupt_ID
142 Result
: Interfaces
.C
.int
;
143 Sig
: aliased Signal
;
146 Result
:= sigwait
(Mask
, Sig
'Access);
152 return Interrupt_ID
(Sig
);
155 ----------------------------
156 -- Install_Default_Action --
157 ----------------------------
159 procedure Install_Default_Action
(Interrupt
: Interrupt_ID
) is
160 Result
: Interfaces
.C
.int
;
164 Initial_Action
(Signal
(Interrupt
))'Access, null);
165 pragma Assert
(Result
= 0);
166 end Install_Default_Action
;
168 ---------------------------
169 -- Install_Ignore_Action --
170 ---------------------------
172 procedure Install_Ignore_Action
(Interrupt
: Interrupt_ID
) is
173 Result
: Interfaces
.C
.int
;
175 Result
:= sigaction
(Signal
(Interrupt
), Ignore_Action
'Access, null);
176 pragma Assert
(Result
= 0);
177 end Install_Ignore_Action
;
179 -------------------------
180 -- Fill_Interrupt_Mask --
181 -------------------------
183 procedure Fill_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
184 Result
: Interfaces
.C
.int
;
186 Result
:= sigfillset
(Mask
);
187 pragma Assert
(Result
= 0);
188 end Fill_Interrupt_Mask
;
190 --------------------------
191 -- Empty_Interrupt_Mask --
192 --------------------------
194 procedure Empty_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
195 Result
: Interfaces
.C
.int
;
197 Result
:= sigemptyset
(Mask
);
198 pragma Assert
(Result
= 0);
199 end Empty_Interrupt_Mask
;
201 ---------------------------
202 -- Add_To_Interrupt_Mask --
203 ---------------------------
205 procedure Add_To_Interrupt_Mask
206 (Mask
: access Interrupt_Mask
;
207 Interrupt
: Interrupt_ID
)
209 Result
: Interfaces
.C
.int
;
211 Result
:= sigaddset
(Mask
, Signal
(Interrupt
));
212 pragma Assert
(Result
= 0);
213 end Add_To_Interrupt_Mask
;
215 --------------------------------
216 -- Delete_From_Interrupt_Mask --
217 --------------------------------
219 procedure Delete_From_Interrupt_Mask
220 (Mask
: access Interrupt_Mask
;
221 Interrupt
: Interrupt_ID
)
223 Result
: Interfaces
.C
.int
;
225 Result
:= sigdelset
(Mask
, Signal
(Interrupt
));
226 pragma Assert
(Result
= 0);
227 end Delete_From_Interrupt_Mask
;
234 (Mask
: access Interrupt_Mask
;
235 Interrupt
: Interrupt_ID
) return Boolean
237 Result
: Interfaces
.C
.int
;
239 Result
:= sigismember
(Mask
, Signal
(Interrupt
));
240 pragma Assert
(Result
= 0 or else Result
= 1);
244 -------------------------
245 -- Copy_Interrupt_Mask --
246 -------------------------
248 procedure Copy_Interrupt_Mask
249 (X
: out Interrupt_Mask
;
250 Y
: Interrupt_Mask
) is
253 end Copy_Interrupt_Mask
;
255 ----------------------------
256 -- Interrupt_Self_Process --
257 ----------------------------
259 procedure Interrupt_Self_Process
(Interrupt
: Interrupt_ID
) is
260 Result
: Interfaces
.C
.int
;
262 Result
:= kill
(getpid
, Signal
(Interrupt
));
263 pragma Assert
(Result
= 0);
264 end Interrupt_Self_Process
;
266 --------------------------
267 -- Setup_Interrupt_Mask --
268 --------------------------
270 procedure Setup_Interrupt_Mask
is
272 -- Mask task for all signals. The original mask of the Environment task
273 -- will be recovered by Interrupt_Manager task during the elaboration
276 Set_Interrupt_Mask
(All_Tasks_Mask
'Access);
277 end Setup_Interrupt_Mask
;
281 mask
: aliased sigset_t
;
282 allmask
: aliased sigset_t
;
283 Result
: Interfaces
.C
.int
;
286 Interrupt_Management
.Initialize
;
288 for Sig
in 1 .. Signal
'Last loop
290 (Sig
, null, Initial_Action
(Sig
)'Access);
293 -- we can't check Result here since sigaction will fail on
294 -- SIGKILL, SIGSTOP, and possibly other signals
295 -- pragma Assert (Result = 0);
299 -- Setup the masks to be exported
301 Result
:= sigemptyset
(mask
'Access);
302 pragma Assert
(Result
= 0);
304 Result
:= sigfillset
(allmask
'Access);
305 pragma Assert
(Result
= 0);
307 Default_Action
.sa_flags
:= 0;
308 Default_Action
.sa_mask
:= mask
;
309 Default_Action
.sa_handler
:=
310 Storage_Elements
.To_Address
311 (Storage_Elements
.Integer_Address
(SIG_DFL
));
313 Ignore_Action
.sa_flags
:= 0;
314 Ignore_Action
.sa_mask
:= mask
;
315 Ignore_Action
.sa_handler
:=
316 Storage_Elements
.To_Address
317 (Storage_Elements
.Integer_Address
(SIG_IGN
));
319 for J
in Interrupt_ID
loop
320 if Keep_Unmasked
(J
) then
321 Result
:= sigaddset
(mask
'Access, Signal
(J
));
322 pragma Assert
(Result
= 0);
323 Result
:= sigdelset
(allmask
'Access, Signal
(J
));
324 pragma Assert
(Result
= 0);
328 -- The Keep_Unmasked signals should be unmasked for Environment task
330 Result
:= pthread_sigmask
(SIG_UNBLOCK
, mask
'Access, null);
331 pragma Assert
(Result
= 0);
333 -- Get the signal mask of the Environment Task
335 Result
:= pthread_sigmask
(SIG_SETMASK
, null, mask
'Access);
336 pragma Assert
(Result
= 0);
338 -- Setup the constants exported
340 Environment_Mask
:= Interrupt_Mask
(mask
);
342 All_Tasks_Mask
:= Interrupt_Mask
(allmask
);
345 end System
.Interrupt_Management
.Operations
;