358,6 → 358,16 |
return t; |
} |
|
/** Destroy thread structure of an unattached thread. |
* |
* Thread t must only have been created and never attached. |
*/ |
void thread_unattached_free(thread_t *t) |
{ |
slab_free(thread_slab, t); |
} |
|
|
/** Destroy thread memory structure |
* |
* Detach thread from all queues, cpus etc. and destroy it. |
398,6 → 408,43 |
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); |
|
/* FIXME: this must be done very carefully.. an unstoppable |
thread cannot appear just-so, it must be possible to catch it. */ |
if (t->flags & THREAD_FLAG_USPACE) |
++task->not_stoppable_count; |
list_append(&t->th_link, &task->th_head); |
} |
|
/** 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 |
410,31 → 457,68 |
{ |
ipl_t ipl; |
|
ipl = interrupts_disable(); |
|
/* |
* Attach to the current 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); |
atomic_inc(&task->refcount); |
atomic_inc(&task->lifecount); |
spinlock_unlock(&tasks_lock); |
|
/* FIXME: this must be done very carefully.. an unstoppable |
thread cannot appear just-so, it must be possible to catch it. */ |
if (t->flags & THREAD_FLAG_USPACE) |
++task->not_stoppable_count; |
list_append(&t->th_link, &task->th_head); |
/* |
* Attach to the current task. |
*/ |
_thread_attach_task(t, task); |
|
spinlock_unlock(&task->lock); |
|
/* |
* Register this thread in the system-wide list. |
*/ |
spinlock_lock(&threads_lock); |
avltree_insert(&threads_tree, &t->threads_tree_node); |
spinlock_unlock(&threads_lock); |
_thread_attach_tree(t); |
|
interrupts_restore(ipl); |
|
return EOK; |
} |
|
|
/** Terminate thread. |
* |
* End current thread execution and switch it to the exiting state. All pending |