1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- SYSTEM.INTERRUPT_MANAGEMENT.OPERATIONS --
9 -- Copyright (C) 1991-2017, Florida State University --
10 -- Copyright (C) 1995-2023, AdaCore --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 3, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. --
19 -- As a special exception under Section 7 of GPL version 3, you are granted --
20 -- additional permissions described in the GCC Runtime Library Exception, --
21 -- version 3.1, as published by the Free Software Foundation. --
23 -- You should have received a copy of the GNU General Public License and --
24 -- a copy of the GCC Runtime Library Exception along with this program; --
25 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
26 -- <http://www.gnu.org/licenses/>. --
28 -- GNARL was developed by the GNARL team at Florida State University. --
29 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
31 ------------------------------------------------------------------------------
33 -- This is a POSIX-like version of this package
35 -- Note: this file can only be used for POSIX compliant systems
39 with System
.OS_Interface
;
40 with System
.Storage_Elements
;
42 package body System
.Interrupt_Management
.Operations
is
45 use System
.OS_Interface
;
51 Initial_Action
: array (Signal
) of aliased struct_sigaction
;
53 Default_Action
: aliased struct_sigaction
;
54 pragma Warnings
(Off
, Default_Action
);
56 Ignore_Action
: aliased struct_sigaction
;
58 ----------------------------
59 -- Thread_Block_Interrupt --
60 ----------------------------
62 procedure Thread_Block_Interrupt
63 (Interrupt
: Interrupt_ID
)
65 Result
: Interfaces
.C
.int
;
66 Mask
: aliased sigset_t
;
68 Result
:= sigemptyset
(Mask
'Access);
69 pragma Assert
(Result
= 0);
70 Result
:= sigaddset
(Mask
'Access, Signal
(Interrupt
));
71 pragma Assert
(Result
= 0);
72 Result
:= pthread_sigmask
(SIG_BLOCK
, Mask
'Access, null);
73 pragma Assert
(Result
= 0);
74 end Thread_Block_Interrupt
;
76 ------------------------------
77 -- Thread_Unblock_Interrupt --
78 ------------------------------
80 procedure Thread_Unblock_Interrupt
81 (Interrupt
: Interrupt_ID
)
83 Mask
: aliased sigset_t
;
84 Result
: Interfaces
.C
.int
;
86 Result
:= sigemptyset
(Mask
'Access);
87 pragma Assert
(Result
= 0);
88 Result
:= sigaddset
(Mask
'Access, Signal
(Interrupt
));
89 pragma Assert
(Result
= 0);
90 Result
:= pthread_sigmask
(SIG_UNBLOCK
, Mask
'Access, null);
91 pragma Assert
(Result
= 0);
92 end Thread_Unblock_Interrupt
;
94 ------------------------
95 -- Set_Interrupt_Mask --
96 ------------------------
98 procedure Set_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
99 Result
: Interfaces
.C
.int
;
101 Result
:= pthread_sigmask
(SIG_SETMASK
, Mask
, null);
102 pragma Assert
(Result
= 0);
103 end Set_Interrupt_Mask
;
105 procedure Set_Interrupt_Mask
106 (Mask
: access Interrupt_Mask
;
107 OMask
: access Interrupt_Mask
)
109 Result
: Interfaces
.C
.int
;
111 Result
:= pthread_sigmask
(SIG_SETMASK
, Mask
, OMask
);
112 pragma Assert
(Result
= 0);
113 end Set_Interrupt_Mask
;
115 ------------------------
116 -- Get_Interrupt_Mask --
117 ------------------------
119 procedure Get_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
120 Result
: Interfaces
.C
.int
;
122 Result
:= pthread_sigmask
(SIG_SETMASK
, null, Mask
);
123 pragma Assert
(Result
= 0);
124 end Get_Interrupt_Mask
;
130 function Interrupt_Wait
131 (Mask
: access Interrupt_Mask
) return Interrupt_ID
133 Result
: Interfaces
.C
.int
;
134 Sig
: aliased Signal
;
137 Result
:= sigwait
(Mask
, Sig
'Access);
138 pragma Assert
(Result
= 0);
144 return Interrupt_ID
(Sig
);
147 ----------------------------
148 -- Install_Default_Action --
149 ----------------------------
151 procedure Install_Default_Action
(Interrupt
: Interrupt_ID
) is
152 Result
: Interfaces
.C
.int
;
156 Initial_Action
(Signal
(Interrupt
))'Access, null);
157 pragma Assert
(Result
= 0);
158 end Install_Default_Action
;
160 ---------------------------
161 -- Install_Ignore_Action --
162 ---------------------------
164 procedure Install_Ignore_Action
(Interrupt
: Interrupt_ID
) is
165 Result
: Interfaces
.C
.int
;
167 Result
:= sigaction
(Signal
(Interrupt
), Ignore_Action
'Access, null);
168 pragma Assert
(Result
= 0);
169 end Install_Ignore_Action
;
171 -------------------------
172 -- Fill_Interrupt_Mask --
173 -------------------------
175 procedure Fill_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
176 Result
: Interfaces
.C
.int
;
178 Result
:= sigfillset
(Mask
);
179 pragma Assert
(Result
= 0);
180 end Fill_Interrupt_Mask
;
182 --------------------------
183 -- Empty_Interrupt_Mask --
184 --------------------------
186 procedure Empty_Interrupt_Mask
(Mask
: access Interrupt_Mask
) is
187 Result
: Interfaces
.C
.int
;
189 Result
:= sigemptyset
(Mask
);
190 pragma Assert
(Result
= 0);
191 end Empty_Interrupt_Mask
;
193 ---------------------------
194 -- Add_To_Interrupt_Mask --
195 ---------------------------
197 procedure Add_To_Interrupt_Mask
198 (Mask
: access Interrupt_Mask
;
199 Interrupt
: Interrupt_ID
)
201 Result
: Interfaces
.C
.int
;
203 Result
:= sigaddset
(Mask
, Signal
(Interrupt
));
204 pragma Assert
(Result
= 0);
205 end Add_To_Interrupt_Mask
;
207 --------------------------------
208 -- Delete_From_Interrupt_Mask --
209 --------------------------------
211 procedure Delete_From_Interrupt_Mask
212 (Mask
: access Interrupt_Mask
;
213 Interrupt
: Interrupt_ID
)
215 Result
: Interfaces
.C
.int
;
217 Result
:= sigdelset
(Mask
, Signal
(Interrupt
));
218 pragma Assert
(Result
= 0);
219 end Delete_From_Interrupt_Mask
;
226 (Mask
: access Interrupt_Mask
;
227 Interrupt
: Interrupt_ID
) return Boolean
229 Result
: Interfaces
.C
.int
;
231 Result
:= sigismember
(Mask
, Signal
(Interrupt
));
232 pragma Assert
(Result
= 0 or else Result
= 1);
236 -------------------------
237 -- Copy_Interrupt_Mask --
238 -------------------------
240 procedure Copy_Interrupt_Mask
241 (X
: out Interrupt_Mask
;
242 Y
: Interrupt_Mask
) is
245 end Copy_Interrupt_Mask
;
247 ----------------------------
248 -- Interrupt_Self_Process --
249 ----------------------------
251 procedure Interrupt_Self_Process
(Interrupt
: Interrupt_ID
) is
252 Result
: Interfaces
.C
.int
;
254 Result
:= kill
(getpid
, Signal
(Interrupt
));
255 pragma Assert
(Result
= 0);
256 end Interrupt_Self_Process
;
258 --------------------------
259 -- Setup_Interrupt_Mask --
260 --------------------------
262 procedure Setup_Interrupt_Mask
is
264 -- Mask task for all signals. The original mask of the Environment task
265 -- will be recovered by Interrupt_Manager task during the elaboration
268 Set_Interrupt_Mask
(All_Tasks_Mask
'Access);
269 end Setup_Interrupt_Mask
;
273 mask
: aliased sigset_t
;
274 allmask
: aliased sigset_t
;
275 Result
: Interfaces
.C
.int
;
278 Interrupt_Management
.Initialize
;
280 for Sig
in 1 .. Signal
'Last loop
282 (Sig
, null, Initial_Action
(Sig
)'Access);
285 -- we can't check Result here since sigaction will fail on
286 -- SIGKILL, SIGSTOP, and possibly other signals
287 -- pragma Assert (Result = 0);
291 -- Setup the masks to be exported
293 Result
:= sigemptyset
(mask
'Access);
294 pragma Assert
(Result
= 0);
296 Result
:= sigfillset
(allmask
'Access);
297 pragma Assert
(Result
= 0);
299 Default_Action
.sa_flags
:= 0;
300 Default_Action
.sa_mask
:= mask
;
301 Default_Action
.sa_handler
:=
302 Storage_Elements
.To_Address
303 (Storage_Elements
.Integer_Address
(SIG_DFL
));
305 Ignore_Action
.sa_flags
:= 0;
306 Ignore_Action
.sa_mask
:= mask
;
307 Ignore_Action
.sa_handler
:=
308 Storage_Elements
.To_Address
309 (Storage_Elements
.Integer_Address
(SIG_IGN
));
311 for J
in Interrupt_ID
loop
312 if Keep_Unmasked
(J
) then
313 Result
:= sigaddset
(mask
'Access, Signal
(J
));
314 pragma Assert
(Result
= 0);
315 Result
:= sigdelset
(allmask
'Access, Signal
(J
));
316 pragma Assert
(Result
= 0);
320 -- The Keep_Unmasked signals should be unmasked for Environment task
322 Result
:= pthread_sigmask
(SIG_UNBLOCK
, mask
'Access, null);
323 pragma Assert
(Result
= 0);
325 -- Get the signal mask of the Environment Task
327 Result
:= pthread_sigmask
(SIG_SETMASK
, null, mask
'Access);
328 pragma Assert
(Result
= 0);
330 -- Setup the constants exported
332 Environment_Mask
:= Interrupt_Mask
(mask
);
334 All_Tasks_Mask
:= Interrupt_Mask
(allmask
);
337 end System
.Interrupt_Management
.Operations
;