OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / ada / 5uintman.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 --                                                                          --
10 --             Copyright (C) 1991-2002 Florida State University             --
11 --                                                                          --
12 -- GNARL 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 2,  or (at your option) any later ver- --
15 -- sion. GNARL 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.  See the GNU General Public License --
18 -- for  more details.  You should have  received  a copy of the GNU General --
19 -- Public License  distributed with GNARL; see file COPYING.  If not, write --
20 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
21 -- MA 02111-1307, USA.                                                      --
22 --                                                                          --
23 -- As a special exception,  if other files  instantiate  generics from this --
24 -- unit, or you link  this unit with other files  to produce an executable, --
25 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
26 -- covered  by the  GNU  General  Public  License.  This exception does not --
27 -- however invalidate  any other reasons why  the executable file  might be --
28 -- covered by the  GNU Public License.                                      --
29 --                                                                          --
30 -- GNARL was developed by the GNARL team at Florida State University. It is --
31 -- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
32 -- State University (http://www.gnat.com).                                  --
33 --                                                                          --
34 ------------------------------------------------------------------------------
35
36 --  This is a Sun OS (FSU THREADS) version of this package
37
38 --  PLEASE DO NOT add any dependences on other packages. ??? why not ???
39 --  This package is designed to work with or without tasking support.
40
41 --  Make a careful study of all signals available under the OS, to see which
42 --  need to be reserved, kept always unmasked, or kept always unmasked. Be on
43 --  the lookout for special signals that may be used by the thread library.
44
45 with Interfaces.C;
46 --  used for int
47
48 with System.Error_Reporting;
49 --  used for Shutdown
50
51 with System.OS_Interface;
52 --  used for various Constants, Signal and types
53
54 package body System.Interrupt_Management is
55
56    use Interfaces.C;
57    use System.Error_Reporting;
58    use System.OS_Interface;
59
60    type Interrupt_List is array (Interrupt_ID range <>) of Interrupt_ID;
61    Exception_Interrupts : constant Interrupt_List :=
62      (SIGFPE, SIGILL, SIGSEGV);
63
64    Unreserve_All_Interrupts : Interfaces.C.int;
65    pragma Import
66      (C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
67
68    -----------------------
69    -- Local Subprograms --
70    -----------------------
71
72    procedure Notify_Exception
73      (signo   : Signal;
74       info    : access siginfo_t;
75       context : access struct_sigcontext);
76    --  This function identifies the Ada exception to be raised using
77    --  the information when the system received a synchronous signal.
78    --  Since this function is machine and OS dependent, different code
79    --  has to be provided for different target.
80
81    ----------------------
82    -- Notify_Exception --
83    ----------------------
84
85    --  The following code is intended for SunOS on Sparcstation.
86
87    procedure Notify_Exception
88      (signo   : Signal;
89       info    : access siginfo_t;
90       context : access struct_sigcontext)
91    is
92    begin
93       --  As long as we are using a longjmp to return control to the
94       --  exception handler on the runtime stack, we are safe. The original
95       --  signal mask (the one we had before coming into this signal catching
96       --  function) will be restored by the longjmp. Therefore, raising
97       --  an exception in this handler should be a safe operation.
98
99       --  Check that treatment of exception propagation here
100       --  is consistent with treatment of the abort signal in
101       --  System.Task_Primitives.Operations.
102
103       case signo is
104          when SIGFPE =>
105             case info.si_code is
106                when FPE_INTOVF_TRAP   |
107                     FPE_STARTSIG_TRAP |
108                     FPE_INTDIV_TRAP   |
109                     FPE_FLTDIV_TRAP   |
110                     FPE_FLTUND_TRAP   |
111                     FPE_FLTOPERR_TRAP |
112                     FPE_FLTOVF_TRAP =>
113                   raise Constraint_Error;
114
115                when others =>
116                   pragma Assert (Shutdown ("Unexpected SIGFPE signal"));
117                   null;
118             end case;
119
120          when SIGILL =>
121             case info.si_code is
122                when ILL_STACK           |
123                     ILL_ILLINSTR_FAULT  |
124                     ILL_PRIVINSTR_FAULT =>
125                   raise Constraint_Error;
126
127                when others =>
128                   pragma Assert (Shutdown ("Unexpected SIGILL signal"));
129                   null;
130             end case;
131
132          when SIGSEGV =>
133
134             --  was caused by accessing a null pointer.
135
136 --  ???? Origin of this code is unclear, may be broken ???
137
138             if context.sc_o0 in 0 .. 16#2000# then
139                raise Constraint_Error;
140             else
141                raise Storage_Error;
142             end if;
143
144          when others =>
145             pragma Assert (Shutdown ("Unexpected signal"));
146             null;
147       end case;
148    end Notify_Exception;
149
150    ---------------------------
151    -- Initialize_Interrupts --
152    ---------------------------
153
154    --  Nothing needs to be done on this platform
155
156    procedure Initialize_Interrupts is
157    begin
158       null;
159    end Initialize_Interrupts;
160
161 -------------------------
162 -- Package Elaboration --
163 -------------------------
164
165 begin
166    declare
167       act     : aliased struct_sigaction;
168       old_act : aliased struct_sigaction;
169       mask    : aliased sigset_t;
170       Result  : Interfaces.C.int;
171
172    begin
173       --  Need to call pthread_init very early because it is doing signal
174       --  initializations.
175
176       pthread_init;
177
178       --  Change the following assignment to use another signal for task abort.
179       --  For example, SIGTERM might be a good one if SIGABRT is required for
180       --  use elsewhere.
181
182       Abort_Task_Interrupt := SIGABRT;
183
184       act.sa_handler := Notify_Exception'Address;
185
186       --  Set sa_flags to SA_NODEFER so that during the handler execution
187       --  we do not change the Signal_Mask to be masked for the Signal.
188       --  This is a temporary fix to the problem that the Signal_Mask is
189       --  not restored after the exception (longjmp) from the handler.
190       --  The right fix should be made in sigsetjmp so that we save
191       --  the Signal_Set and restore it after a longjmp.
192
193       --  In that case, this field should be changed back to 0. ???
194
195       act.sa_flags := 16;
196
197       Result := sigemptyset (mask'Access);
198       pragma Assert (Result = 0);
199
200       for J in Exception_Interrupts'Range loop
201          Result := sigaddset (mask'Access, Signal (Exception_Interrupts (J)));
202          pragma Assert (Result = 0);
203       end loop;
204
205       act.sa_mask := mask;
206
207       for J in Exception_Interrupts'Range loop
208          Keep_Unmasked (Exception_Interrupts (J)) := True;
209
210          Result :=
211            sigaction
212            (Signal (Exception_Interrupts (J)),
213             act'Unchecked_Access,
214             old_act'Unchecked_Access);
215          pragma Assert (Result = 0);
216       end loop;
217
218       Keep_Unmasked (Abort_Task_Interrupt) := True;
219       Keep_Unmasked (SIGALRM) := True;
220       Keep_Unmasked (SIGSTOP) := True;
221       Keep_Unmasked (SIGKILL) := True;
222
223       --  By keeping SIGINT unmasked, allow the user to do a Ctrl-C, but at
224       --  the same time, disable the ability of handling this signal using
225       --  package Ada.Interrupts.
226
227       --  The pragma Unreserve_All_Interrupts allows the user the ability to
228       --  change this behavior.
229
230       if Unreserve_All_Interrupts = 0 then
231          Keep_Unmasked (SIGINT) := True;
232       end if;
233
234       --  Reserve this not to interfere with thread scheduling
235
236       --  ??? consider adding this to interrupt exceptions
237       --  Keep_Unmasked (SIGALRM) := True;
238
239       --  An earlier version had a comment about SIGALRM needing to be unmasked
240       --  in at least one thread for cond_timedwait to work.
241
242       --  It is unclear whether this is True for Solaris threads, FSU threads,
243       --  both, or maybe just an old version of FSU threads. ????
244
245       --  Following signals should not be disturbed. Found by experiment
246
247       Keep_Unmasked (SIGEMT) := True;
248       Keep_Unmasked (SIGCHLD) := True;
249
250       --  We do not have Signal 0 in reality. We just use this value
251       --  to identify not existing signals (see s-intnam.ads). Therefore,
252       --  Signal 0 should not be used in all signal related operations hence
253       --  mark it as reserved.
254
255       Reserve := Reserve or Keep_Unmasked or Keep_Masked;
256       Reserve (0) := True;
257    end;
258 end System.Interrupt_Management;