412,52 → 412,6 |
slab_free(thread_slab, t); |
} |
|
/** Attach thread to the given task. |
* |
* The task's lock must already be held and interrupts must be disabled. |
* |
* @param t Thread to be attached to the task. |
* @param task Task to which the thread is to be attached. |
*/ |
static void _thread_attach_task(thread_t *t, task_t *task) |
{ |
atomic_inc(&task->refcount); |
atomic_inc(&task->lifecount); |
|
list_append(&t->th_link, &task->th_head); |
|
/* |
* Copy task debugging state to thread struct. |
* The thread needs to know it is being debugged, |
* otherwise it would neither stop nor respond to |
* debug ops. |
*/ |
if (t->flags & THREAD_FLAG_USPACE) { |
if (task->dt_state == UDEBUG_TS_BEGINNING || |
task->dt_state == UDEBUG_TS_ACTIVE) { |
t->debug_active = true; |
} |
} |
} |
|
/** Add thread to the threads tree. |
* |
* Interrupts must be already disabled. |
* |
* @param t Thread to be attached to the task. |
* @param task Task to which the thread is to be attached. |
*/ |
static void _thread_attach_tree(thread_t *t) |
{ |
/* |
* Register this thread in the system-wide list. |
*/ |
spinlock_lock(&threads_lock); |
avltree_insert(&threads_tree, &t->threads_tree_node); |
spinlock_unlock(&threads_lock); |
} |
|
|
/** Make the thread visible to the system. |
* |
* Attach the thread structure to the current task and make it visible in the |
470,68 → 424,28 |
{ |
ipl_t ipl; |
|
ipl = interrupts_disable(); |
|
/* |
* Attach to the current task. |
* Attach to the specified task. |
*/ |
spinlock_lock(&task->lock); |
_thread_attach_task(t, task); |
spinlock_unlock(&task->lock); |
|
/* |
* Register this thread in the system-wide list. |
*/ |
_thread_attach_tree(t); |
|
interrupts_restore(ipl); |
} |
|
/** Attach thread to a task given by its ID. |
* |
* Unlike thread_attach(), this function allows to attach a thread |
* to an arbitrary task. |
* |
* @param t Thread to be attached to the task. |
* @param taskid Task id to which the thread is to be attached. |
* @return An error code from errno.h |
*/ |
int thread_attach_by_id(thread_t *t, task_id_t taskid) |
{ |
ipl_t ipl; |
task_t *task; |
|
ipl = interrupts_disable(); |
|
spinlock_lock(&tasks_lock); |
task = task_find_by_id(taskid); |
if (task == NULL) { |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
|
spinlock_lock(&task->lock); |
spinlock_unlock(&tasks_lock); |
|
/* |
* Attach to the current task. |
*/ |
_thread_attach_task(t, task); |
|
atomic_inc(&task->refcount); |
/* Must not count kbox thread into lifecount */ |
if (t->flags & THREAD_FLAG_USPACE) |
atomic_inc(&task->lifecount); |
list_append(&t->th_link, &task->th_head); |
spinlock_unlock(&task->lock); |
|
/* |
* Register this thread in the system-wide list. |
*/ |
_thread_attach_tree(t); |
spinlock_lock(&threads_lock); |
avltree_insert(&threads_tree, &t->threads_tree_node); |
spinlock_unlock(&threads_lock); |
|
interrupts_restore(ipl); |
|
return EOK; |
} |
|
|
/** Terminate thread. |
* |
* End current thread execution and switch it to the exiting state. All pending |
541,16 → 455,17 |
{ |
ipl_t ipl; |
|
if (atomic_predec(&TASK->lifecount) == 0) { |
/* |
* We are the last thread in the task that still has not exited. |
* With the exception of the moment the task was created, new |
* threads can only be created by threads of the same task. |
* We are safe to perform cleanup. |
*/ |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
if (atomic_predec(&TASK->lifecount) == 0) { |
/* |
* We are the last userspace thread in the task that |
* still has not exited. With the exception of the |
* moment the task was created, new userspace threads |
* can only be created by threads of the same task. |
* We are safe to perform cleanup. |
*/ |
ipc_cleanup(); |
futex_cleanup(); |
futex_cleanup(); |
klog_printf("Cleanup of task %llu completed.", |
TASK->taskid); |
} |