diff options
Diffstat (limited to 'src/thread')
-rw-r--r-- | src/thread/pthread_attr_getstack.c | 10 | ||||
-rw-r--r-- | src/thread/pthread_attr_setstack.c | 14 | ||||
-rw-r--r-- | src/thread/pthread_create.c | 22 |
3 files changed, 37 insertions, 9 deletions
diff --git a/src/thread/pthread_attr_getstack.c b/src/thread/pthread_attr_getstack.c new file mode 100644 index 00000000..07ac5926 --- /dev/null +++ b/src/thread/pthread_attr_getstack.c @@ -0,0 +1,10 @@ +#include "pthread_impl.h" + +int pthread_attr_getstack(const pthread_attr_t *a, void **addr, size_t *size) +{ + if (!a->_a_stackaddr) + return EINVAL; + *size = a->_a_stacksize + DEFAULT_STACK_SIZE; + *addr = (void *)(a->_a_stackaddr - *size); + return 0; +} diff --git a/src/thread/pthread_attr_setstack.c b/src/thread/pthread_attr_setstack.c new file mode 100644 index 00000000..c51ad34d --- /dev/null +++ b/src/thread/pthread_attr_setstack.c @@ -0,0 +1,14 @@ +#include "pthread_impl.h" + +/* pthread_key_create.c overrides this */ +static const size_t dummy = 0; +weak_alias(dummy, __pthread_tsd_size); + +int pthread_attr_setstack(pthread_attr_t *a, void *addr, size_t size) +{ + if (size-PTHREAD_STACK_MIN-__pthread_tsd_size > SIZE_MAX/4) + return EINVAL; + a->_a_stackaddr = (size_t)addr + size; + a->_a_stacksize = size - DEFAULT_STACK_SIZE; + return 0; +} diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 5b34e7e8..48290d35 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -98,16 +98,20 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo libc.threaded = 1; } - if (attr) { - guard = ROUND(attr->_a_guardsize + DEFAULT_GUARD_SIZE); - size = guard + ROUND(attr->_a_stacksize + DEFAULT_STACK_SIZE); + if (attr && attr->_a_stackaddr) { + map = 0; + tsd = (void *)(attr->_a_stackaddr-__pthread_tsd_size & -16); + } else { + if (attr) { + guard = ROUND(attr->_a_guardsize + DEFAULT_GUARD_SIZE); + size = guard + ROUND(attr->_a_stacksize + DEFAULT_STACK_SIZE); + } + size += __pthread_tsd_size; + map = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); + if (map == MAP_FAILED) return EAGAIN; + if (guard) mprotect(map, guard, PROT_NONE); + tsd = map + size - __pthread_tsd_size; } - size += __pthread_tsd_size; - map = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); - if (map == MAP_FAILED) return EAGAIN; - if (guard) mprotect(map, guard, PROT_NONE); - - tsd = map + size - __pthread_tsd_size; new = (void *)(tsd - sizeof *new - PAGE_SIZE%sizeof *new); new->map_base = map; new->map_size = size; |