New file.
[kopensolaris-gnu/glibc.git] / hurd / hurd / signal.h
1 /* Implementing POSIX.1 signals under the Hurd.
2 Copyright (C) 1993, 1994, 1995, 1996 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 struct hurd_signal_preempter;   /* <hurd/sigpreempt.h> */
44
45
46 /* Per-thread signal state.  */
47
48 struct hurd_sigstate
49   {
50     spin_lock_t lock;           /* Locks most of the rest of the structure.  */
51
52     int critical_section;       /* Nonzero if in critical section.  */
53
54     thread_t thread;
55     struct hurd_sigstate *next; /* Linked-list of thread sigstates.  */
56
57     sigset_t blocked;           /* What signals are blocked.  */
58     sigset_t pending;           /* Pending signals, possibly blocked.  */
59     struct sigaction actions[NSIG];
60     struct sigaltstack sigaltstack;
61
62     /* Chain of thread-local signal preempters; see <hurd/sigpreempt.h>.
63        Each element of this chain is in local stack storage, and the chain
64        parallels the stack: the head of this chain is in the innermost
65        stack frame, and each next element in an outermore frame.  */
66     struct hurd_signal_preempter *preempters;
67
68     struct
69       {
70         /* For each signal that may be pending, the
71            sigcode and error code to deliver it with.  */
72         long int code;
73         error_t error;
74       } pending_data[NSIG];
75
76     /* If `suspended' is set when this thread gets a signal,
77        the signal thread sends an empty message to it.  */
78     mach_port_t suspended;
79
80     /* The following members are not locked.  They are used only by this
81        thread, or by the signal thread with this thread suspended.  */
82
83     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
84
85     /* If this is not null, the thread is in sigreturn awaiting delivery of
86        pending signals.  This context (the machine-dependent portions only)
87        will be passed to sigreturn after running the handler for a pending
88        signal, instead of examining the thread state.  */
89     struct sigcontext *context;
90
91     /* This is the head of the thread's list of active resources; see
92        <hurd/userlink.h> for details.  This member is only used by the
93        thread itself, and always inside a critical section.  */
94     struct hurd_userlink *active_resources;
95
96     /* These are locked normally.  */
97     int cancel;                 /* Flag set by hurd_thread_cancel.  */
98     void (*cancel_hook) (void); /* Called on cancellation.  */
99   };
100
101 /* Linked list of states of all threads whose state has been asked for.  */
102
103 extern struct hurd_sigstate *_hurd_sigstates;
104
105 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
106
107 /* Get the sigstate of a given thread, taking its lock.  */
108
109 extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
110
111 /* Get the sigstate of the current thread.
112    This uses a per-thread variable to optimize the lookup.  */
113
114 extern struct hurd_sigstate *_hurd_self_sigstate (void)
115      /* This declaration tells the compiler that the value is constant.
116         We assume this won't be called twice from the same stack frame
117         by different threads.  */
118      __attribute__ ((__const__));
119
120 _EXTERN_INLINE struct hurd_sigstate *
121 _hurd_self_sigstate (void)
122 {
123   struct hurd_sigstate **location =
124     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
125   if (*location == NULL)
126     *location = _hurd_thread_sigstate (__mach_thread_self ());
127   return *location;
128 }
129 \f
130 /* Thread listening on our message port; also called the "signal thread".  */
131
132 extern thread_t _hurd_msgport_thread;
133
134 /* Our message port.  We hold the receive right and _hurd_msgport_thread
135    listens for messages on it.  We also hold a send right, for convenience.  */
136
137 extern mach_port_t _hurd_msgport;
138
139
140 /* Thread to receive process-global signals.  */
141
142 extern thread_t _hurd_sigthread;
143
144
145 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
146 extern int _hurd_core_limit;
147 \f
148 /* Critical sections.
149
150    A critical section is a section of code which cannot safely be interrupted
151    to run a signal handler; for example, code that holds any lock cannot be
152    interrupted lest the signal handler try to take the same lock and
153    deadlock result.  */
154
155 _EXTERN_INLINE void *
156 _hurd_critical_section_lock (void)
157 {
158   struct hurd_sigstate **location =
159     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
160   struct hurd_sigstate *ss = *location;
161   if (ss == NULL)
162     /* The thread variable is unset; this must be the first time we've
163        asked for it.  In this case, the critical section flag cannot
164        possible already be set.  Look up our sigstate structure the slow
165        way; this locks the sigstate lock.  */
166     ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
167   else
168     __spin_lock (&ss->lock);
169
170   if (ss->critical_section)
171     {
172       /* We are already in a critical section, so do nothing.  */
173       __spin_unlock (&ss->lock);
174       return NULL;
175     }
176
177   /* Set the critical section flag so no signal handler will run.  */
178   ss->critical_section = 1;
179   __spin_unlock (&ss->lock);
180
181   /* Return our sigstate pointer; this will be passed to
182      _hurd_critical_section_unlock to clear the critical section flag. */
183   return ss;
184 }
185
186 _EXTERN_INLINE void
187 _hurd_critical_section_unlock (void *our_lock)
188 {
189   if (our_lock == NULL)
190     /* The critical section lock was held when we began.  Do nothing.  */
191     return;
192   else
193     {
194       /* It was us who acquired the critical section lock.  Clear the
195          critical section flag.  */
196       struct hurd_sigstate *ss = our_lock;
197       sigset_t pending;
198       __spin_lock (&ss->lock);
199       ss->critical_section = 0;
200       pending = ss->pending & ~ss->blocked;
201       __spin_unlock (&ss->lock);
202       if (pending)
203         /* There are unblocked signals pending, which weren't
204            delivered because we were in the critical section.
205            Tell the signal thread to deliver them now.  */
206         __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
207     }
208 }
209
210 /* Convenient macros for simple uses of critical sections.
211    These two must be used as a pair at the same C scoping level.  */
212
213 #define HURD_CRITICAL_BEGIN \
214   { void *__hurd_critical__ = _hurd_critical_section_lock ()
215 #define HURD_CRITICAL_END \
216       _hurd_critical_section_unlock (__hurd_critical__); } while (0)
217 \f
218 /* Initialize the signal code, and start the signal thread.  */
219
220 extern void _hurdsig_init (void);
221
222 /* Initialize proc server-assisted fault recovery for the signal thread.  */
223
224 extern void _hurdsig_fault_init (void);
225
226 /* Raise a signal as described by SIGNO, SIGCODE and SIGERROR, on the
227    thread whose sigstate SS points to.  If SS is a null pointer, this
228    instead affects the calling thread.  */
229
230 extern void _hurd_raise_signal (struct hurd_sigstate *ss,
231                                 int signo, long int sigcode, int sigerror);
232
233 /* Translate a Mach exception into a signal (machine-dependent).  */
234
235 extern void _hurd_exception2signal (int exception, int code, int subcode,
236                                     int *signo, long int *sigcode, int *error);
237
238
239 /* Make the thread described by SS take the signal described by SIGNO and
240    SIGCODE.  If the process is traced, this will in fact stop with a SIGNO
241    as the stop signal unless UNTRACED is nonzero.  When the signal can be
242    considered delivered, sends a sig_post reply message on REPLY_PORT
243    indicating success.  SS is not locked.  */
244
245 extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
246                                         int signo, long int sigcode, int error,
247                                         mach_port_t reply_port,
248                                         mach_msg_type_name_t reply_port_type,
249                                         int untraced);
250
251 /* Set up STATE and SS to handle signal SIGNO by running HANDLER.  If
252    RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to
253    finish before running the signal handler.  The handler is passed SIGNO,
254    SIGCODE, and the returned `struct sigcontext' (which resides on the
255    stack the handler will use, and which describes the state of the thread
256    encoded in STATE before running the handler).  */
257
258 struct machine_thread_all_state;
259 extern struct sigcontext *
260 _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
261                         int signo, long int sigcode,
262                         int rpc_wait, struct machine_thread_all_state *state);
263
264 /* Function run by the signal thread to receive from the signal port.  */
265
266 extern void _hurd_msgport_receive (void);
267
268 /* Set up STATE with a thread state that, when resumed, is
269    like `longjmp (_hurd_sigthread_fault_env, 1)'.  */
270
271 extern void _hurd_initialize_fault_recovery_state (void *state);
272
273 /* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'.  */
274
275 extern void _hurd_longjmp_thread_state (void *state, jmp_buf env, int value);
276
277 /* Function run for SIGINFO when its action is SIG_DFL and the current
278    process is the session leader.  */
279
280 extern void _hurd_siginfo_handler (int);
281
282
283 /* Milliseconds to wait for an interruptible RPC to return after
284    `interrupt_operation'.  */
285
286 extern mach_msg_timeout_t _hurd_interrupted_rpc_timeout;
287
288
289 /* Mask of signals that cannot be caught, blocked, or ignored.  */
290 #define _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
291
292 /* Do an RPC to a process's message port.
293
294    Each argument is an expression which returns an error code; each
295    expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
296    fetch the appropriate message port and store it in the local variable
297    `msgport'; it will be deallocated after use.  FETCH_REFPORT_EXPR should
298    fetch the appropriate message port and store it in the local variable
299    `refport' (if no reference port is needed in the call, then
300    FETCH_REFPORT_EXPR should be simply KERN_SUCCESS or 0); if
301    DEALLOC_REFPORT evaluates to nonzero it will be deallocated after use,
302    otherwise the FETCH_REFPORT_EXPR must take care of user references to
303    `refport'.  RPC_EXPR should perform the desired RPC operation using
304    `msgport' and `refport'.
305
306    The reason for the complexity is that a process's message port and
307    reference port may change between fetching those ports and completing an
308    RPC using them (usually they change only when a process execs).  The RPC
309    will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
310    send the RPC request; or with MIG_SERVER_DIED if the msgport was
311    destroyed after we sent the RPC request but before it was serviced.  In
312    either of these cases, we retry the entire operation, discarding the old
313    message and reference ports and fetch them anew.  */
314
315 #define HURD_MSGPORT_RPC(fetch_msgport_expr,                                  \
316                          fetch_refport_expr, dealloc_refport,                 \
317                          rpc_expr)                                            \
318 ({                                                                            \
319     error_t __err;                                                            \
320     mach_port_t msgport, refport = MACH_PORT_NULL;                            \
321     do                                                                        \
322       {                                                                       \
323         /* Get the message port.  */                                          \
324         if (__err = (fetch_msgport_expr))                                     \
325           break;                                                              \
326         /* Get the reference port.  */                                        \
327         if (__err = (fetch_refport_expr))                                     \
328           {                                                                   \
329             /* Couldn't get it; deallocate MSGPORT and fail.  */              \
330             __mach_port_deallocate (__mach_task_self (), msgport);            \
331             break;                                                            \
332           }                                                                   \
333         __err = (rpc_expr);                                                   \
334         __mach_port_deallocate (__mach_task_self (), msgport);                \
335         if ((dealloc_refport) && refport != MACH_PORT_NULL)                   \
336           __mach_port_deallocate (__mach_task_self (), refport);              \
337       } while (__err == MACH_SEND_INVALID_DEST ||                             \
338                __err == MIG_SERVER_DIED);                                     \
339     __err;                                                                    \
340 })
341
342
343 #endif  /* hurd/signal.h */