summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2014-12-07 23:05:48 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2014-12-07 23:09:46 +0100
commitbe05086a4b9de42ba7c596905e8980d8713eae49 (patch)
tree579058e3ee11fcfe22d997720d795527a63556e8
parentcd76999cd1cf590b95df3e22d2eb2a7dad333499 (diff)
Fix pthread_create warning on translator termination
This was due to task_terminate not actually properly suspending threads before disable the task port, which was thus preventing pthread_create from being able to create a stack. Thanks Gabriele Giacone for finding out a reproducer of this. * kern/task.h (task_hold_locked): New declaration. * kern/task.c (task_hold): Move the locked part of the code into... (task_hold_locked): ... new function. (task_terminate): Call task_hold_locked just before deactivating the task. Call ipc_task_disable after waiting for threads to actually suspend with task_dowait.
-rw-r--r--kern/task.c37
-rw-r--r--kern/task.h1
2 files changed, 29 insertions, 9 deletions
diff --git a/kern/task.c b/kern/task.c
index 20acc6a..44963c6 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -272,6 +272,7 @@ kern_return_t task_terminate(
thread_terminate(cur_thread);
return KERN_FAILURE;
}
+ task_hold_locked(task);
task->active = FALSE;
queue_remove(list, cur_thread, thread_t, thread_list);
thread_unlock(cur_thread);
@@ -325,6 +326,7 @@ kern_return_t task_terminate(
task_unlock(task);
return KERN_FAILURE;
}
+ task_hold_locked(task);
task->active = FALSE;
task_unlock(task);
}
@@ -335,9 +337,8 @@ kern_return_t task_terminate(
* If this is the current task, the current thread will
* be left running.
*/
- ipc_task_disable(task);
- (void) task_hold(task);
(void) task_dowait(task,TRUE); /* may block */
+ ipc_task_disable(task);
/*
* Terminate each thread in the task.
@@ -402,20 +403,18 @@ kern_return_t task_terminate(
* Suspend execution of the specified task.
* This is a recursive-style suspension of the task, a count of
* suspends is maintained.
+ *
+ * CONDITIONS: the task is locked and active.
*/
-kern_return_t task_hold(
+void task_hold_locked(
task_t task)
{
queue_head_t *list;
thread_t thread, cur_thread;
- cur_thread = current_thread();
+ assert(task->active);
- task_lock(task);
- if (!task->active) {
- task_unlock(task);
- return KERN_FAILURE;
- }
+ cur_thread = current_thread();
task->suspend_count++;
@@ -429,6 +428,26 @@ kern_return_t task_hold(
if (thread != cur_thread)
thread_hold(thread);
}
+}
+
+/*
+ * task_hold:
+ *
+ * Suspend execution of the specified task.
+ * This is a recursive-style suspension of the task, a count of
+ * suspends is maintained.
+ */
+kern_return_t task_hold(
+ task_t task)
+{
+ task_lock(task);
+ if (!task->active) {
+ task_unlock(task);
+ return KERN_FAILURE;
+ }
+
+ task_hold_locked(task);
+
task_unlock(task);
return KERN_SUCCESS;
}
diff --git a/kern/task.h b/kern/task.h
index 3c10dc0..2a4c28f 100644
--- a/kern/task.h
+++ b/kern/task.h
@@ -182,6 +182,7 @@ extern void consider_task_collect(void);
extern void task_init(void);
extern void task_reference(task_t);
extern void task_deallocate(task_t);
+extern void task_hold_locked(task_t);
extern kern_return_t task_hold(task_t);
extern kern_return_t task_dowait(task_t, boolean_t);
extern kern_return_t task_release(task_t);