Formerly hurd/hurd/signal.h.~6~
[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 #include <mach/mach_types.h>
30 #include <mach/port.h>
31 #include <mach/message.h>
32 #include <hurd/hurd_types.h>
33 #include <signal.h>
34 #include <errno.h>
35
36
37 /* Per-thread signal state.  */
38
39 struct hurd_sigstate
40   {
41     /* XXX should be in cthread variable (?) */
42     thread_t thread;
43     struct hurd_sigstate *next; /* Linked-list of thread sigstates.  */
44
45 #ifdef noteven
46     struct mutex lock;          /* Locks the rest of this structure.  */
47 #endif
48     sigset_t blocked;
49     sigset_t pending;
50     struct sigaction actions[NSIG];
51     struct sigaltstack sigaltstack;
52     int sigcodes[NSIG];         /* Codes for pending signals.  */
53
54     int suspended;              /* If nonzero, sig_post signals `arrived'.  */
55 #ifdef noteven
56     struct condition arrived;
57 #endif
58
59 #if 0
60     int vforked;                /* Nonzero if this thread is a vfork child.  */
61     struct
62       {
63         process_t proc;
64         file_t ccdir, cwdir, crdir, auth;
65         mode_t umask;
66         int ctty_fstype;
67         fsid_t ctty_fsid;
68         ino_t ctty_fileid;
69         struct hurd_dtable *dtable;
70         jmp_buf continuation;
71       } *vfork_saved;
72 #endif
73
74     /* Not locked.  Used only by this thread,
75        or by signal thread with this thread suspended.  */
76     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
77     volatile int intr_restart;  /* If nonzero, restart interrupted RPC.  */
78   };
79
80 /* Linked list of states of all threads whose state has been asked for.  */
81
82 extern struct hurd_sigstate *_hurd_sigstates;
83
84 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
85
86 /* Get the sigstate of a given thread, taking its lock.  */
87
88 extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
89 \f
90 /* Thread listening on our message port; also called the "signal thread".  */
91
92 extern thread_t _hurd_msgport_thread;
93
94 /* Our message port.  We hold the receive right and _hurd_msgport_thread
95    listens for messages on it.  We also hold a send right, for convenience.  */
96
97 extern mach_port_t _hurd_msgport;
98
99
100 /* Thread to receive process-global signals.  */
101
102 extern thread_t _hurd_sigthread;
103
104
105 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
106 extern int _hurd_core_limit;
107 \f
108 /* Translate a Mach exception into a signal (machine-dependent).  */
109
110 extern void _hurd_exception2signal (int exception, int code, int subcode,
111                                     int *signo, int *sigcode);
112
113
114 /* Make the thread described by SS take the signal described by SIGNO and
115    SIGCODE.  SS->lock is held on entry, and released before return.  */
116
117 extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
118                                         int signo, int sigcode);
119
120 /* Set up STATE to handle signal SIGNO by running HANDLER.  FLAGS is the
121    `sa_flags' member from `struct sigaction'.  If the SA_ONSTACK bit is
122    set, *ALTSTACK describes the alternate signal stack to use.  The handler
123    is passed SIGNO, SIGCODE, and the returned `struct sigcontext' (which
124    resides on the stack the handler will use, and which describes the state
125    of the thread encoded in STATE before running the handler).  */
126
127 extern struct sigcontext *_hurd_setup_sighandler (int flags,
128                                                   __sighandler_t handler,
129                                                   struct sigaltstack *altstack,
130                                                   int signo, int sigcode,
131                                                   void *state);
132
133 /* Function run by the signal thread to receive from the signal port.  */
134
135 extern void _hurd_msgport_receive (void);
136
137 /* Return nonzero if STATE indicates a thread that is blocked in a mach_msg
138    system call (machine-dependent).  */
139
140 extern int _hurd_thread_state_msging_p (void *state);
141
142 /* Start THREAD running FUNCTION (machine-dependent).  */
143
144 extern kern_return_t _hurd_start_sigthread (thread_t thread,
145                                             void (*function) (void));
146
147 /* Set up STATE with a thread state that, when resumed, is
148    like `longjmp (_hurd_sigthread_fault_env, 1)'.  */
149
150 extern void _hurd_initialize_fault_recovery_state (void *state);
151
152
153 /* Function run for SIGINFO when its action is SIG_DFL and the current
154    process is the session leader.  */
155
156 extern void _hurd_siginfo_handler (int);
157
158
159 #ifdef notyet
160 /* Perform interruptible RPC CALL on PORT.
161    The args in CALL should be constant or local variable refs.
162    They may be evaluated many times, and must not change.
163    PORT must not be deallocated before this RPC is finished.  */
164 #define HURD_EINTR_RPC(port, call) \
165   ({
166     error_t __err;
167     struct hurd_sigstate *__ss
168       = _hurd_thread_sigstate (__mach_thread_self ());
169     __mutex_unlock (&__ss->lock); /* Lock not needed.  */
170     /* If we get a signal and should return EINTR, the signal thread will
171        clear this.  The RPC might return EINTR when some other thread gets
172        a signal, in which case we want to restart our call.  */
173     __ss->intr_restart = 1;
174     /* This one needs to be last.  A signal can arrive before here,
175        and if intr_port were set before intr_restart is
176        initialized, the signal thread would get confused.  */
177     __ss->intr_port = (port);
178     /* A signal may arrive here, after intr_port is set,
179        but before the mach_msg system call.  The signal handler might do an
180        interruptible RPC, and clobber intr_port; then it would not be set
181        properly when we actually did send the RPC, and a later signal
182        wouldn't interrupt that RPC.  So, _hurd_run_sighandler saves
183        intr_port in the sigcontext, and sigreturn restores it.  */
184   __do_call:
185     switch (__err = (call))
186       {
187       case EINTR:               /* RPC went out and was interrupted.  */
188       case MACH_SEND_INTERRUPTED: /* RPC didn't get out.  */
189         if (__ss->intr_restart)
190           /* Restart the interrupted call.  */
191           goto __do_call;
192         /* FALLTHROUGH */
193       case MACH_RCV_PORT_DIED:
194         /* Server didn't respond to interrupt_operation,
195            so the signal thread destroyed the reply port.  */
196         __err = EINTR;
197         break;
198       }
199     __ss->intr_port = MACH_PORT_NULL;
200     __err;
201   })
202
203 #endif /* notyet */
204
205 /* Mask of signals that cannot be caught, blocked, or ignored.  */
206 #define _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
207
208 /* Do an RPC to a process's message port.
209
210    Each argument is an expression which returns an error code; each
211    expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
212    fetch the appropriate message port and store it in the local variable
213    `msgport'.  FETCH_REFPORT_EXPR should fetch the appropriate message port
214    and store it in the local variable `refport' (if no reference port is
215    needed in the call, then FETCH_REFPORT_EXPR should be simply
216    KERN_SUCCESS or 0).  Both of these are assumed to create user
217    references, which this macro deallocates.  RPC_EXPR should perform the
218    desired RPC operation using `msgport' and `refport'.
219
220    The reason for the complexity is that a process's message port and
221    reference port may change between fetching those ports and completing an
222    RPC using them (usually they change only when a process execs).  The RPC
223    will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
224    send the RPC request; or with MIG_SERVER_DIED if the msgport was
225    destroyed after we sent the RPC request but before it was serviced.  In
226    either of these cases, we retry the entire operation, discarding the old
227    message and reference ports and fetch them anew.  */
228
229 #define HURD_MSGPORT_RPC(fetch_msgport_expr, fetch_refport_expr, rpc_expr)   \
230 ({                                                                            \
231     error_t __err;                                                            \
232     mach_port_t msgport, refport = MACH_PORT_NULL;                            \
233     do                                                                        \
234       {                                                                       \
235         /* Get the message port.  */                                          \
236         if (__err = (fetch_msgport_expr))                                     \
237           break;                                                              \
238         /* Get the reference port.  */                                        \
239         if (__err = (fetch_refport_expr))                                     \
240           {                                                                   \
241             /* Couldn't get it; deallocate MSGPORT and fail.  */              \
242             __mach_port_deallocate (__mach_task_self (), msgport);            \
243             break;                                                            \
244           }                                                                   \
245         __err = (rpc_expr);                                                   \
246         __mach_port_deallocate (__mach_task_self (), msgport);                \
247         if (refport != MACH_PORT_NULL)                                        \
248           __mach_port_deallocate (__mach_task_self (), refport);              \
249       } while (__err != MACH_SEND_INVALID_DEST &&                             \
250                __err != MIG_SERVER_DIED);                                     \
251     __err;                                                                    \
252 })
253
254
255 #endif  /* hurd/signal.h */