Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2838 → Rev 2839

/branches/tracing/kernel/generic/include/proc/task.h
100,8 → 100,12
call_t *debug_begin_call;
int not_stoppable_count;
 
/** Kernel answerbox */
answerbox_t kernel_box;
/** Thread used to service kernel answerbox */
struct thread *kb_thread;
/** True if kb_thread != NULL or is being prepared */
bool kb_thread_at_hand;
/** Architecture specific task data. */
task_arch_t arch;
/branches/tracing/kernel/generic/include/proc/thread.h
228,6 → 228,7
extern thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
int flags, char *name, bool uncounted);
extern void thread_attach(thread_t *t, task_t *task);
extern int thread_attach_by_id(thread_t *t, task_id_t taskid);
extern void thread_ready(thread_t *t);
extern void thread_exit(void) __attribute__((noreturn));
 
253,6 → 254,7
void *call_me_with);
extern void thread_print_list(void);
extern void thread_destroy(thread_t *t);
extern void thread_unattached_free(thread_t *t);
extern void thread_update_accounting(void);
extern bool thread_exists(thread_t *t);
 
/branches/tracing/kernel/generic/src/proc/task.c
178,6 → 178,7
 
ipc_answerbox_init(&ta->kernel_box, ta);
ta->kb_thread = NULL;
ta->kb_thread_at_hand = false;
 
ipc_answerbox_init(&ta->answerbox, ta);
for (i = 0; i < IPC_MAX_PHONES; i++)
/branches/tracing/kernel/generic/src/proc/thread.c
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
/branches/tracing/kernel/generic/src/ipc/ipc.c
657,6 → 657,7
klog_printf("kbox: finished");
}
 
 
/**
* Connect phone to a task kernel-box specified by id.
*
666,12 → 667,17
{
int newphid;
task_t *ta;
thread_t *kb_thread;
int rc;
ipl_t ipl;
 
newphid = phone_alloc();
if (newphid < 0)
return ELIMIT;
 
ipl = interrupts_disable();
spinlock_lock(&tasks_lock);
 
ta = task_find_by_id(taskid);
if (ta == NULL) {
spinlock_unlock(&tasks_lock);
682,17 → 688,35
spinlock_unlock(&tasks_lock);
 
ipc_phone_connect(&TASK->phones[newphid], &ta->kernel_box);
spinlock_unlock(&ta->lock);
 
/* FIXME: locking! */
if (ta->kb_thread == NULL) {
ta->kb_thread = thread_create(kbox_thread_proc,
NULL, ta, 0, "kbox", false);
if (!ta->kb_thread)
if (ta->kb_thread_at_hand == false) {
ta->kb_thread_at_hand = true;
spinlock_unlock(&ta->lock);
interrupts_restore(ipl);
 
kb_thread = thread_create(kbox_thread_proc,
NULL, ta, THREAD_FLAG_NOATTACH, "kbox", false);
if (!kb_thread)
return ENOMEM;
 
thread_detach(ta->kb_thread);
thread_ready(ta->kb_thread);
rc = thread_attach_by_id(kb_thread, taskid);
if (rc == EOK) {
ipl = interrupts_disable();
spinlock_lock(&ta->lock);
ta->kb_thread = kb_thread;
spinlock_unlock(&ta->lock);
interrupts_restore(ipl);
 
thread_detach(kb_thread);
thread_ready(kb_thread);
} else {
/* Return the allocated thread struct */
thread_unattached_free(kb_thread);
}
} else {
spinlock_unlock(&ta->lock);
interrupts_restore(ipl);
}
 
return newphid;