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