_st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size) { _st_thread_t *thread; _st_stack_t *stack; void **ptds; char *sp; #ifdef __ia64__ char *bsp; #endif /* Adjust stack size */ if (stk_size == 0) stk_size = ST_DEFAULT_STACK_SIZE; stk_size = ((stk_size + _ST_PAGE_SIZE - 1) / _ST_PAGE_SIZE) * _ST_PAGE_SIZE; stack = _st_stack_new(stk_size); if (!stack) return NULL; /* Allocate thread object and per-thread data off the stack */ #if defined (MD_STACK_GROWS_DOWN) sp = stack->stk_top; #ifdef __ia64__ /* * The stack segment is split in the middle. The upper half is used * as backing store for the register stack which grows upward. * The lower half is used for the traditional memory stack which * grows downward. Both stacks start in the middle and grow outward * from each other. */ sp -= (stk_size >> 1); bsp = sp; /* Make register stack 64-byte aligned */ if ((unsigned long)bsp & 0x3f) bsp = bsp + (0x40 - ((unsigned long)bsp & 0x3f)); stack->bsp = bsp + _ST_STACK_PAD_SIZE; #endif sp = sp - (ST_KEYS_MAX * sizeof(void *)); ptds = (void **) sp; sp = sp - sizeof(_st_thread_t); thread = (_st_thread_t *) sp; /* Make stack 64-byte aligned */ if ((unsigned long)sp & 0x3f) sp = sp - ((unsigned long)sp & 0x3f); stack->sp = sp - _ST_STACK_PAD_SIZE; #elif defined (MD_STACK_GROWS_UP) sp = stack->stk_bottom; thread = (_st_thread_t *) sp; sp = sp + sizeof(_st_thread_t); ptds = (void **) sp; sp = sp + (ST_KEYS_MAX * sizeof(void *)); /* Make stack 64-byte aligned */ if ((unsigned long)sp & 0x3f) sp = sp + (0x40 - ((unsigned long)sp & 0x3f)); stack->sp = sp + _ST_STACK_PAD_SIZE; #else #error Unknown OS #endif memset(thread, 0, sizeof(_st_thread_t)); memset(ptds, 0, ST_KEYS_MAX * sizeof(void *)); /* Initialize thread */ thread->private_data = ptds; thread->stack = stack; thread->start = start; thread->arg = arg; #ifndef __ia64__ _ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main); #else _ST_INIT_CONTEXT(thread, stack->sp, stack->bsp, _st_thread_main); #endif /* If thread is joinable, allocate a termination condition variable */ if (joinable) { thread->term = st_cond_new(); if (thread->term == NULL) { _st_stack_free(thread->stack); return NULL; } } /* Make thread runnable */ thread->state = _ST_ST_RUNNABLE; _st_active_count++; _ST_ADD_RUNQ(thread); #ifdef DEBUG _ST_ADD_THREADQ(thread); #endif return thread; }
extern "C" st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size) { st_thread_t *thread; st_stack_t *stack; void **ptds; char *sp; /* Adjust stack size */ if (stk_size == 0) stk_size = ST_DEFAULT_STACK_SIZE; stk_size = ((stk_size + _ST_PAGE_SIZE - 1) / _ST_PAGE_SIZE) * _ST_PAGE_SIZE; stack = _st_stack_new(stk_size); if (!stack) return NULL; /* Allocate thread object and per-thread data off the stack */ #if defined (MD_STACK_GROWS_DOWN) sp = stack->stk_top; sp = sp - (ST_KEYS_MAX * sizeof(void *)); ptds = (void **) sp; sp = sp - sizeof(st_thread_t); thread = (st_thread_t *) sp; /* Make stack 64-byte aligned */ if ((unsigned long)sp & 0x3f) sp = sp - ((unsigned long)sp & 0x3f); stack->sp = sp - _ST_STACK_PAD_SIZE; #elif defined (MD_STACK_GROWS_UP) sp = stack->stk_bottom; thread = (st_thread_t *)sp; sp = sp + sizeof(st_thread_t); ptds = (void **)sp; sp = sp + (ST_KEYS_MAX * sizeof(void *)); /* Make stack 64-byte aligned */ if ((unsigned long)sp & 0x3f) sp = sp + (0x40 - ((unsigned long)sp & 0x3f)); stack->sp = sp + _ST_STACK_PAD_SIZE; #else #error Unknown OS #endif memset(thread, 0, sizeof(st_thread_t)); memset(ptds, 0, ST_KEYS_MAX * sizeof(void *)); /* Initialize thread */ thread->private_data = ptds; thread->stack = stack; thread->start = start; thread->arg = arg; _ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main); /* If thread is joinable, allocate a termination condition variable */ if (joinable) { thread->term = st_cond_new(); if (thread->term == NULL) { _st_stack_free(thread->stack); return NULL; } } if (!thread->context_switch) { thread->context_switch = (st_context_switch_t*)calloc(1, sizeof(st_context_switch_t)); thread->context_switch->thread = thread; } /* Make thread runnable */ thread->state = _ST_ST_RUNNABLE; _st_active_count++; _ST_ADD_RUNQ(thread); return thread; }