Revert "More pthreads cleanup."
This reverts commit 2a1bb4e64677b9abbc17173c79768ed494565047
Change-Id: Ia443d0748015c8e9fc3121e40e68258616767b51
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index bdf2b87..e1ace7d 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -26,12 +26,23 @@
* SUCH DAMAGE.
*/
-#include <pthread.h>
-
+#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
+#include <malloc.h>
+#include <memory.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <sys/atomics.h>
#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
#include "bionic_atomic_inline.h"
@@ -73,8 +84,23 @@
static const int kPthreadInitFailed = 1;
+#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
+#define PTHREAD_ATTR_FLAG_USER_STACK 0x00000002
+
+#define DEFAULT_STACKSIZE (1024 * 1024)
+
static pthread_mutex_t mmap_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static const pthread_attr_t gDefaultPthreadAttr = {
+ .flags = 0,
+ .stack_base = NULL,
+ .stack_size = DEFAULT_STACKSIZE,
+ .guard_size = PAGE_SIZE,
+ .sched_policy = SCHED_NORMAL,
+ .sched_priority = 0
+};
+
__LIBC_HIDDEN__ pthread_internal_t* gThreadList = NULL;
__LIBC_HIDDEN__ pthread_mutex_t gThreadListLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t gDebuggerNotificationLock = PTHREAD_MUTEX_INITIALIZER;
@@ -280,7 +306,7 @@
pthread_internal_t* thread = calloc(sizeof(*thread), 1);
if (thread == NULL) {
- return EAGAIN;
+ return ENOMEM;
}
thread->allocated_on_heap = true;
@@ -295,7 +321,7 @@
stack = mkstack(stack_size, attr->guard_size);
if (stack == NULL) {
free(thread);
- return EAGAIN;
+ return ENOMEM;
}
}
@@ -353,6 +379,152 @@
}
+int pthread_attr_init(pthread_attr_t * attr)
+{
+ *attr = gDefaultPthreadAttr;
+ return 0;
+}
+
+int pthread_attr_destroy(pthread_attr_t * attr)
+{
+ memset(attr, 0x42, sizeof(pthread_attr_t));
+ return 0;
+}
+
+int pthread_attr_setdetachstate(pthread_attr_t * attr, int state)
+{
+ if (state == PTHREAD_CREATE_DETACHED) {
+ attr->flags |= PTHREAD_ATTR_FLAG_DETACHED;
+ } else if (state == PTHREAD_CREATE_JOINABLE) {
+ attr->flags &= ~PTHREAD_ATTR_FLAG_DETACHED;
+ } else {
+ return EINVAL;
+ }
+ return 0;
+}
+
+int pthread_attr_getdetachstate(pthread_attr_t const * attr, int * state)
+{
+ *state = (attr->flags & PTHREAD_ATTR_FLAG_DETACHED)
+ ? PTHREAD_CREATE_DETACHED
+ : PTHREAD_CREATE_JOINABLE;
+ return 0;
+}
+
+int pthread_attr_setschedpolicy(pthread_attr_t * attr, int policy)
+{
+ attr->sched_policy = policy;
+ return 0;
+}
+
+int pthread_attr_getschedpolicy(pthread_attr_t const * attr, int * policy)
+{
+ *policy = attr->sched_policy;
+ return 0;
+}
+
+int pthread_attr_setschedparam(pthread_attr_t * attr, struct sched_param const * param)
+{
+ attr->sched_priority = param->sched_priority;
+ return 0;
+}
+
+int pthread_attr_getschedparam(pthread_attr_t const * attr, struct sched_param * param)
+{
+ param->sched_priority = attr->sched_priority;
+ return 0;
+}
+
+int pthread_attr_setstacksize(pthread_attr_t * attr, size_t stack_size)
+{
+ if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) {
+ return EINVAL;
+ }
+ attr->stack_size = stack_size;
+ return 0;
+}
+
+int pthread_attr_getstacksize(pthread_attr_t const * attr, size_t * stack_size)
+{
+ *stack_size = attr->stack_size;
+ return 0;
+}
+
+int pthread_attr_setstackaddr(pthread_attr_t * attr __attribute__((unused)),
+ void * stack_addr __attribute__((unused)))
+{
+ // This was removed from POSIX.1-2008, and is not implemented on bionic.
+ // Needed for ABI compatibility with the NDK.
+ return ENOSYS;
+}
+
+int pthread_attr_getstackaddr(pthread_attr_t const * attr, void ** stack_addr)
+{
+ // This was removed from POSIX.1-2008.
+ // Needed for ABI compatibility with the NDK.
+ *stack_addr = (char*)attr->stack_base + attr->stack_size;
+ return 0;
+}
+
+int pthread_attr_setstack(pthread_attr_t * attr, void * stack_base, size_t stack_size)
+{
+ if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) {
+ return EINVAL;
+ }
+ if ((uint32_t)stack_base & (PAGE_SIZE - 1)) {
+ return EINVAL;
+ }
+ attr->stack_base = stack_base;
+ attr->stack_size = stack_size;
+ return 0;
+}
+
+int pthread_attr_getstack(pthread_attr_t const * attr, void ** stack_base, size_t * stack_size)
+{
+ *stack_base = attr->stack_base;
+ *stack_size = attr->stack_size;
+ return 0;
+}
+
+int pthread_attr_setguardsize(pthread_attr_t * attr, size_t guard_size)
+{
+ if (guard_size & (PAGE_SIZE - 1) || guard_size < PAGE_SIZE) {
+ return EINVAL;
+ }
+
+ attr->guard_size = guard_size;
+ return 0;
+}
+
+int pthread_attr_getguardsize(pthread_attr_t const * attr, size_t * guard_size)
+{
+ *guard_size = attr->guard_size;
+ return 0;
+}
+
+int pthread_getattr_np(pthread_t thid, pthread_attr_t * attr)
+{
+ pthread_internal_t * thread = (pthread_internal_t *)thid;
+ *attr = thread->attr;
+ return 0;
+}
+
+int pthread_attr_setscope(pthread_attr_t *attr __attribute__((unused)), int scope)
+{
+ if (scope == PTHREAD_SCOPE_SYSTEM)
+ return 0;
+ if (scope == PTHREAD_SCOPE_PROCESS)
+ return ENOTSUP;
+
+ return EINVAL;
+}
+
+int pthread_attr_getscope(pthread_attr_t const *attr __attribute__((unused)))
+{
+ return PTHREAD_SCOPE_SYSTEM;
+}
+
+
/* CAVEAT: our implementation of pthread_cleanup_push/pop doesn't support C++ exceptions
* and thread cancelation
*/
@@ -1709,6 +1881,57 @@
return 0;
}
+/* This value is not exported by kernel headers, so hardcode it here */
+#define MAX_TASK_COMM_LEN 16
+#define TASK_COMM_FMT "/proc/self/task/%u/comm"
+
+int pthread_setname_np(pthread_t thid, const char *thname)
+{
+ size_t thname_len;
+ int saved_errno, ret;
+
+ if (thid == 0 || thname == NULL)
+ return EINVAL;
+
+ thname_len = strlen(thname);
+ if (thname_len >= MAX_TASK_COMM_LEN)
+ return ERANGE;
+
+ saved_errno = errno;
+ if (thid == pthread_self())
+ {
+ ret = prctl(PR_SET_NAME, (unsigned long)thname, 0, 0, 0) ? errno : 0;
+ }
+ else
+ {
+ /* Have to change another thread's name */
+ pthread_internal_t *thread = (pthread_internal_t *)thid;
+ char comm_name[sizeof(TASK_COMM_FMT) + 8];
+ ssize_t n;
+ int fd;
+
+ snprintf(comm_name, sizeof(comm_name), TASK_COMM_FMT, (unsigned int)thread->kernel_id);
+ fd = open(comm_name, O_RDWR);
+ if (fd == -1)
+ {
+ ret = errno;
+ goto exit;
+ }
+ n = TEMP_FAILURE_RETRY(write(fd, thname, thname_len));
+ close(fd);
+
+ if (n < 0)
+ ret = errno;
+ else if ((size_t)n != thname_len)
+ ret = EIO;
+ else
+ ret = 0;
+ }
+exit:
+ errno = saved_errno;
+ return ret;
+}
+
/* Return the kernel thread ID for a pthread.
* This is only defined for implementations where pthread <-> kernel is 1:1, which this is.
* Not the same as pthread_getthreadid_np, which is commonly defined to be opaque.