summaryrefslogtreecommitdiff
path: root/hurd/hurd/signal.h
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/hurd/signal.h')
-rw-r--r--hurd/hurd/signal.h91
1 files changed, 71 insertions, 20 deletions
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index 9798681853..73bf976b7d 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -40,7 +40,6 @@
#include <cthreads.h> /* For `struct mutex'. */
#include <setjmp.h> /* For `jmp_buf'. */
#include <spin-lock.h>
-#include <hurd/threadvar.h> /* We cache sigstate in a threadvar. */
struct hurd_signal_preemptor; /* <hurd/sigpreempt.h> */
@@ -64,12 +63,20 @@ struct hurd_sigstate
spin_lock_t lock; /* Locks most of the rest of the structure. */
+ /* The signal state holds a reference on the thread port. */
thread_t thread;
+
struct hurd_sigstate *next; /* Linked-list of thread sigstates. */
sigset_t blocked; /* What signals are blocked. */
sigset_t pending; /* Pending signals, possibly blocked. */
+
+ /* Signal handlers. ACTIONS[0] is used to mark the threads with POSIX
+ semantics: if sa_handler is SIG_IGN instead of SIG_DFL, this thread
+ will receive global signals and use the process-wide action vector
+ instead of this one. */
struct sigaction actions[NSIG];
+
struct sigaltstack sigaltstack;
/* Chain of thread-local signal preemptors; see <hurd/sigpreempt.h>.
@@ -112,7 +119,9 @@ extern struct hurd_sigstate *_hurd_sigstates;
extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates. */
-/* Get the sigstate of a given thread, taking its lock. */
+/* Get the sigstate of a given thread. If there was no sigstate for
+ the thread, one is created, and the thread gains a reference. If
+ the given thread is MACH_PORT_NULL, return the global sigstate. */
extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
@@ -125,19 +134,44 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void)
by different threads. */
__attribute__ ((__const__));
+/* Process-wide signal state. */
+
+extern struct hurd_sigstate *_hurd_global_sigstate;
+
+/* Mark the given thread as a process-wide signal receiver. */
+
+extern void _hurd_sigstate_set_global_rcv (struct hurd_sigstate *ss);
+
+/* A thread can either use its own action vector and pending signal set
+ or use the global ones, depending on wether it has been marked as a
+ global receiver. The accessors below take that into account. */
+
+extern void _hurd_sigstate_lock (struct hurd_sigstate *ss);
+extern struct sigaction *_hurd_sigstate_actions (struct hurd_sigstate *ss);
+extern sigset_t _hurd_sigstate_pending (const struct hurd_sigstate *ss);
+extern void _hurd_sigstate_unlock (struct hurd_sigstate *ss);
+
+/* Used by libpthread to remove stale sigstate structures. */
+extern void _hurd_sigstate_delete (thread_t thread);
+
#ifndef _HURD_SIGNAL_H_EXTERN_INLINE
#define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline
#endif
+#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc
_HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate *
_hurd_self_sigstate (void)
{
- struct hurd_sigstate **location =
- (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
+ struct hurd_sigstate **location = &THREAD_SELF->_hurd_sigstate;
if (*location == NULL)
- *location = _hurd_thread_sigstate (__mach_thread_self ());
+ {
+ thread_t self = __mach_thread_self ();
+ *location = _hurd_thread_sigstate (self);
+ __mach_port_deallocate (__mach_task_self (), self);
+ }
return *location;
}
+#endif
/* Thread listening on our message port; also called the "signal thread". */
@@ -148,12 +182,6 @@ extern thread_t _hurd_msgport_thread;
extern mach_port_t _hurd_msgport;
-
-/* Thread to receive process-global signals. */
-
-extern thread_t _hurd_sigthread;
-
-
/* Resource limit on core file size. Enforced by hurdsig.c. */
extern int _hurd_core_limit;
@@ -164,20 +192,33 @@ extern int _hurd_core_limit;
interrupted lest the signal handler try to take the same lock and
deadlock result. */
+void *_hurd_critical_section_lock (void);
+
+#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc
_HURD_SIGNAL_H_EXTERN_INLINE void *
_hurd_critical_section_lock (void)
{
- struct hurd_sigstate **location =
- (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
- struct hurd_sigstate *ss = *location;
+ struct hurd_sigstate **location;
+ struct hurd_sigstate *ss;
+
+#ifdef __LIBC_NO_TLS
+ if (__LIBC_NO_TLS())
+ /* TLS is currently initializing, no need to enter critical section. */
+ return NULL;
+#endif
+
+ location = &THREAD_SELF->_hurd_sigstate;
+ ss = *location;
if (ss == NULL)
{
+ thread_t self = __mach_thread_self ();
+
/* The thread variable is unset; this must be the first time we've
asked for it. In this case, the critical section flag cannot
possible already be set. Look up our sigstate structure the slow
- way; this locks the sigstate lock. */
- ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
- __spin_unlock (&ss->lock);
+ way. */
+ ss = *location = _hurd_thread_sigstate (self);
+ __mach_port_deallocate (__mach_task_self (), self);
}
if (! __spin_try_lock (&ss->critical_section_lock))
@@ -189,7 +230,11 @@ _hurd_critical_section_lock (void)
_hurd_critical_section_unlock to unlock it. */
return ss;
}
+#endif
+
+void _hurd_critical_section_unlock (void *our_lock);
+#if defined __USE_EXTERN_INLINES && defined _LIBC && !defined NOT_IN_libc
_HURD_SIGNAL_H_EXTERN_INLINE void
_hurd_critical_section_unlock (void *our_lock)
{
@@ -201,10 +246,10 @@ _hurd_critical_section_unlock (void *our_lock)
/* It was us who acquired the critical section lock. Unlock it. */
struct hurd_sigstate *ss = our_lock;
sigset_t pending;
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
__spin_unlock (&ss->critical_section_lock);
- pending = ss->pending & ~ss->blocked;
- __spin_unlock (&ss->lock);
+ pending = _hurd_sigstate_pending(ss) & ~ss->blocked;
+ _hurd_sigstate_unlock (ss);
if (! __sigisemptyset (&pending))
/* There are unblocked signals pending, which weren't
delivered because we were in the critical section.
@@ -212,6 +257,7 @@ _hurd_critical_section_unlock (void *our_lock)
__msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
}
}
+#endif
/* Convenient macros for simple uses of critical sections.
These two must be used as a pair at the same C scoping level. */
@@ -242,6 +288,11 @@ extern int _hurd_raise_signal (struct hurd_sigstate *ss, int signo,
extern void _hurd_exception2signal (struct hurd_signal_detail *detail,
int *signo);
+/* Translate a Mach exception into a signal with a legacy sigcode. */
+
+extern void _hurd_exception2signal_legacy (struct hurd_signal_detail *detail,
+ int *signo);
+
/* Make the thread described by SS take the signal described by SIGNO and
DETAIL. If the process is traced, this will in fact stop with a SIGNO