OSDN Git Service

2005-03-29 Ed Falis <falis@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-intman-solaris.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS               --
4 --                                                                          --
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 --                                                                          --
7 --                                  B o d y                                 --
8 --                                                                          --
9 --          Copyright (C) 1992-2002 Free Software Foundation, Inc.          --
10 --                                                                          --
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.                                                      --
21 --                                                                          --
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.                                      --
28 --                                                                          --
29 -- GNARL was developed by the GNARL team at Florida State University.       --
30 -- Extensive contributions were provided by Ada Core Technologies, Inc.     --
31 --                                                                          --
32 ------------------------------------------------------------------------------
33
34 --  This is a Solaris version of this package.
35
36 --  PLEASE DO NOT add any dependences on other packages.
37 --  This package is designed to work with or without tasking support.
38
39 --  Make a careful study of all signals available under the OS,
40 --  to see which need to be reserved, kept always unmasked,
41 --  or kept always unmasked.
42
43 --  Be on the lookout for special signals that
44 --  may be used by the thread library.
45
46 with Interfaces.C;
47 --  used for int
48
49 with System.OS_Interface;
50 --  used for various Constants, Signal and types
51
52 package body System.Interrupt_Management is
53
54    use Interfaces.C;
55    use System.OS_Interface;
56
57    type Interrupt_List is array (Interrupt_ID range <>) of Interrupt_ID;
58
59    Exception_Interrupts : constant Interrupt_List :=
60      (SIGFPE, SIGILL, SIGSEGV, SIGBUS);
61
62    Unreserve_All_Interrupts : Interfaces.C.int;
63    pragma Import
64      (C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
65
66    ----------------------
67    -- Notify_Exception --
68    ----------------------
69
70    --  This function identifies the Ada exception to be raised using
71    --  the information when the system received a synchronous signal.
72    --  Since this function is machine and OS dependent, different code
73    --  has to be provided for different target.
74
75    procedure Notify_Exception
76      (signo   : Signal;
77       info    : access siginfo_t;
78       context : access ucontext_t);
79
80    ----------------------
81    -- Notify_Exception --
82    ----------------------
83
84    procedure Notify_Exception
85      (signo   : Signal;
86       info    : access siginfo_t;
87       context : access ucontext_t)
88    is
89       pragma Warnings (Off, context);
90
91    begin
92       --  Check that treatment of exception propagation here
93       --  is consistent with treatment of the abort signal in
94       --  System.Task_Primitives.Operations.
95
96       case signo is
97          when SIGFPE =>
98             case info.si_code is
99                when  FPE_INTDIV |
100                      FPE_INTOVF |
101                      FPE_FLTDIV |
102                      FPE_FLTOVF |
103                      FPE_FLTUND |
104                      FPE_FLTRES |
105                      FPE_FLTINV |
106                      FPE_FLTSUB =>
107
108                   raise Constraint_Error;
109
110                when others =>
111                   pragma Assert (False);
112                   null;
113             end case;
114
115          when SIGILL | SIGSEGV | SIGBUS  =>
116             raise Storage_Error;
117
118          when others =>
119             pragma Assert (False);
120             null;
121       end case;
122    end Notify_Exception;
123
124    ---------------------------
125    -- Initialize_Interrupts --
126    ---------------------------
127
128    --  Nothing needs to be done on this platform.
129
130    procedure Initialize_Interrupts is
131    begin
132       null;
133    end Initialize_Interrupts;
134
135 ----------------------------
136 -- Package Initialization --
137 ----------------------------
138
139 begin
140    declare
141       act     : aliased struct_sigaction;
142       old_act : aliased struct_sigaction;
143       mask    : aliased sigset_t;
144       Result  : Interfaces.C.int;
145
146       function State (Int : Interrupt_ID) return Character;
147       pragma Import (C, State, "__gnat_get_interrupt_state");
148       --  Get interrupt state.  Defined in a-init.c
149       --  The input argument is the interrupt number,
150       --  and the result is one of the following:
151       --
152       User    : constant Character := 'u';
153       Runtime : constant Character := 'r';
154       Default : constant Character := 's';
155       --    'n'   this interrupt not set by any Interrupt_State pragma
156       --    'u'   Interrupt_State pragma set state to User
157       --    'r'   Interrupt_State pragma set state to Runtime
158       --    's'   Interrupt_State pragma set state to System (use "default"
159       --           system handler)
160
161    begin
162       --  Need to call pthread_init very early because it is doing signal
163       --  initializations.
164
165       pthread_init;
166
167       --  Change this if you want to use another signal for task abort.
168       --  SIGTERM might be a good one.
169
170       Abort_Task_Interrupt := SIGABRT;
171
172       act.sa_handler := Notify_Exception'Address;
173
174       --  Set sa_flags to SA_NODEFER so that during the handler execution
175       --  we do not change the Signal_Mask to be masked for the Signal.
176       --  This is a temporary fix to the problem that the Signal_Mask is
177       --  not restored after the exception (longjmp) from the handler.
178       --  The right fix should be made in sigsetjmp so that we save
179       --  the Signal_Set and restore it after a longjmp.
180
181       --  In that case, this field should be changed back to 0. ??? (Dong-Ik)
182
183       act.sa_flags := 16;
184
185       Result := sigemptyset (mask'Access);
186       pragma Assert (Result = 0);
187
188       --  ??? For the same reason explained above, we can't mask these
189       --  signals because otherwise we won't be able to catch more than
190       --  one signal.
191
192       act.sa_mask := mask;
193
194       pragma Assert (Keep_Unmasked = (Interrupt_ID'Range => False));
195       pragma Assert (Reserve = (Interrupt_ID'Range => False));
196
197       for J in Exception_Interrupts'Range loop
198          if State (Exception_Interrupts (J)) /= User then
199             Keep_Unmasked (Exception_Interrupts (J)) := True;
200             Reserve (Exception_Interrupts (J)) := True;
201
202             if State (Exception_Interrupts (J)) /= Default then
203                Result :=
204                  sigaction
205                  (Signal (Exception_Interrupts (J)), act'Unchecked_Access,
206                   old_act'Unchecked_Access);
207                pragma Assert (Result = 0);
208             end if;
209          end if;
210       end loop;
211
212       if State (Abort_Task_Interrupt) /= User then
213          Keep_Unmasked (Abort_Task_Interrupt) := True;
214          Reserve (Abort_Task_Interrupt) := True;
215       end if;
216
217       --  Set SIGINT to unmasked state as long as it's
218       --  not in "User" state.  Check for Unreserve_All_Interrupts last
219
220       if State (SIGINT) /= User then
221          Keep_Unmasked (SIGINT) := True;
222          Reserve (SIGINT) := True;
223       end if;
224
225       --  Check all signals for state that requires keeping them
226       --  unmasked and reserved
227
228       for J in Interrupt_ID'Range loop
229          if State (J) = Default or else State (J) = Runtime then
230             Keep_Unmasked (J) := True;
231             Reserve (J) := True;
232          end if;
233       end loop;
234
235       --  Add the set of signals that must always be unmasked for this target
236
237       for J in Unmasked'Range loop
238          Keep_Unmasked (Interrupt_ID (Unmasked (J))) := True;
239          Reserve (Interrupt_ID (Unmasked (J))) := True;
240       end loop;
241
242       --  Add target-specific reserved signals
243
244       for J in Reserved'Range loop
245          Reserve (Interrupt_ID (Reserved (J))) := True;
246       end loop;
247
248       --  Process pragma Unreserve_All_Interrupts. This overrides any
249       --  settings due to pragma Interrupt_State:
250
251       if Unreserve_All_Interrupts /= 0 then
252          Keep_Unmasked (SIGINT) := False;
253          Reserve (SIGINT) := False;
254       end if;
255
256       --  We do not have Signal 0 in reality. We just use this value
257       --  to identify not existing signals (see s-intnam.ads). Therefore,
258       --  Signal 0 should not be used in all signal related operations hence
259       --  mark it as reserved.
260
261       Reserve (0) := True;
262    end;
263 end System.Interrupt_Management;