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