summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/librthread/Makefile4
-rw-r--r--lib/librthread/rthread.c43
-rw-r--r--lib/librthread/rthread.h11
-rw-r--r--lib/librthread/rthread_attr.c49
-rw-r--r--lib/librthread/rthread_stack.c92
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);
+}
+