Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2901 → Rev 2902

/branches/tracing/kernel/generic/src/proc/thread.c
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);
}