struct thread *thread_init_stack(void *stack, size_t stack_sz, int priority, void *(*run)(void *), void *arg) { struct thread *thread = stack; /* Allocating at the bottom */ /* Stack setting up */ thread_stack_init(thread, stack_sz); /* General initialization and task setting up */ thread_init(thread, priority, run, arg); return thread; }
struct thread *thread_alloc(void) { thread_pool_entry_t *block; struct thread *t; if (!(block = (thread_pool_entry_t *) pool_alloc(&thread_pool))) { return NULL; } memset(block, 0x53, sizeof(*block)); t = &block->thread; thread_stack_init(t, STACK_SZ); return t; }
kernel_pid_t thread_create(char *stack, int stacksize, char priority, int flags, void *(*function)(void *arg), void *arg, const char *name) { /* allocate our thread control block at the top of our stackspace */ #ifdef DEVELHELP int total_stacksize = stacksize; #endif stacksize -= sizeof(tcb_t); /* align tcb address on 32bit boundary */ unsigned int tcb_address = (unsigned int) stack + stacksize; if (tcb_address & 1) { tcb_address--; stacksize--; } if (tcb_address & 2) { tcb_address -= 2; stacksize -= 2; } tcb_t *cb = (tcb_t *) tcb_address; if (priority >= SCHED_PRIO_LEVELS) { return -EINVAL; } #ifdef DEVELHELP if (flags & CREATE_STACKTEST) { /* assign each int of the stack the value of it's address */ unsigned int *stackmax = (unsigned int *)((char *)stack + stacksize); unsigned int *stackp = (unsigned int *)stack; while (stackp < stackmax) { *stackp = (unsigned int)stackp; stackp++; } } else { /* create stack guard */ *stack = (unsigned int)stack; } #endif if (!inISR()) { dINT(); } kernel_pid_t pid = KERNEL_PID_UNDEF; for (kernel_pid_t i = KERNEL_PID_FIRST; i <= KERNEL_PID_LAST; ++i) { if (sched_threads[i] == NULL) { pid = i; break; } } if (pid == KERNEL_PID_UNDEF) { DEBUG("thread_create(): too many threads!\n"); if (!inISR()) { eINT(); } return -EOVERFLOW; } sched_threads[pid] = cb; cb->pid = pid; cb->sp = thread_stack_init(function, arg, stack, stacksize); cb->stack_start = stack; #ifdef DEVELHELP cb->stack_size = total_stacksize; #endif cb->priority = priority; cb->status = 0; cb->rq_entry.next = NULL; cb->rq_entry.prev = NULL; cb->name = name; cb->wait_data = NULL; cb->msg_waiters.first = NULL; cib_init(&(cb->msg_queue), 0); cb->msg_array = NULL; sched_num_threads++; DEBUG("Created thread %s. PID: %" PRIkernel_pid ". Priority: %u.\n", name, cb->pid, priority); if (flags & CREATE_SLEEPING) { sched_set_status(cb, STATUS_SLEEPING); } else { sched_set_status(cb, STATUS_PENDING); if (!(flags & CREATE_WOUT_YIELD)) { if (!inISR()) { eINT(); thread_yield(); } else { sched_context_switch_request = 1; } } } if (!inISR() && sched_active_thread != NULL) { eINT(); } return pid; }