aace9e0a9c402b21f3a46a61e397240e7cee6ee2
[kopensolaris-gnu/glibc.git] / hurd / hurd / signal.h
1 /* Implementing POSIX.1 signals under the Hurd.
2 Copyright (C) 1993, 1994 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
39 #include <cthreads.h>           /* For `struct mutex'.  */
40 #include <lock-intern.h>
41 #include <hurd/threadvar.h>     /* We cache sigstate in a threadvar.  */
42
43
44 /* Per-thread signal state.  */
45
46 struct hurd_sigstate
47   {
48     /* This mutex locks most of the rest of this structure.  It also acts
49        as a critical section lock for the thread (see below).  */
50     struct mutex lock;
51     int critical_section;
52
53     /* XXX This should perhaps instead be something that identifies
54        cthreads multiplexed on a single kernel thread.  */
55     thread_t thread;
56     struct hurd_sigstate *next; /* Linked-list of thread sigstates.  */
57
58     sigset_t blocked;
59     sigset_t pending;
60     struct sigaction actions[NSIG];
61     struct sigaltstack sigaltstack;
62     struct
63       {
64         /* For each signal that may be pending, the
65            sigcode and error code to deliver it with.  */
66         int code, error;
67       } pending_data[NSIG];
68
69     /* If `suspended' is set when this thread gets a signal,
70        the signal thread clears it and then signals `arrived'.  */
71     int suspended;
72 #ifdef noteven
73     struct condition arrived;
74 #endif
75
76     /* Not locked.  Used only by this thread, or by the signal thread with
77        this thread suspended.  */
78     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
79
80     /* If this is not null, the thread is in sigreturn awaiting delivery of
81        pending signals.  This context (the machine-dependent portions only)
82        will be passed to sigreturn after running the handler for a pending
83        signal, instead of examining the thread state.  */
84     struct sigcontext *context;
85   };
86
87 /* Linked list of states of all threads whose state has been asked for.  */
88
89 extern struct hurd_sigstate *_hurd_sigstates;
90
91 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
92
93 /* Get the sigstate of a given thread, taking its lock.  */
94
95 extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
96
97 /* Get the sigstate of the current thread, taking its lock.
98    This uses a per-thread variable to optimize the lookup.  */
99
100 _EXTERN_INLINE struct hurd_sigstate *
101 _hurd_self_sigstate_unlocked (void)
102 {
103   struct hurd_sigstate **location =
104     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
105   if (! *location)
106     {
107       *location = _hurd_thread_sigstate (__mach_thread_self ());
108       __mutex_unlock (&(*location)->lock);
109     }
110   return *location;
111 }
112
113 _EXTERN_INLINE struct hurd_sigstate *
114 _hurd_self_sigstate (void)
115 {
116   struct hurd_sigstate **location =
117     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
118   if (*location)
119     __mutex_lock (&(*location)->lock);
120   else
121     *location = _hurd_thread_sigstate (__mach_thread_self ());
122   return *location;
123 }
124 \f
125 /* Critical sections.
126
127    A critical section is a section of code which cannot safely be interrupted
128    to run a signal handler; for example, code that holds any lock cannot be
129    interrupted lest the signal handler try to take the same lock and
130    deadlock result.  Before entering a critical section, a thread must make
131    sure it holds its own sigstate lock.  The thread sets the
132    `critical_section' flag (which is not itself locked) to indicate the
133    lock is already held by the same thread.  Subroutines which contain
134    critical sections of their own then test this flag; if it is set, they
135    don't try to acquire the sigstate lock again, to avoid deadlock.  */
136
137 _EXTERN_INLINE void *
138 _hurd_critical_section_lock (void)
139 {
140   struct hurd_sigstate **location =
141     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
142   struct hurd_sigstate *ss = *location;
143   if (ss == NULL)
144     /* The thread variable is unset; this must be the first time we've
145        asked for it.  In this case, the critical section flag cannot
146        possible already be set.  Look up our sigstate structure the slow
147        way; this locks the sigstate lock.  */
148     ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
149   else
150     {
151       if (ss->critical_section)
152         /* Some caller higher up has already acquired the critical section
153            lock.  We need do nothing.  The null pointer we return will
154            make _hurd_critical_section_unlock (below) be a no-op.  */
155         return NULL;
156       /* Acquire the sigstate lock to prevent any signal from arriving.  */
157       __mutex_lock (&ss->lock);
158     }
159   /* Set the critical section flag so no later call will try to
160      take the sigstate lock while we already have it locked.  */
161   ss->critical_section = 1;
162   /* Return our sigstate pointer; this will be passed to
163      _hurd_critical_section_unlock to clear the critical section flag. */
164   return ss;
165 }
166
167 _EXTERN_INLINE void
168 _hurd_critical_section_unlock (void *our_lock)
169 {
170   if (our_lock == NULL)
171     /* The critical section lock was held when we began.  Do nothing.  */
172     return;
173   else
174     {
175       /* It was us who acquired the critical section lock.  Clear the
176          critical section flag and unlock the sigstate lock.  */
177       struct hurd_sigstate *ss = our_lock;
178       ss->critical_section = 0;
179       __mutex_unlock (&ss->lock);
180     }
181 }
182
183 /* Convenient macros for simple uses of critical sections.
184    These two must be used as a pair at the same C scoping level.  */
185
186 #define HURD_CRITICAL_BEGIN \
187   { void *__hurd_critical__ = _hurd_critical_section_lock ()
188 #define HURD_CRITICAL_END \
189       _hurd_critical_section_unlock (__hurd_critical__); } while (0)
190 \f
191 /* Thread listening on our message port; also called the "signal thread".  */
192
193 extern thread_t _hurd_msgport_thread;
194
195 /* Our message port.  We hold the receive right and _hurd_msgport_thread
196    listens for messages on it.  We also hold a send right, for convenience.  */
197
198 extern mach_port_t _hurd_msgport;
199
200
201 /* Thread to receive process-global signals.  */
202
203 extern thread_t _hurd_sigthread;
204
205
206 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
207 extern int _hurd_core_limit;
208 \f
209 /* Initialize the signal code, and start the signal thread.  */
210
211 extern void _hurdsig_init (void);
212
213 /* Initialize proc server-assisted fault recovery for the signal thread.  */
214
215 extern void _hurdsig_fault_init (void);
216
217 /* Raise a signal as described by SIGNO, SIGCODE and SIGERROR, on the
218    thread whose sigstate SS points to.  If SS is a null pointer, this
219    instead affects the calling thread.  */
220
221 extern void _hurd_raise_signal (struct hurd_sigstate *ss,
222                                 int signo, int sigcode, int sigerror);
223
224 /* Translate a Mach exception into a signal (machine-dependent).  */
225
226 extern void _hurd_exception2signal (int exception, int code, int subcode,
227                                     int *signo, int *sigcode, int *error);
228
229
230 /* Make the thread described by SS take the signal described by SIGNO and
231    SIGCODE.  When the signal can be considered delivered, sends a sig_post
232    reply message on REPLY_PORT indicating success.  SS->lock is held on
233    entry, and released before return.  */
234
235 extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
236                                         int signo, int sigcode, int error,
237                                         mach_port_t reply_port,
238                                         mach_msg_type_name_t reply_port_type);
239
240 /* Set up STATE and SS to handle signal SIGNO by running HANDLER.  If
241    RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to
242    finish before running the signal handler.  The handler is passed SIGNO,
243    SIGCODE, and the returned `struct sigcontext' (which resides on the
244    stack the handler will use, and which describes the state of the thread
245    encoded in STATE before running the handler).  */
246
247 struct machine_thread_all_state;
248 extern struct sigcontext *
249 _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
250                         int signo, int sigcode,
251                         int rpc_wait, struct machine_thread_all_state *state);
252
253 /* Function run by the signal thread to receive from the signal port.  */
254
255 extern void _hurd_msgport_receive (void);
256
257 /* STATE describes a thread that had intr_port set (meaning it was inside
258    HURD_EINTR_RPC), after it has been thread_abort'd.  It it looks to have
259    just completed a mach_msg_trap system call that returned
260    MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right
261    being waited on.  */
262
263 extern int _hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
264                                        mach_port_t *port);
265
266 /* Set up STATE with a thread state that, when resumed, is
267    like `longjmp (_hurd_sigthread_fault_env, 1)'.  */
268
269 extern void _hurd_initialize_fault_recovery_state (void *state);
270
271
272 /* Function run for SIGINFO when its action is SIG_DFL and the current
273    process is the session leader.  */
274
275 extern void _hurd_siginfo_handler (int);
276
277
278 /* Perform interruptible RPC CALL on PORT.
279    The call should use 
280    The args in CALL should be constant or local variable refs.
281    They may be evaluated many times, and must not change.
282    PORT must not be deallocated before this RPC is finished.  */
283 #define HURD_EINTR_RPC(port, call)                                            \
284   ({                                                                          \
285     __label__ __do_call;        /* Give this label block scope.  */           \
286     error_t __err;                                                            \
287     struct hurd_sigstate *__ss = _hurd_self_sigstate_unlocked ();             \
288     __do_call:                                                                \
289     /* Tell the signal thread that we are doing an interruptible RPC on       \
290        this port.  If we get a signal and should return EINTR, the signal     \
291        thread will set this variable to MACH_PORT_NULL.  The RPC might        \
292        return EINTR when some other thread gets a signal, in which case we    \
293        want to restart our call.  */                                          \
294     __ss->intr_port = (port);                                                 \
295     /* A signal may arrive here, after intr_port is set, but before the       \
296        mach_msg system call.  The signal handler might do an interruptible    \
297        RPC, and clobber intr_port; then it would not be set properly when     \
298        we actually did send the RPC, and a later signal wouldn't interrupt    \
299        that RPC.  So, _hurd_setup_sighandler saves intr_port in the           \
300        sigcontext, and sigreturn restores it.  */                             \
301     switch (__err = (call))                                                   \
302       {                                                                       \
303       case EINTR:               /* RPC went out and was interrupted.  */      \
304       case MACH_SEND_INTERRUPTED: /* RPC didn't get out.  */                  \
305         if (__ss->intr_port != MACH_PORT_NULL)                                \
306           /* If this signal was for us and it should interrupt calls, the     \
307              signal thread will have cleared SS->intr_port.  Since it's not   \
308              cleared, the signal was for another thread, or SA_RESTART is     \
309              set.  Restart the interrupted call.  */                          \
310           goto __do_call;                                                     \
311         /* FALLTHROUGH */                                                     \
312       case MACH_RCV_PORT_DIED:                                                \
313         /* Server didn't respond to interrupt_operation,                      \
314            so the signal thread destroyed the reply port.  */                 \
315         __err = EINTR;                                                        \
316         break;                                                                \
317       default:                  /* Quiet -Wswitch-enum.  */                   \
318       }                                                                       \
319     __ss->intr_port = MACH_PORT_NULL;                                         \
320     __err;                                                                    \
321   })                                                                          \
322
323
324 /* Mask of signals that cannot be caught, blocked, or ignored.  */
325 #define _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
326
327 /* Do an RPC to a process's message port.
328
329    Each argument is an expression which returns an error code; each
330    expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
331    fetch the appropriate message port and store it in the local variable
332    `msgport'.  FETCH_REFPORT_EXPR should fetch the appropriate message port
333    and store it in the local variable `refport' (if no reference port is
334    needed in the call, then FETCH_REFPORT_EXPR should be simply
335    KERN_SUCCESS or 0).  Both of these are assumed to create user
336    references, which this macro deallocates.  RPC_EXPR should perform the
337    desired RPC operation using `msgport' and `refport'.
338
339    The reason for the complexity is that a process's message port and
340    reference port may change between fetching those ports and completing an
341    RPC using them (usually they change only when a process execs).  The RPC
342    will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
343    send the RPC request; or with MIG_SERVER_DIED if the msgport was
344    destroyed after we sent the RPC request but before it was serviced.  In
345    either of these cases, we retry the entire operation, discarding the old
346    message and reference ports and fetch them anew.  */
347
348 #define HURD_MSGPORT_RPC(fetch_msgport_expr, fetch_refport_expr, rpc_expr)   \
349 ({                                                                            \
350     error_t __err;                                                            \
351     mach_port_t msgport, refport = MACH_PORT_NULL;                            \
352     do                                                                        \
353       {                                                                       \
354         /* Get the message port.  */                                          \
355         if (__err = (fetch_msgport_expr))                                     \
356           break;                                                              \
357         /* Get the reference port.  */                                        \
358         if (__err = (fetch_refport_expr))                                     \
359           {                                                                   \
360             /* Couldn't get it; deallocate MSGPORT and fail.  */              \
361             __mach_port_deallocate (__mach_task_self (), msgport);            \
362             break;                                                            \
363           }                                                                   \
364         __err = (rpc_expr);                                                   \
365         __mach_port_deallocate (__mach_task_self (), msgport);                \
366         if (refport != MACH_PORT_NULL)                                        \
367           __mach_port_deallocate (__mach_task_self (), refport);              \
368       } while (__err == MACH_SEND_INVALID_DEST ||                             \
369                __err == MIG_SERVER_DIED);                                     \
370     __err;                                                                    \
371 })
372 \f
373 /* Some other parts of the library need to preempt signals, to detect
374    errors that should not result in a POSIX signal.  For example, when
375    some mapped region of memory is used, an extraneous SIGSEGV might be
376    generated when the mapping server returns an error for a page fault.  */
377
378 struct hurd_signal_preempt
379   {
380     /* Function to examine a thread receiving a given signal.  The handler
381        is called even for blocked signals.  This function is run in the
382        signal thread, with THREAD's sigstate locked; it should be as simple
383        and robust as possible.  THREAD is the thread which is about to
384        receive the signal.  SIGNO and SIGCODE would be passed to the normal
385        handler.
386
387        If the return value is SIG_DFL, normal signal processing continues.
388        If it is SIG_IGN, the signal is ignored.
389        Any other value is used in place of the normal handler.  */
390     sighandler_t (*handler) (thread_t thread, int signo, int sigcode);
391     int first, last;            /* Range of sigcodes this handler wants.  */
392     struct hurd_signal_preempt *next; /* Next handler on the chain. */
393   };
394
395 extern struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
396 extern struct mutex _hurd_signal_preempt_lock;
397
398
399 #endif  /* hurd/signal.h */