summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-06-09 19:53:29 -0400
committerRich Felker <dalias@aerifal.cx>2012-06-09 19:53:29 -0400
commit819006a88b9473872fee91135b06f4e23231d97e (patch)
treea123767e77980a5feeee0e05a21ea2fe2b2a2b8e
parentf457b1cb0d49f1b47bc7baf4bb516f1860816f03 (diff)
downloadmusl-819006a88b9473872fee91135b06f4e23231d97e.tar.gz
musl-819006a88b9473872fee91135b06f4e23231d97e.tar.bz2
musl-819006a88b9473872fee91135b06f4e23231d97e.tar.xz
musl-819006a88b9473872fee91135b06f4e23231d97e.zip
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.h3
-rw-r--r--src/thread/pthread_attr_getstack.c10
-rw-r--r--src/thread/pthread_attr_setstack.c14
-rw-r--r--src/thread/pthread_create.c22
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;