102,7 → 102,7 |
thread_id_t last_tid = 0; |
|
static slab_cache_t *thread_slab; |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
slab_cache_t *fpu_context_slab; |
#endif |
|
161,7 → 161,7 |
/* call the architecture-specific part of the constructor */ |
thr_constructor_arch(t); |
|
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
#ifdef CONFIG_FPU_LAZY |
t->saved_fpu_context = NULL; |
#else |
169,11 → 169,11 |
if (!t->saved_fpu_context) |
return -1; |
#endif |
#endif |
#endif |
|
t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags); |
if (!t->kstack) { |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
if (t->saved_fpu_context) |
slab_free(fpu_context_slab, t->saved_fpu_context); |
#endif |
180,6 → 180,10 |
return -1; |
} |
|
#ifdef CONFIG_UDEBUG |
mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE); |
#endif |
|
return 0; |
} |
|
192,7 → 196,7 |
thr_destructor_arch(t); |
|
frame_free(KA2PA(t->kstack)); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
if (t->saved_fpu_context) |
slab_free(fpu_context_slab, t->saved_fpu_context); |
#endif |
207,11 → 211,11 |
void thread_init(void) |
{ |
THREAD = NULL; |
atomic_set(&nrdy,0); |
atomic_set(&nrdy, 0); |
thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0, |
thr_constructor, thr_destructor, 0); |
|
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t), |
FPU_CONTEXT_ALIGN, NULL, NULL, 0); |
#endif |
275,7 → 279,7 |
* guarantee that the task won't cease to exist during the |
* call. The task's lock may not be held. |
* @param flags Thread flags. |
* @param name Symbolic name. |
* @param name Symbolic name (a copy is made). |
* @param uncounted Thread's accounting doesn't affect accumulated task |
* accounting. |
* |
312,6 → 316,7 |
interrupts_restore(ipl); |
|
memcpy(t->name, name, THREAD_NAME_BUFLEN); |
t->name[THREAD_NAME_BUFLEN - 1] = '\0'; |
|
t->thread_code = func; |
t->thread_arg = arg; |
347,6 → 352,11 |
avltree_node_initialize(&t->threads_tree_node); |
t->threads_tree_node.key = (uintptr_t) t; |
|
#ifdef CONFIG_UDEBUG |
/* Init debugging stuff */ |
udebug_thread_initialize(&t->udebug); |
#endif |
|
/* might depend on previous initialization */ |
thread_create_arch(t); |
|
409,12 → 419,17 |
ipl_t ipl; |
|
/* |
* Attach to the current task. |
* Attach to the specified task. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&task->lock); |
|
atomic_inc(&task->refcount); |
atomic_inc(&task->lifecount); |
|
/* 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); |
|
437,14 → 452,19 |
{ |
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) { |
#ifdef CONFIG_UDEBUG |
/* Generate udebug THREAD_E event */ |
udebug_thread_e_event(); |
#endif |
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(); |
LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid); |
689,7 → 709,7 |
* |
*/ |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, |
thread_id_t *uspace_thread_id) |
size_t name_len, thread_id_t *uspace_thread_id) |
{ |
thread_t *t; |
char namebuf[THREAD_NAME_BUFLEN]; |
696,10 → 716,15 |
uspace_arg_t *kernel_uarg; |
int rc; |
|
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
if (name_len > THREAD_NAME_BUFLEN - 1) |
name_len = THREAD_NAME_BUFLEN - 1; |
|
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
|
namebuf[name_len] = '\0'; |
|
/* |
* In case of failure, kernel_uarg will be deallocated in this function. |
* In case of success, kernel_uarg will be freed in uinit(). |
738,7 → 763,18 |
return (unative_t) rc; |
} |
} |
#ifdef CONFIG_UDEBUG |
/* |
* Generate udebug THREAD_B event and attach the thread. |
* This must be done atomically (with the debug locks held), |
* otherwise we would either miss some thread or receive |
* THREAD_B events for threads that already existed |
* and could be detected with THREAD_READ before. |
*/ |
udebug_thread_b_event_attach(t, TASK); |
#else |
thread_attach(t, TASK); |
#endif |
thread_ready(t); |
|
return 0; |