xref: /openbsd-src/lib/librthread/rthread_stack.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
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