Declare hurd_preempt_signals and hurd_unpreempt_signals.
[kopensolaris-gnu/glibc.git] / hurd / hurd / signal.h
1 /* Implementing POSIX.1 signals under the Hurd.
2 Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #ifndef _HURD_SIGNAL_H
21
22 #define _HURD_SIGNAL_H  1
23 #include <features.h>
24 /* Make sure <signal.h> is going to define NSIG.  */
25 #ifndef __USE_GNU
26 #error "Must have `_GNU_SOURCE' feature test macro to use this file"
27 #endif
28
29 #define __need_NULL
30 #include <stddef.h>
31
32 #include <mach/mach_types.h>
33 #include <mach/port.h>
34 #include <mach/message.h>
35 #include <hurd/hurd_types.h>
36 #include <signal.h>
37 #include <errno.h>
38 #include <hurd/msg.h>
39
40 #include <cthreads.h>           /* For `struct mutex'.  */
41 #include <spin-lock.h>
42 #include <hurd/threadvar.h>     /* We cache sigstate in a threadvar.  */
43
44
45 /* Per-thread signal state.  */
46
47 struct hurd_sigstate
48   {
49     spin_lock_t lock;           /* Locks most of the rest of the structure.  */
50
51     int critical_section;       /* Nonzero if in critical section.  */
52
53     thread_t thread;
54     struct hurd_sigstate *next; /* Linked-list of thread sigstates.  */
55
56     sigset_t blocked;           /* What signals are blocked.  */
57     sigset_t pending;           /* Pending signals, possibly blocked.  */
58     struct sigaction actions[NSIG];
59     struct sigaltstack sigaltstack;
60     struct
61       {
62         /* For each signal that may be pending, the
63            sigcode and error code to deliver it with.  */
64         long int code;
65         error_t error;
66       } pending_data[NSIG];
67
68     /* If `suspended' is set when this thread gets a signal,
69        the signal thread sends an empty message to it.  */
70     mach_port_t suspended;
71
72     /* The following members are not locked.  They are used only by this
73        thread, or by the signal thread with this thread suspended.  */
74
75     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
76
77     /* If this is not null, the thread is in sigreturn awaiting delivery of
78        pending signals.  This context (the machine-dependent portions only)
79        will be passed to sigreturn after running the handler for a pending
80        signal, instead of examining the thread state.  */
81     struct sigcontext *context;
82
83     /* This is the head of the thread's list of active resources; see
84        <hurd/userlink.h> for details.  This member is only used by the
85        thread itself, and always inside a critical section.  */
86     struct hurd_userlink *active_resources;
87
88     /* These are locked normally.  */
89     int cancel;                 /* Flag set by hurd_thread_cancel.  */
90     void (*cancel_hook) (void); /* Called on cancellation.  */
91   };
92
93 /* Linked list of states of all threads whose state has been asked for.  */
94
95 extern struct hurd_sigstate *_hurd_sigstates;
96
97 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
98
99 /* Get the sigstate of a given thread, taking its lock.  */
100
101 extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
102
103 /* Get the sigstate of the current thread.
104    This uses a per-thread variable to optimize the lookup.  */
105
106 extern struct hurd_sigstate *_hurd_self_sigstate (void)
107      /* This declaration tells the compiler that the value is constant.
108         We assume this won't be called twice from the same stack frame
109         by different threads.  */
110      __attribute__ ((__const__));
111
112 _EXTERN_INLINE struct hurd_sigstate *
113 _hurd_self_sigstate (void)
114 {
115   struct hurd_sigstate **location =
116     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
117   if (*location == NULL)
118     *location = _hurd_thread_sigstate (__mach_thread_self ());
119   return *location;
120 }
121 \f
122 /* Thread listening on our message port; also called the "signal thread".  */
123
124 extern thread_t _hurd_msgport_thread;
125
126 /* Our message port.  We hold the receive right and _hurd_msgport_thread
127    listens for messages on it.  We also hold a send right, for convenience.  */
128
129 extern mach_port_t _hurd_msgport;
130
131
132 /* Thread to receive process-global signals.  */
133
134 extern thread_t _hurd_sigthread;
135
136
137 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
138 extern int _hurd_core_limit;
139 \f
140 /* Critical sections.
141
142    A critical section is a section of code which cannot safely be interrupted
143    to run a signal handler; for example, code that holds any lock cannot be
144    interrupted lest the signal handler try to take the same lock and
145    deadlock result.  */
146
147 _EXTERN_INLINE void *
148 _hurd_critical_section_lock (void)
149 {
150   struct hurd_sigstate **location =
151     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
152   struct hurd_sigstate *ss = *location;
153   if (ss == NULL)
154     /* The thread variable is unset; this must be the first time we've
155        asked for it.  In this case, the critical section flag cannot
156        possible already be set.  Look up our sigstate structure the slow
157        way; this locks the sigstate lock.  */
158     ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
159   else
160     __spin_lock (&ss->lock);
161
162   if (ss->critical_section)
163     {
164       /* We are already in a critical section, so do nothing.  */
165       __spin_unlock (&ss->lock);
166       return NULL;
167     }
168
169   /* Set the critical section flag so no signal handler will run.  */
170   ss->critical_section = 1;
171   __spin_unlock (&ss->lock);
172
173   /* Return our sigstate pointer; this will be passed to
174      _hurd_critical_section_unlock to clear the critical section flag. */
175   return ss;
176 }
177
178 _EXTERN_INLINE void
179 _hurd_critical_section_unlock (void *our_lock)
180 {
181   if (our_lock == NULL)
182     /* The critical section lock was held when we began.  Do nothing.  */
183     return;
184   else
185     {
186       /* It was us who acquired the critical section lock.  Clear the
187          critical section flag.  */
188       struct hurd_sigstate *ss = our_lock;
189       sigset_t pending;
190       __spin_lock (&ss->lock);
191       ss->critical_section = 0;
192       pending = ss->pending & ~ss->blocked;
193       __spin_unlock (&ss->lock);
194       if (pending)
195         /* There are unblocked signals pending, which weren't
196            delivered because we were in the critical section.
197            Tell the signal thread to deliver them now.  */
198         __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
199     }
200 }
201
202 /* Convenient macros for simple uses of critical sections.
203    These two must be used as a pair at the same C scoping level.  */
204
205 #define HURD_CRITICAL_BEGIN \
206   { void *__hurd_critical__ = _hurd_critical_section_lock ()
207 #define HURD_CRITICAL_END \
208       _hurd_critical_section_unlock (__hurd_critical__); } while (0)
209 \f
210 /* Initialize the signal code, and start the signal thread.  */
211
212 extern void _hurdsig_init (void);
213
214 /* Initialize proc server-assisted fault recovery for the signal thread.  */
215
216 extern void _hurdsig_fault_init (void);
217
218 /* Raise a signal as described by SIGNO, SIGCODE and SIGERROR, on the
219    thread whose sigstate SS points to.  If SS is a null pointer, this
220    instead affects the calling thread.  */
221
222 extern void _hurd_raise_signal (struct hurd_sigstate *ss,
223                                 int signo, long int sigcode, int sigerror);
224
225 /* Translate a Mach exception into a signal (machine-dependent).  */
226
227 extern void _hurd_exception2signal (int exception, int code, int subcode,
228                                     int *signo, long int *sigcode, int *error);
229
230
231 /* Make the thread described by SS take the signal described by SIGNO and
232    SIGCODE.  If the process is traced, this will in fact stop with a SIGNO
233    as the stop signal unless UNTRACED is nonzero.  When the signal can be
234    considered delivered, sends a sig_post reply message on REPLY_PORT
235    indicating success.  SS is not locked.  */
236
237 extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
238                                         int signo, long int sigcode, int error,
239                                         mach_port_t reply_port,
240                                         mach_msg_type_name_t reply_port_type,
241                                         int untraced);
242
243 /* Set up STATE and SS to handle signal SIGNO by running HANDLER.  If
244    RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to
245    finish before running the signal handler.  The handler is passed SIGNO,
246    SIGCODE, and the returned `struct sigcontext' (which resides on the
247    stack the handler will use, and which describes the state of the thread
248    encoded in STATE before running the handler).  */
249
250 struct machine_thread_all_state;
251 extern struct sigcontext *
252 _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
253                         int signo, long int sigcode,
254                         int rpc_wait, struct machine_thread_all_state *state);
255
256 /* Function run by the signal thread to receive from the signal port.  */
257
258 extern void _hurd_msgport_receive (void);
259
260 /* Set up STATE with a thread state that, when resumed, is
261    like `longjmp (_hurd_sigthread_fault_env, 1)'.  */
262
263 extern void _hurd_initialize_fault_recovery_state (void *state);
264
265 /* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'.  */
266
267 extern void _hurd_longjmp_thread_state (void *state, jmp_buf env, int value);
268
269 /* Function run for SIGINFO when its action is SIG_DFL and the current
270    process is the session leader.  */
271
272 extern void _hurd_siginfo_handler (int);
273
274
275 /* Milliseconds to wait for an interruptible RPC to return after
276    `interrupt_operation'.  */
277
278 extern mach_msg_timeout_t _hurd_interrupted_rpc_timeout;
279
280
281 /* Mask of signals that cannot be caught, blocked, or ignored.  */
282 #define _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
283
284 /* Do an RPC to a process's message port.
285
286    Each argument is an expression which returns an error code; each
287    expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
288    fetch the appropriate message port and store it in the local variable
289    `msgport'; it will be deallocated after use.  FETCH_REFPORT_EXPR should
290    fetch the appropriate message port and store it in the local variable
291    `refport' (if no reference port is needed in the call, then
292    FETCH_REFPORT_EXPR should be simply KERN_SUCCESS or 0); if
293    DEALLOC_REFPORT evaluates to nonzero it will be deallocated after use,
294    otherwise the FETCH_REFPORT_EXPR must take care of user references to
295    `refport'.  RPC_EXPR should perform the desired RPC operation using
296    `msgport' and `refport'.
297
298    The reason for the complexity is that a process's message port and
299    reference port may change between fetching those ports and completing an
300    RPC using them (usually they change only when a process execs).  The RPC
301    will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
302    send the RPC request; or with MIG_SERVER_DIED if the msgport was
303    destroyed after we sent the RPC request but before it was serviced.  In
304    either of these cases, we retry the entire operation, discarding the old
305    message and reference ports and fetch them anew.  */
306
307 #define HURD_MSGPORT_RPC(fetch_msgport_expr,                                  \
308                          fetch_refport_expr, dealloc_refport,                 \
309                          rpc_expr)                                            \
310 ({                                                                            \
311     error_t __err;                                                            \
312     mach_port_t msgport, refport = MACH_PORT_NULL;                            \
313     do                                                                        \
314       {                                                                       \
315         /* Get the message port.  */                                          \
316         if (__err = (fetch_msgport_expr))                                     \
317           break;                                                              \
318         /* Get the reference port.  */                                        \
319         if (__err = (fetch_refport_expr))                                     \
320           {                                                                   \
321             /* Couldn't get it; deallocate MSGPORT and fail.  */              \
322             __mach_port_deallocate (__mach_task_self (), msgport);            \
323             break;                                                            \
324           }                                                                   \
325         __err = (rpc_expr);                                                   \
326         __mach_port_deallocate (__mach_task_self (), msgport);                \
327         if ((dealloc_refport) && refport != MACH_PORT_NULL)                   \
328           __mach_port_deallocate (__mach_task_self (), refport);              \
329       } while (__err == MACH_SEND_INVALID_DEST ||                             \
330                __err == MIG_SERVER_DIED);                                     \
331     __err;                                                                    \
332 })
333 \f
334 /* Some other parts of the library need to preempt signals, to detect
335    errors that should not result in a POSIX signal.  For example, when
336    some mapped region of memory is used, an extraneous SIGSEGV might be
337    generated when the mapping server returns an error for a page fault.  */
338
339 struct hurd_signal_preempt
340   {
341     /* Function to examine a thread receiving a given signal.  The handler
342        is called even for blocked signals.  This function is run in the
343        signal thread, with THREAD's sigstate locked; it should be as simple
344        and robust as possible.  THREAD is the thread which is about to
345        receive the signal.  SIGNO and SIGCODE would be passed to the normal
346        handler.
347
348        If the return value is SIG_DFL, normal signal processing continues.
349        If it is SIG_IGN, the signal is ignored.
350        Any other value is used in place of the normal handler.  */
351     sighandler_t (*handler) (thread_t thread,
352                              int signo, long int sigcode, int sigerror);
353     long int first, last;       /* Range of sigcodes this handler wants.  */
354     struct hurd_signal_preempt *next; /* Next handler on the chain. */
355   };
356
357 extern struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
358 extern struct mutex _hurd_signal_preempt_lock;
359
360 /* Install a signal preempter for the given signal and range.
361    The caller is responsible for the storage for PREEMPTER.  */
362 extern int hurd_preempt_signals (struct hurd_signal_preempt *preempter,
363                                  int signo, int first_code, int last_code,
364                                  sighandler_t (*handler) (thread_t,
365                                                           int, long int, int));
366
367 /* Remove the signal preempter previously installed by calling
368    `hurd_preempt_signals' with PREEMPTER and SIGNO.  */
369 extern int hurd_unpreempt_signals (struct hurd_signal_preempt *preempter,
370                                    int signo);
371
372
373
374 #endif  /* hurd/signal.h */