Преглед на файлове

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.
Rich Felker преди 12 години
родител
ревизия
819006a88b
променени са 4 файла, в които са добавени 39 реда и са изтрити 10 реда
  1. 2 1
      src/internal/pthread_impl.h
  2. 10 0
      src/thread/pthread_attr_getstack.c
  3. 14 0
      src/thread/pthread_attr_setstack.c
  4. 13 9
      src/thread/pthread_create.c

+ 2 - 1
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]

+ 10 - 0
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;
+}

+ 14 - 0
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;
+}

+ 13 - 9
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;