summaryrefslogtreecommitdiff
path: root/hurd/hurd
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-12-23 11:57:58 +0100
committerRichard Braun <rbraun@sceen.net>2013-12-23 11:57:58 +0100
commit512a1659ed7c20fa94e32ceb9b3bdf715b1253e9 (patch)
tree27e275d15a8921473c57e4964c7683dcebcb82be /hurd/hurd
parente631e5064e2efc594149a07e726ed086f2d8b84d (diff)
Hurd: make sigstates hold a reference on thread ports
This change is required in order to correctly release per-thread resources. Directly reusing the threading library reference isn't possible since the sigstate is also used early in the main thread, before threading is initialized. * hurd/hurd/signal.h (_hurd_self_sigstate): Drop thread reference after calling _hurd_thread_sigstate. (_hurd_critical_section_lock): Likewise. * hurd/hurdsig.c (_hurd_thread_sigstate): Add a reference on the thread. (_hurd_sigstate_delete): Drop thread reference.
Diffstat (limited to 'hurd/hurd')
-rw-r--r--hurd/hurd/signal.h17
1 files changed, 14 insertions, 3 deletions
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index db60e6f0a1..1d1218a88a 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -64,7 +64,9 @@ 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. */
@@ -118,7 +120,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);
@@ -161,7 +165,11 @@ _hurd_self_sigstate (void)
struct hurd_sigstate **location =
(void *) __hurd_threadvar_location (_HURD_THREADVAR_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;
}
@@ -192,11 +200,14 @@ _hurd_critical_section_lock (void)
struct 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 ());
+ ss = *location = _hurd_thread_sigstate (self);
+ __mach_port_deallocate (__mach_task_self (), self);
__spin_unlock (&ss->lock);
}