diff options
author | Richard Braun <rbraun@sceen.net> | 2013-12-23 12:03:12 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2013-12-23 12:03:12 +0100 |
commit | b01bde4c4d7571d7323b0fbbae6c5b2da5df978c (patch) | |
tree | 3808b259f4d3db55fa74452e1db75fdcd43ccaf4 /hurd | |
parent | b1786ee5b8fbe09663596c7554f5322d79eee25b (diff) | |
parent | 512a1659ed7c20fa94e32ceb9b3bdf715b1253e9 (diff) |
Merge branch 't/sigstate_thread_reference' into refs/top-bases/tschwinge/Roger_Whittaker
Conflicts:
hurd/hurd/signal.h
Diffstat (limited to 'hurd')
-rw-r--r-- | hurd/hurd/signal.h | 17 | ||||
-rw-r--r-- | hurd/hurdsig.c | 17 |
2 files changed, 28 insertions, 6 deletions
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index 2a2238c7df..607b05919c 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -63,7 +63,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. */ @@ -117,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); @@ -160,7 +164,11 @@ _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { if (_hurd_sigstate == NULL) - _hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + { + thread_t self = __mach_thread_self (); + _hurd_sigstate = _hurd_thread_sigstate (self); + __mach_port_deallocate (__mach_task_self (), self); + } return _hurd_sigstate; } #endif @@ -201,11 +209,14 @@ _hurd_critical_section_lock (void) ss = _hurd_sigstate; 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. */ - ss = _hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + ss = _hurd_sigstate = _hurd_thread_sigstate (self); + __mach_port_deallocate (__mach_task_self (), self); } if (! __spin_try_lock (&ss->critical_section_lock)) diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 2d7b003454..661d3b36e3 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -108,6 +108,8 @@ _hurd_thread_sigstate (thread_t thread) } else { + error_t err; + /* Use the global actions as a default for new threads. */ struct hurd_sigstate *s = _hurd_global_sigstate; if (s) @@ -121,6 +123,11 @@ _hurd_thread_sigstate (thread_t thread) ss->next = _hurd_sigstates; _hurd_sigstates = ss; + + err = __mach_port_mod_refs (__mach_task_self (), thread, + MACH_PORT_RIGHT_SEND, 1); + if (err) + __libc_fatal ("hurd: Can't add reference on Mach thread\n"); } } __mutex_unlock (&_hurd_siglock); @@ -128,8 +135,7 @@ _hurd_thread_sigstate (thread_t thread) } /* Destroy a sigstate structure. Called by libpthread just before the - * corresponding thread is terminated (the kernel thread port must remain valid - * until this function is called.) */ + * corresponding thread is terminated. */ void _hurd_sigstate_delete (thread_t thread) { @@ -146,7 +152,12 @@ _hurd_sigstate_delete (thread_t thread) __mutex_unlock (&_hurd_siglock); if (ss) - free (ss); + { + if (ss->thread != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), ss->thread); + + free (ss); + } } /* Make SS a global receiver, with pthread signal semantics. */ |