1 /* $OpenBSD: rthread_stack.c,v 1.4 2010/05/26 21:40:05 guenther Exp $ */ 2 /* $snafu: rthread_stack.c,v 1.12 2005/01/11 02:45:28 marc Exp $ */ 3 4 /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ 5 6 #include <sys/types.h> 7 #include <sys/mman.h> 8 9 #include <machine/param.h> 10 #include <machine/spinlock.h> 11 12 #include <errno.h> 13 #include <pthread.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 17 #include "rthread.h" 18 19 struct stack * 20 _rthread_alloc_stack(pthread_t thread) 21 { 22 struct stack *stack; 23 caddr_t base; 24 caddr_t guard; 25 caddr_t start = NULL; 26 size_t pgsz; 27 size_t size; 28 29 /* guard pages are forced to a multiple of the page size */ 30 pgsz = sysconf(_SC_PAGESIZE); 31 if (pgsz == (size_t)-1) 32 return NULL; 33 34 /* figure out the actual requested size, including guard size */ 35 size = thread->attr.stack_size + thread->attr.guard_size; 36 size += pgsz - 1; 37 size &= ~(pgsz - 1); 38 39 /* 40 * Allocate some stack space unless an address was provided. 41 * A provided address is ASSUMED to be correct with respect to 42 * alignment constraints. 43 */ 44 if (size > thread->attr.guard_size) { 45 if (thread->attr.stack_addr) 46 base = thread->attr.stack_addr; 47 else { 48 base = mmap(NULL, size, PROT_READ | PROT_WRITE, 49 MAP_ANON, -1, 0); 50 if (base == MAP_FAILED) 51 return (NULL); 52 } 53 /* memory protect the guard region */ 54 55 #ifdef MACHINE_STACK_GROWS_UP 56 guard = base + size - thread->attr.guard_size; 57 start = base; 58 #else 59 guard = base; 60 start = base + size; 61 #endif 62 if (mprotect(guard, thread->attr.guard_size, PROT_NONE) == -1) { 63 munmap(base, size); 64 return (NULL); 65 } 66 67 /* wrap up the info in a struct stack and return it */ 68 stack = malloc(sizeof(*stack)); 69 if (!stack) { 70 munmap(base, size); 71 return (NULL); 72 } 73 stack->sp = start; 74 stack->base = base; 75 stack->guard = guard; 76 stack->guardsize = thread->attr.guard_size; 77 stack->len = size; 78 return (stack); 79 } 80 errno = EINVAL; 81 return (NULL); 82 } 83 84 void 85 _rthread_free_stack(struct stack *stack) 86 { 87 munmap(stack->base, stack->len); 88 free(stack); 89 } 90 91