diff options
| author | Rich Felker <dalias@aerifal.cx> | 2012-06-09 19:53:29 -0400 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2012-06-09 19:53:29 -0400 | 
| commit | 819006a88b9473872fee91135b06f4e23231d97e (patch) | |
| tree | a123767e77980a5feeee0e05a21ea2fe2b2a2b8e | |
| parent | f457b1cb0d49f1b47bc7baf4bb516f1860816f03 (diff) | |
| download | musl-819006a88b9473872fee91135b06f4e23231d97e.tar.gz | |
add pthread_attr_setstack interface (and get)
i originally omitted these (optional, per POSIX) interfaces because i
considered them backwards implementation details. however, someone
later brought to my attention a fairly legitimate use case: allocating
thread stacks in memory that's setup for sharing and/or fast transfer
between CPU and GPU so that the thread can move data to a GPU directly
from automatic-storage buffers without having to go through additional
buffer copies.
perhaps there are other situations in which these interfaces are
useful too.
| -rw-r--r-- | src/internal/pthread_impl.h | 3 | ||||
| -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 | 
4 files changed, 39 insertions, 10 deletions
| diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index d67edf2f..0ce3c1e8 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -59,7 +59,8 @@ struct __timer {  #define _a_stacksize __u.__s[0]  #define _a_guardsize __u.__s[1] -#define _a_detach __u.__i[2*__SU+0] +#define _a_stackaddr __u.__s[2] +#define _a_detach __u.__i[3*__SU+0]  #define _m_type __u.__i[0]  #define _m_lock __u.__i[1]  #define _m_waiters __u.__i[2] 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; | 
