lk/kernel/thread.c
thread_create:
thread_t *thread_create(const char *name, thread_start_routine entry, void *arg, int priority, size_t stack_size) { return thread_create_etc(NULL, name, entry, arg, priority, NULL, stack_size); }
/** * @brief Create a new thread * * This function creates a new thread. The thread is initially suspended, so you * need to call thread_resume() to execute it. * * @param name Name of thread * @param entry Entry point of thread * @param arg Arbitrary argument passed to entry() * @param priority Execution priority for the thread. * @param stack_size Stack size for the thread. * * Thread priority is an integer from 0 (lowest) to 31 (highest). Some standard * prioritys are defined in <kernel/thread.h>: * * HIGHEST_PRIORITY * DPC_PRIORITY * HIGH_PRIORITY * DEFAULT_PRIORITY * LOW_PRIORITY * IDLE_PRIORITY * LOWEST_PRIORITY * * Stack size is typically set to DEFAULT_STACK_SIZE * * @return Pointer to thread object, or NULL on failure. */ thread_t *thread_create_etc(thread_t *t, const char *name, thread_start_routine entry, void *arg, int priority, void *stack, size_t stack_size) { unsigned int flags = 0;
if (!t) { t = malloc(sizeof(thread_t)); if (!t) return NULL; flags |= THREAD_FLAG_FREE_STRUCT; }
init_thread_struct(t, name);
t->entry = entry; t->arg = arg; t->priority = priority; t->state = THREAD_SUSPENDED; t->blocking_wait_queue = NULL; t->wait_queue_block_ret = NO_ERROR; thread_set_curr_cpu(t, -1);
t->retcode = 0; wait_queue_init(&t->retcode_wait_queue);
#if WITH_KERNEL_VM t->aspace = NULL; #endif
/* create the stack */ if (!stack) { #if THREAD_STACK_BOUNDS_CHECK stack_size += THREAD_STACK_PADDING_SIZE; flags |= THREAD_FLAG_DEBUG_STACK_BOUNDS_CHECK; #endif t->stack = malloc(stack_size); if (!t->stack) { if (flags & THREAD_FLAG_FREE_STRUCT) free(t); return NULL; } flags |= THREAD_FLAG_FREE_STACK; #if THREAD_STACK_BOUNDS_CHECK memset(t->stack, STACK_DEBUG_BYTE, THREAD_STACK_PADDING_SIZE); #endif } else { t->stack = stack; } #if THREAD_STACK_HIGHWATER if (flags & THREAD_FLAG_DEBUG_STACK_BOUNDS_CHECK) { memset(t->stack + THREAD_STACK_PADDING_SIZE, STACK_DEBUG_BYTE, stack_size - THREAD_STACK_PADDING_SIZE); } else { memset(t->stack, STACK_DEBUG_BYTE, stack_size); } #endif
t->stack_size = stack_size;
/* save whether or not we need to free the thread struct and/or stack */ t->flags = flags;
/* inheirit thread local storage from the parent */ thread_t *current_thread = get_current_thread(); int i; for (i=0; i < MAX_TLS_ENTRY; i++) t->tls[i] = current_thread->tls[i];
/* set up the initial stack frame */ arch_thread_initialize(t);
/* add it to the global thread list */ THREAD_LOCK(state); list_add_head(&thread_list, &t->thread_list_node); THREAD_UNLOCK(state);
return t; }