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