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