/*! * Create new thread * \param start_func Starting function for new thread * \param param Parameter sent to starting function * \param exit_func Thread will call this function when it leaves 'start_func' * \param prio Thread priority * \param stack Address of thread stack (if not NULL) * \param stack_size Stack size * \param run Move thread descriptor to ready threads? * \param proc Process descriptor thread belongs to * \return Pointer to descriptor of created kernel thread */ kthread_t *k_create_thread ( void *start_func, void *param, void *exit_func, int prio, void *stack, size_t stack_size, int run, kprocess_t *proc ) { kthread_t *kthr; /* if stack is not defined */ if ( proc && proc->stack_pool && ( !stack || !stack_size ) ) { stack_size = proc->pi->thread_stack; stack = ffs_alloc ( proc->stack_pool, stack_size ); } else if ( !stack || !stack_size ) { if ( !stack_size ) stack_size = DEFAULT_THREAD_STACK_SIZE; stack = kmalloc ( stack_size ); } ASSERT ( stack && stack_size ); kthr = kmalloc ( sizeof (kthread_t) ); /* thread descriptor */ ASSERT ( kthr ); /* initialize thread descriptor */ kthr->id = k_new_unique_id (); kthr->state = THR_STATE_PASSIVE; if ( prio < 0 ) prio = 0; if ( prio >= PRIO_LEVELS ) prio = PRIO_LEVELS - 1; kthr->sched.prio = prio; arch_create_thread_context ( &kthr->context, start_func, param, exit_func, stack, stack_size, proc ); kthr->queue = NULL; kthr->exit_status = 0; k_threadq_init ( &kthr->join_queue ); kthr->ref_cnt = 0; if ( run ) { move_to_ready ( kthr ); kthr->ref_cnt = 1; } kthr->stack = stack; kthr->stack_size = stack_size; kthr->proc = proc; kthr->proc->thr_count++; kthr->private_storage = NULL; #ifdef MESSAGES k_thr_msg_init ( &kthr->msg ); #endif list_append ( &all_threads, kthr, &kthr->all ); return kthr; }
/*! create/insert state for signal handler and similar */ void kthread_create_new_state ( kthread_t *kthread, void *start_func, void *param, void *stack, size_t stack_size, int save_old_state ) { ASSERT ( kthread ); /* save old state if requested (put it at beginning of state list) */ if ( save_old_state ) { kthread_state_t *state = kmalloc ( sizeof (kthread_state_t) ); *state = kthread->state; list_prepend ( &kthread->states, state, &state->list ); } int stack_provided = FALSE; if ( !stack || !stack_size ) { if ( !stack_size ) stack_size = DEFAULT_THREAD_STACK_SIZE; stack = kmalloc ( stack_size ); } ASSERT ( stack && stack_size ); if ( stack_provided ) { kthread->state.stack = NULL; kthread->state.stack_size = 0; } else { kthread->state.stack = stack; kthread->state.stack_size = stack_size; } arch_create_thread_context ( &kthread->state.context, start_func, param, pi.exit, stack, stack_size ); kthread->state.flags = 0; kthread->state.retval = 0; kthread->state.errno = 0; kthread->state.exit_status = NULL; kthread->state.pparam = NULL; list_init ( &kthread->state.cleanup ); }
uthread_t *create_uthread ( void (func) (void *), void *param ) { uthread_t *thread; thread = malloc ( sizeof (uthread_t) ); thread->stack = malloc (DEFAULT_THREAD_STACK_SIZE); thread->id = next_id; arch_create_thread_context ( &thread->context, func, param, uthread_exit, thread->stack, DEFAULT_THREAD_STACK_SIZE ); next_id++; list_append ( &ready, thread, &thread->list ); return thread; }
/*! create/insert state for signal handler and similar */ void kthread_create_new_state ( kthread_t *kthread, void *start_func, void *param, void *stack, size_t stack_size, int save_old_state ) { ASSERT ( kthread ); kprocess_t *kproc = kthread_get_process ( kthread ); ASSERT ( kproc ); /* save old state if requested (put it at beginning of state list) */ if ( save_old_state ) { kthread_state_t *state = kmalloc ( sizeof (kthread_state_t) ); *state = kthread->state; list_prepend ( &kthread->states, state, &state->list ); } int stack_provided = FALSE; if ( stack && stack_size ) { stack_provided = TRUE; } else if ( kproc->smap ) { /* use process stack heap */ stack_size = kproc->thread_stack_size; stack = kprocess_stack_alloc ( kproc ); } else { /* use kernel heap */ if ( !stack_size ) stack_size = DEFAULT_THREAD_STACK_SIZE; stack = kmalloc ( stack_size ); } ASSERT ( stack && stack_size ); if ( stack_provided ) { kthread->state.stack = NULL; /* don't free it on exit */ kthread->state.stack_size = 0; } else { kthread->state.stack = stack; kthread->state.stack_size = stack_size; } /* reserve space for errno in user space */ stack_size -= sizeof (int); kthread->state.errno = kthread->state.stack + stack_size; arch_create_thread_context ( &kthread->state.context, start_func, param, kproc->proc->p.exit, stack, stack_size, kproc ); *kthread->state.errno = 0; kthread->state.exit_status = NULL; kthread->state.pparam = NULL; list_init ( &kthread->state.cleanup ); }