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