diff options
author | Marco S Hyman <marc@cvs.openbsd.org> | 2006-01-01 19:32:31 +0000 |
---|---|---|
committer | Marco S Hyman <marc@cvs.openbsd.org> | 2006-01-01 19:32:31 +0000 |
commit | 2e8171134016d44dbd15da591feea9b72aae4eca (patch) | |
tree | b662d6d91abfc80d0ad3ebdcee14d62cdfdb8317 | |
parent | e0e72bc78b187b57a6f7e98347ba15b306a3508f (diff) |
thread stack handling changes. Add guard zones and allow stack
size (and guard zone size) to be set using pthread_attr. Guard
zones are specified in bytes, but implemented in terms of a
page size.
OK Otto@
-rw-r--r-- | lib/librthread/Makefile | 4 | ||||
-rw-r--r-- | lib/librthread/rthread.c | 43 | ||||
-rw-r--r-- | lib/librthread/rthread.h | 11 | ||||
-rw-r--r-- | lib/librthread/rthread_attr.c | 49 | ||||
-rw-r--r-- | lib/librthread/rthread_stack.c | 92 |
5 files changed, 156 insertions, 43 deletions
diff --git a/lib/librthread/Makefile b/lib/librthread/Makefile index 1f488ace167..24a0fa53fdc 100644 --- a/lib/librthread/Makefile +++ b/lib/librthread/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.6 2005/12/31 21:40:43 marc Exp $ +# $OpenBSD: Makefile,v 1.7 2006/01/01 19:32:30 marc Exp $ LIB=rthread WANTLINT= @@ -7,7 +7,7 @@ CFLAGS+=-Wall -g -Werror -Wshadow .PATH: ${.CURDIR}/arch/${MACHINE_ARCH} SRCS= rthread.c rthread_attr.c rthread_sched.c rthread_sync.c rthread_tls.c \ - rthread_sig.c rthread_np.c rthread_debug.c + rthread_sig.c rthread_np.c rthread_debug.c rthread_stack.c OBJS+= _atomic_lock.o rfork_thread.o diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c index 71bff294202..b4d07b73903 100644 --- a/lib/librthread/rthread.c +++ b/lib/librthread/rthread.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread.c,v 1.25 2005/12/31 08:51:20 otto Exp $ */ +/* $OpenBSD: rthread.c,v 1.26 2006/01/01 19:32:30 marc Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -111,40 +111,6 @@ _rthread_init(void) return (0); } -static struct stack * -_rthread_alloc_stack(size_t len, void *base) -{ - struct stack *stack; - - stack = malloc(sizeof(*stack)); - if (!stack) - return (NULL); - if (base) { - stack->base = base; - } else { - stack->base = mmap(NULL, len, PROT_READ | PROT_WRITE, - MAP_ANON, -1, 0); - if (stack->base == MAP_FAILED) { - free(stack); - return (NULL); - } - } -#ifdef MACHINE_STACK_GROWS_UP - stack->sp = (void *)(((size_t)stack->base + 64) & ~63); -#else - stack->sp = (void *)(((size_t)stack->base + len - 16) & ~15); -#endif - stack->len = len; - return (stack); -} - -static void -_rthread_free_stack(struct stack *stack) -{ - munmap(stack->base, stack->len); - free(stack); -} - /* * real pthread functions */ @@ -238,10 +204,15 @@ pthread_create(pthread_t *threadp, const pthread_attr_t *attr, thread->arg = arg; if (attr) thread->attr = *(*attr); + else { + thread->attr.stack_size = RTHREAD_STACK_SIZE_DEF; + thread->attr.guard_size = sysconf(_SC_PAGESIZE); + thread->attr.stack_size -= thread->attr.guard_size; + } _spinlock(&_thread_lock); - thread->stack = _rthread_alloc_stack(64 * 1024, NULL); + thread->stack = _rthread_alloc_stack(thread); if (!thread->stack) { rc = errno; goto fail1; diff --git a/lib/librthread/rthread.h b/lib/librthread/rthread.h index 792b9259a19..9a312ef64bc 100644 --- a/lib/librthread/rthread.h +++ b/lib/librthread/rthread.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread.h,v 1.14 2005/12/31 21:40:43 marc Exp $ */ +/* $OpenBSD: rthread.h,v 1.15 2006/01/01 19:32:30 marc Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -27,9 +27,13 @@ #include <sys/queue.h> +#define RTHREAD_STACK_SIZE_DEF (64 * 1024) + struct stack { void *sp; void *base; + void *guard; + size_t guardsize; size_t len; }; @@ -73,6 +77,7 @@ struct pthread_rwlockattr { struct pthread_attr { void *stack_addr; size_t stack_size; + size_t guard_size; int detach_state; int contention_scope; int sched_policy; @@ -134,10 +139,14 @@ int _sem_post(sem_t); int _sem_wakeup(sem_t); int _sem_wakeall(sem_t); +struct stack *_rthread_alloc_stack(pthread_t); +void _rthread_free_stack(struct stack *); void _rthread_tls_destructors(pthread_t); void _rthread_debug(int, const char *, ...) __attribute__((__format__ (printf, 2, 3))); +void _thread_dump_info(void); + int _atomic_lock(register volatile _spinlock_lock_t *); /* syscalls */ diff --git a/lib/librthread/rthread_attr.c b/lib/librthread/rthread_attr.c index 93a18346079..741c4641aff 100644 --- a/lib/librthread/rthread_attr.c +++ b/lib/librthread/rthread_attr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_attr.c,v 1.4 2005/12/31 08:51:20 otto Exp $ */ +/* $OpenBSD: rthread_attr.c,v 1.5 2006/01/01 19:32:30 marc Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -36,6 +36,17 @@ #include "rthread.h" +/* + * Note: stack_size + guard_size == total stack used + * + * pthread_attr_init MUST be called before any other attribute function + * for proper operation. + * + * Every call to pthread_attr_init MUST be matched with a call to + * pthread_attr_destroy to avoid leaking memory. This is an implementation + * requirement, not a POSIX requirement. + */ + int pthread_attr_init(pthread_attr_t *attrp) { @@ -45,6 +56,9 @@ pthread_attr_init(pthread_attr_t *attrp) if (!attr) return (errno); memset(attr, 0, sizeof(*attr)); + attr->stack_size = RTHREAD_STACK_SIZE_DEF; + attr->guard_size = sysconf(_SC_PAGESIZE); + attr->stack_size -= attr->guard_size; *attrp = attr; return (0); @@ -60,6 +74,26 @@ pthread_attr_destroy(pthread_attr_t *attrp) } int +pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize) +{ + *guardsize = (*attrp)->guard_size; + + return (0); +} + +int +pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize) +{ + if ((*attrp)->guard_size != guardsize) { + (*attrp)->stack_size += (*attrp)->guard_size; + (*attrp)->guard_size = guardsize; + (*attrp)->stack_size -= (*attrp)->guard_size; + } + + return 0; +} + +int pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate) { *detachstate = (*attrp)->detach_state; @@ -70,6 +104,7 @@ pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate) int pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate) { + /* XXX detachstate should be validated here */ (*attrp)->detach_state = detachstate; return (0); @@ -80,7 +115,7 @@ pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr, size_t *stacksize) { *stackaddr = (*attrp)->stack_addr; - *stacksize = (*attrp)->stack_size; + *stacksize = (*attrp)->stack_size + (*attrp)->guard_size; return (0); } @@ -90,6 +125,7 @@ pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize) { (*attrp)->stack_addr = stackaddr; (*attrp)->stack_size = stacksize; + (*attrp)->stack_size -= (*attrp)->guard_size; return (0); } @@ -97,8 +133,8 @@ pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize) int pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize) { - *stacksize = (*attrp)->stack_size; - + *stacksize = (*attrp)->stack_size + (*attrp)->guard_size; + return (0); } @@ -106,6 +142,10 @@ int pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize) { (*attrp)->stack_size = stacksize; + if ((*attrp)->stack_size > (*attrp)->guard_size) + (*attrp)->stack_size -= (*attrp)->guard_size; + else + (*attrp)->stack_size = 0; return (0); } @@ -137,6 +177,7 @@ pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope) int pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope) { + /* XXX contentionscope should be validated here */ (*attrp)->contention_scope = contentionscope; return (0); diff --git a/lib/librthread/rthread_stack.c b/lib/librthread/rthread_stack.c new file mode 100644 index 00000000000..05a1f6158ea --- /dev/null +++ b/lib/librthread/rthread_stack.c @@ -0,0 +1,92 @@ +/* $OpenBSD: rthread_stack.c,v 1.1 2006/01/01 19:32:30 marc Exp $ */ +/* $snafu: rthread_stack.c,v 1.12 2005/01/11 02:45:28 marc Exp $ */ + +/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ + +#include <sys/types.h> +#include <sys/mman.h> + +#include <machine/param.h> +#include <machine/spinlock.h> + +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> + +#include "rthread.h" + +struct stack * +_rthread_alloc_stack(pthread_t thread) +{ + struct stack *stack; + caddr_t base; + caddr_t guard; + caddr_t start = NULL; + size_t pgsz; + size_t size; + + /* guard pages are forced to a multiple of the page size */ + pgsz = sysconf(_SC_PAGESIZE); + if (pgsz == (size_t)-1) + return NULL; + + /* figure out the actual requested size, including guard size */ + size = thread->attr.stack_size + thread->attr.guard_size; + size += pgsz - 1; + size &= ~(pgsz - 1); + + /* + * Allocate some stack space unless and address was provided. + * A provided address is ASSUMED to be correct with respect to + * alignment constraints. + */ + if (size > thread->attr.guard_size) { + if (thread->attr.stack_addr) + base = thread->attr.stack_addr; + else { + base = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_ANON, -1, 0); + if (base == MAP_FAILED) + return (NULL); + } + /* memory protect the guard region */ + +#ifdef MACHINE_STACK_GROWS_UP + guard = base + size - thread->attr.guard_size; + start = base; +#else + guard = base; + start = base + size; +#endif + if (mprotect(guard, thread->attr.guard_size, PROT_NONE) == -1) { + munmap(base, size); + return (NULL); + } + + /* wrap up the info in a struct stack and return it */ + stack = malloc(sizeof(*stack)); + if (!stack) { + mprotect(guard, thread->attr.guard_size, + PROT_EXEC | PROT_READ | PROT_WRITE); + munmap(base, size); + return (NULL); + } + stack->sp = start; + stack->base = base; + stack->guard = guard; + stack->guardsize = thread->attr.guard_size; + stack->len = size; + return (stack); + } + return (NULL); +} + +void +_rthread_free_stack(struct stack *stack) +{ + mprotect(stack->guard, stack->guardsize, + PROT_EXEC | PROT_READ | PROT_WRITE); + munmap(stack->base, stack->len); + free(stack); +} + |