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