1------------------------------------------------------------------------------ 2-- -- 3-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS -- 4-- -- 5-- SYSTEM.INTERRUPT_MANAGEMENT.OPERATIONS -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 1991-2017, Florida State University -- 10-- Copyright (C) 1995-2019, AdaCore -- 11-- -- 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. -- 18-- -- 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. -- 22-- -- 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/>. -- 27-- -- 28-- GNARL was developed by the GNARL team at Florida State University. -- 29-- Extensive contributions were provided by Ada Core Technologies, Inc. -- 30-- -- 31------------------------------------------------------------------------------ 32 33-- This is a POSIX-like version of this package 34 35-- Note: this file can only be used for POSIX compliant systems 36 37with Interfaces.C; 38 39with System.OS_Interface; 40with System.Storage_Elements; 41 42package body System.Interrupt_Management.Operations is 43 44 use Interfaces.C; 45 use System.OS_Interface; 46 47 --------------------- 48 -- Local Variables -- 49 --------------------- 50 51 Initial_Action : array (Signal) of aliased struct_sigaction; 52 53 Default_Action : aliased struct_sigaction; 54 pragma Warnings (Off, Default_Action); 55 56 Ignore_Action : aliased struct_sigaction; 57 58 ---------------------------- 59 -- Thread_Block_Interrupt -- 60 ---------------------------- 61 62 procedure Thread_Block_Interrupt 63 (Interrupt : Interrupt_ID) 64 is 65 Result : Interfaces.C.int; 66 Mask : aliased sigset_t; 67 begin 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; 75 76 ------------------------------ 77 -- Thread_Unblock_Interrupt -- 78 ------------------------------ 79 80 procedure Thread_Unblock_Interrupt 81 (Interrupt : Interrupt_ID) 82 is 83 Mask : aliased sigset_t; 84 Result : Interfaces.C.int; 85 begin 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; 93 94 ------------------------ 95 -- Set_Interrupt_Mask -- 96 ------------------------ 97 98 procedure Set_Interrupt_Mask (Mask : access Interrupt_Mask) is 99 Result : Interfaces.C.int; 100 begin 101 Result := pthread_sigmask (SIG_SETMASK, Mask, null); 102 pragma Assert (Result = 0); 103 end Set_Interrupt_Mask; 104 105 procedure Set_Interrupt_Mask 106 (Mask : access Interrupt_Mask; 107 OMask : access Interrupt_Mask) 108 is 109 Result : Interfaces.C.int; 110 begin 111 Result := pthread_sigmask (SIG_SETMASK, Mask, OMask); 112 pragma Assert (Result = 0); 113 end Set_Interrupt_Mask; 114 115 ------------------------ 116 -- Get_Interrupt_Mask -- 117 ------------------------ 118 119 procedure Get_Interrupt_Mask (Mask : access Interrupt_Mask) is 120 Result : Interfaces.C.int; 121 begin 122 Result := pthread_sigmask (SIG_SETMASK, null, Mask); 123 pragma Assert (Result = 0); 124 end Get_Interrupt_Mask; 125 126 -------------------- 127 -- Interrupt_Wait -- 128 -------------------- 129 130 function Interrupt_Wait 131 (Mask : access Interrupt_Mask) return Interrupt_ID 132 is 133 Result : Interfaces.C.int; 134 Sig : aliased Signal; 135 136 begin 137 Result := sigwait (Mask, Sig'Access); 138 139 if Result /= 0 then 140 return 0; 141 end if; 142 143 return Interrupt_ID (Sig); 144 end Interrupt_Wait; 145 146 ---------------------------- 147 -- Install_Default_Action -- 148 ---------------------------- 149 150 procedure Install_Default_Action (Interrupt : Interrupt_ID) is 151 Result : Interfaces.C.int; 152 begin 153 Result := sigaction 154 (Signal (Interrupt), 155 Initial_Action (Signal (Interrupt))'Access, null); 156 pragma Assert (Result = 0); 157 end Install_Default_Action; 158 159 --------------------------- 160 -- Install_Ignore_Action -- 161 --------------------------- 162 163 procedure Install_Ignore_Action (Interrupt : Interrupt_ID) is 164 Result : Interfaces.C.int; 165 begin 166 Result := sigaction (Signal (Interrupt), Ignore_Action'Access, null); 167 pragma Assert (Result = 0); 168 end Install_Ignore_Action; 169 170 ------------------------- 171 -- Fill_Interrupt_Mask -- 172 ------------------------- 173 174 procedure Fill_Interrupt_Mask (Mask : access Interrupt_Mask) is 175 Result : Interfaces.C.int; 176 begin 177 Result := sigfillset (Mask); 178 pragma Assert (Result = 0); 179 end Fill_Interrupt_Mask; 180 181 -------------------------- 182 -- Empty_Interrupt_Mask -- 183 -------------------------- 184 185 procedure Empty_Interrupt_Mask (Mask : access Interrupt_Mask) is 186 Result : Interfaces.C.int; 187 begin 188 Result := sigemptyset (Mask); 189 pragma Assert (Result = 0); 190 end Empty_Interrupt_Mask; 191 192 --------------------------- 193 -- Add_To_Interrupt_Mask -- 194 --------------------------- 195 196 procedure Add_To_Interrupt_Mask 197 (Mask : access Interrupt_Mask; 198 Interrupt : Interrupt_ID) 199 is 200 Result : Interfaces.C.int; 201 begin 202 Result := sigaddset (Mask, Signal (Interrupt)); 203 pragma Assert (Result = 0); 204 end Add_To_Interrupt_Mask; 205 206 -------------------------------- 207 -- Delete_From_Interrupt_Mask -- 208 -------------------------------- 209 210 procedure Delete_From_Interrupt_Mask 211 (Mask : access Interrupt_Mask; 212 Interrupt : Interrupt_ID) 213 is 214 Result : Interfaces.C.int; 215 begin 216 Result := sigdelset (Mask, Signal (Interrupt)); 217 pragma Assert (Result = 0); 218 end Delete_From_Interrupt_Mask; 219 220 --------------- 221 -- Is_Member -- 222 --------------- 223 224 function Is_Member 225 (Mask : access Interrupt_Mask; 226 Interrupt : Interrupt_ID) return Boolean 227 is 228 Result : Interfaces.C.int; 229 begin 230 Result := sigismember (Mask, Signal (Interrupt)); 231 pragma Assert (Result = 0 or else Result = 1); 232 return Result = 1; 233 end Is_Member; 234 235 ------------------------- 236 -- Copy_Interrupt_Mask -- 237 ------------------------- 238 239 procedure Copy_Interrupt_Mask 240 (X : out Interrupt_Mask; 241 Y : Interrupt_Mask) is 242 begin 243 X := Y; 244 end Copy_Interrupt_Mask; 245 246 ---------------------------- 247 -- Interrupt_Self_Process -- 248 ---------------------------- 249 250 procedure Interrupt_Self_Process (Interrupt : Interrupt_ID) is 251 Result : Interfaces.C.int; 252 begin 253 Result := kill (getpid, Signal (Interrupt)); 254 pragma Assert (Result = 0); 255 end Interrupt_Self_Process; 256 257 -------------------------- 258 -- Setup_Interrupt_Mask -- 259 -------------------------- 260 261 procedure Setup_Interrupt_Mask is 262 begin 263 -- Mask task for all signals. The original mask of the Environment task 264 -- will be recovered by Interrupt_Manager task during the elaboration 265 -- of s-interr.adb. 266 267 Set_Interrupt_Mask (All_Tasks_Mask'Access); 268 end Setup_Interrupt_Mask; 269 270begin 271 declare 272 mask : aliased sigset_t; 273 allmask : aliased sigset_t; 274 Result : Interfaces.C.int; 275 276 begin 277 Interrupt_Management.Initialize; 278 279 for Sig in 1 .. Signal'Last loop 280 Result := sigaction 281 (Sig, null, Initial_Action (Sig)'Access); 282 283 -- ??? [assert 1] 284 -- we can't check Result here since sigaction will fail on 285 -- SIGKILL, SIGSTOP, and possibly other signals 286 -- pragma Assert (Result = 0); 287 288 end loop; 289 290 -- Setup the masks to be exported 291 292 Result := sigemptyset (mask'Access); 293 pragma Assert (Result = 0); 294 295 Result := sigfillset (allmask'Access); 296 pragma Assert (Result = 0); 297 298 Default_Action.sa_flags := 0; 299 Default_Action.sa_mask := mask; 300 Default_Action.sa_handler := 301 Storage_Elements.To_Address 302 (Storage_Elements.Integer_Address (SIG_DFL)); 303 304 Ignore_Action.sa_flags := 0; 305 Ignore_Action.sa_mask := mask; 306 Ignore_Action.sa_handler := 307 Storage_Elements.To_Address 308 (Storage_Elements.Integer_Address (SIG_IGN)); 309 310 for J in Interrupt_ID loop 311 if Keep_Unmasked (J) then 312 Result := sigaddset (mask'Access, Signal (J)); 313 pragma Assert (Result = 0); 314 Result := sigdelset (allmask'Access, Signal (J)); 315 pragma Assert (Result = 0); 316 end if; 317 end loop; 318 319 -- The Keep_Unmasked signals should be unmasked for Environment task 320 321 Result := pthread_sigmask (SIG_UNBLOCK, mask'Access, null); 322 pragma Assert (Result = 0); 323 324 -- Get the signal mask of the Environment Task 325 326 Result := pthread_sigmask (SIG_SETMASK, null, mask'Access); 327 pragma Assert (Result = 0); 328 329 -- Setup the constants exported 330 331 Environment_Mask := Interrupt_Mask (mask); 332 333 All_Tasks_Mask := Interrupt_Mask (allmask); 334 end; 335 336end System.Interrupt_Management.Operations; 337