diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c index 7d4056d25..666a6b8e3 100644 --- a/libc/bionic/pthread.c +++ b/libc/bionic/pthread.c @@ -43,6 +43,9 @@ #include #include #include +#include +#include +#include extern int __pthread_clone(int (*fn)(void*), void *child_stack, int flags, void *arg); extern void _exit_with_stack_teardown(void * stackBase, int stackSize, int retCode); @@ -1721,3 +1724,54 @@ int pthread_once( pthread_once_t* once_control, void (*init_routine)(void) ) } 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; +} diff --git a/libc/include/pthread.h b/libc/include/pthread.h index 6603b3f6c..c0aa4b9df 100644 --- a/libc/include/pthread.h +++ b/libc/include/pthread.h @@ -226,6 +226,8 @@ int pthread_getcpuclockid(pthread_t tid, clockid_t *clockid); int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); +int pthread_setname_np(pthread_t thid, const char *thname); + typedef void (*__pthread_cleanup_func_t)(void*); typedef struct __pthread_cleanup_t { diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 1ada37e51..73b7f41b0 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -185,6 +185,12 @@ extern int cacheflush(long start, long end, long flags); extern pid_t tcgetpgrp(int fd); extern int tcsetpgrp(int fd, pid_t _pid); +#define TEMP_FAILURE_RETRY(expr) \ + ({ long int __ret; \ + do __ret = (long int)(expr); \ + while (__ret == -1L && errno == EINTR); \ + __ret; }) + __END_DECLS #endif /* _UNISTD_H_ */