summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlávio Cruz <flaviocruz@gmail.com>2015-08-28 01:34:01 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2015-08-28 01:37:51 +0200
commit2c1cccc529737527ad9ef981952d2c14d3dd13ec (patch)
treed39bfb7d7ed794c8bbb092f3245fe5b0522460da
parenteec39c5f50fb1b4e2025025773f77293f3466492 (diff)
Make sure the reply port's reference is released when the thread needs to be halted.
* kern/thread.h (thread_halt_self): Add continuation_t parameter. * kern/thread.c (thread_halt_self): Pass continuation_t parameter to thread_block instead of thread_exception_return. * kern/ast.c (ast_taken): Pass thread_exception_return to thread_halt_self. * kern/profile.c (profile_thread): Likewise. * kern/exception.c (exception_no_server): Likewise. (thread_release_and_exception_return): New function. (exception_raise_continue_slow): Pass thread_release_and_exception_return to thread_halt_self.
-rw-r--r--kern/ast.c2
-rw-r--r--kern/exception.c32
-rw-r--r--kern/profile.c2
-rw-r--r--kern/thread.c4
-rw-r--r--kern/thread.h2
5 files changed, 33 insertions, 9 deletions
diff --git a/kern/ast.c b/kern/ast.c
index 4b9d63d6..2772ed3e 100644
--- a/kern/ast.c
+++ b/kern/ast.c
@@ -96,7 +96,7 @@ ast_taken(void)
if (self != current_processor()->idle_thread) {
#ifndef MIGRATING_THREADS
while (thread_should_halt(self))
- thread_halt_self();
+ thread_halt_self(thread_exception_return);
#endif
/*
diff --git a/kern/exception.c b/kern/exception.c
index 6cb3bfbf..63a63d66 100644
--- a/kern/exception.c
+++ b/kern/exception.c
@@ -231,7 +231,7 @@ exception_no_server(void)
*/
while (thread_should_halt(self))
- thread_halt_self();
+ thread_halt_self(thread_exception_return);
#if 0
@@ -257,7 +257,7 @@ exception_no_server(void)
*/
(void) task_terminate(self->task);
- thread_halt_self();
+ thread_halt_self(thread_exception_return);
panic("terminating the task didn't kill us");
/*NOTREACHED*/
}
@@ -848,6 +848,26 @@ exception_raise_continue(void)
}
/*
+ * Routine: thread_release_and_exception_return
+ * Purpose:
+ * Continue after thread was halted.
+ * Conditions:
+ * Nothing locked. We are running on a new kernel stack and
+ * control goes back to thread_exception_return.
+ * Returns:
+ * Doesn't return.
+ */
+static void
+thread_release_and_exception_return(void)
+{
+ ipc_thread_t self = current_thread();
+ /* reply port must be released */
+ ipc_port_release(self->ith_port);
+ thread_exception_return();
+ /*NOTREACHED*/
+}
+
+/*
* Routine: exception_raise_continue_slow
* Purpose:
* Continue after finishing an ipc_mqueue_receive
@@ -876,10 +896,14 @@ exception_raise_continue_slow(
*/
while (thread_should_halt(self)) {
- /* don't terminate while holding a reference */
+ /* if thread is about to terminate, release the port */
if (self->ast & AST_TERMINATE)
ipc_port_release(reply_port);
- thread_halt_self();
+ /*
+ * Use the continuation to release the port in
+ * case the thread is about to halt.
+ */
+ thread_halt_self(thread_release_and_exception_return);
}
ip_lock(reply_port);
diff --git a/kern/profile.c b/kern/profile.c
index 2c9c44bb..1381b1a5 100644
--- a/kern/profile.c
+++ b/kern/profile.c
@@ -172,7 +172,7 @@ printf("profile_thread: mach_msg failed returned %x\n",(int)mr);
sizeof(struct buf_to_send));
}
- thread_halt_self();
+ thread_halt_self(thread_exception_return);
}
diff --git a/kern/thread.c b/kern/thread.c
index c638075c..3e900792 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -1132,7 +1132,7 @@ void __attribute__((noreturn)) walking_zombie(void)
* Thread calls this routine on exit from the kernel when it
* notices a halt request.
*/
-void thread_halt_self(void)
+void thread_halt_self(continuation_t continuation)
{
thread_t thread = current_thread();
spl_t s;
@@ -1173,7 +1173,7 @@ void thread_halt_self(void)
thread_unlock(thread);
splx(s);
counter(c_thread_halt_self_block++);
- thread_block(thread_exception_return);
+ thread_block(continuation);
/*
* thread_release resets TH_HALTED.
*/
diff --git a/kern/thread.h b/kern/thread.h
index 949d6189..7106fd2d 100644
--- a/kern/thread.h
+++ b/kern/thread.h
@@ -362,7 +362,7 @@ extern void thread_release(thread_t);
extern kern_return_t thread_halt(
thread_t thread,
boolean_t must_halt);
-extern void thread_halt_self(void);
+extern void thread_halt_self(continuation_t);
extern void thread_force_terminate(thread_t);
extern thread_t kernel_thread(
task_t task,