diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2014-12-07 23:05:48 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2014-12-07 23:09:46 +0100 |
commit | be05086a4b9de42ba7c596905e8980d8713eae49 (patch) | |
tree | 579058e3ee11fcfe22d997720d795527a63556e8 | |
parent | cd76999cd1cf590b95df3e22d2eb2a7dad333499 (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.c | 37 | ||||
-rw-r--r-- | kern/task.h | 1 |
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); |