mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-25 13:58:32 +00:00
Add phtread_setname_np() and pthread_getname_np()
This commit is contained in:
parent
114176c304
commit
de511bc71a
8 changed files with 355 additions and 4 deletions
|
@ -91,6 +91,8 @@ void pthread_exit(void *) wontreturn;
|
||||||
pthread_t pthread_self(void) pureconst;
|
pthread_t pthread_self(void) pureconst;
|
||||||
pthread_id_np_t pthread_getthreadid_np(void);
|
pthread_id_np_t pthread_getthreadid_np(void);
|
||||||
int64_t pthread_getunique_np(pthread_t);
|
int64_t pthread_getunique_np(pthread_t);
|
||||||
|
int pthread_setname_np(pthread_t, const char *);
|
||||||
|
int pthread_getname_np(pthread_t, char *, size_t);
|
||||||
int pthread_getattr_np(pthread_t, pthread_attr_t *);
|
int pthread_getattr_np(pthread_t, pthread_attr_t *);
|
||||||
int pthread_attr_init(pthread_attr_t *);
|
int pthread_attr_init(pthread_attr_t *);
|
||||||
int pthread_attr_destroy(pthread_attr_t *);
|
int pthread_attr_destroy(pthread_attr_t *);
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* The top 16 bytes of a stack can't be used due to openbsd:stackbound
|
* The top 16 bytes of a stack can't be used due to openbsd:stackbound
|
||||||
* and those bytes are also poisoned under ASAN build modes.
|
* and those bytes are also poisoned under ASAN build modes.
|
||||||
*
|
*
|
||||||
* @return stack bottom address on success, or null w/ errrno
|
* @return stack bottom address on success, or null w/ errno
|
||||||
*/
|
*/
|
||||||
void *_mapstack(void) {
|
void *_mapstack(void) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
|
@ -798,6 +798,24 @@ scall setrtable 0xfff136ffffffffff globl
|
||||||
scall swapctl 0x10f0c1ffffffffff globl
|
scall swapctl 0x10f0c1ffffffffff globl
|
||||||
scall thrkill 0xfff077ffffffffff globl
|
scall thrkill 0xfff077ffffffffff globl
|
||||||
scall sys_unveil 0xfff072ffffffffff globl hidden
|
scall sys_unveil 0xfff072ffffffffff globl hidden
|
||||||
|
#──────────────────────────NETBSD────────────────────────────
|
||||||
|
#scall _lwp_create 0x135fffffffffffff globl # int _lwp_create(const struct ucontext_netbsd *ucp, uint64_t flags, int *new_lwp)
|
||||||
|
#scall _lwp_exit 0x136fffffffffffff globl # int _lwp_exit(void)
|
||||||
|
#scall _lwp_self 0x137fffffffffffff globl # int _lwp_self(void)
|
||||||
|
#scall _lwp_wait 0x138fffffffffffff globl # int _lwp_wait(int wait_for, int *departed)
|
||||||
|
#scall _lwp_suspend 0x139fffffffffffff globl # int _lwp_suspend(int target)
|
||||||
|
#scall _lwp_continue 0x13afffffffffffff globl # int _lwp_continue(int target)
|
||||||
|
#scall _lwp_wakeup 0x13bfffffffffffff globl # int _lwp_wakeup(int target)
|
||||||
|
#scall _lwp_getprivate 0x13cfffffffffffff globl # void *_lwp_getprivate(void)
|
||||||
|
#scall _lwp_setprivate 0x13dfffffffffffff globl # int _lwp_setprivate(void *ptr)
|
||||||
|
#scall _lwp_kill 0x13efffffffffffff globl # int _lwp_kill(int target, int signo)
|
||||||
|
#scall _lwp_detach 0x13ffffffffffffff globl # int _lwp_park(int clock_id, int flags, struct timespec *ts, int unpark, const void *hint, const void *unparkhint)
|
||||||
|
#scall _lwp_park 0x1defffffffffffff globl # int _lwp_park(int clock_id, int flags, struct timespec *ts, int unpark, const void *hint, const void *unparkhint)
|
||||||
|
#scall _lwp_unpark 0x141fffffffffffff globl # int _lwp_unpark_all(int target, const void *hint)
|
||||||
|
#scall _lwp_unpark_all 0x142fffffffffffff globl # int _lwp_unpark_all(const int *targets, size_t ntargets, const void *hint)
|
||||||
|
#scall _lwp_setname 0x143fffffffffffff globl # int _lwp_setname(int target, const char *name)
|
||||||
|
#scall _lwp_getname 0x144fffffffffffff globl # int _lwp_getname(int target, char *name, size_t len)
|
||||||
|
#scall _lwp_ctl 0x145fffffffffffff globl # int _lwp_ctl(int features, struct lwpctl **address)
|
||||||
|
|
||||||
# The Fifth Bell System Interface, Community Edition
|
# The Fifth Bell System Interface, Community Edition
|
||||||
# » beyond the pale
|
# » beyond the pale
|
||||||
|
|
|
@ -35,12 +35,13 @@
|
||||||
*
|
*
|
||||||
* pthread_t id;
|
* pthread_t id;
|
||||||
* pthread_attr_t attr;
|
* pthread_attr_t attr;
|
||||||
|
* char *stk = _mapstack();
|
||||||
* pthread_attr_init(&attr);
|
* pthread_attr_init(&attr);
|
||||||
* pthread_attr_setstack(&attr, gc(malloc(GetStackSize())),
|
* pthread_attr_setstack(&attr, stk, GetStackSize());
|
||||||
* GetStackSize());
|
|
||||||
* pthread_create(&id, &attr, func, 0);
|
* pthread_create(&id, &attr, func, 0);
|
||||||
* pthread_attr_destroy(&attr);
|
* pthread_attr_destroy(&attr);
|
||||||
* pthread_join(id, 0);
|
* pthread_join(id, 0);
|
||||||
|
* _freestack(stk);
|
||||||
*
|
*
|
||||||
* Your stack must have at least `PTHREAD_STACK_MIN` bytes, which
|
* Your stack must have at least `PTHREAD_STACK_MIN` bytes, which
|
||||||
* Cosmpolitan Libc defines as `GetStackSize()`. It's a link-time
|
* Cosmpolitan Libc defines as `GetStackSize()`. It's a link-time
|
||||||
|
@ -52,11 +53,16 @@
|
||||||
* (e.g. kprintf) assumes that stack sizes are two-powers and are
|
* (e.g. kprintf) assumes that stack sizes are two-powers and are
|
||||||
* aligned to that two-power. Conformance isn't required since we
|
* aligned to that two-power. Conformance isn't required since we
|
||||||
* say caveat emptor to those who don't maintain these invariants
|
* say caveat emptor to those who don't maintain these invariants
|
||||||
|
* please consider using _mapstack() which always does it perfect
|
||||||
|
* or use `mmap(0, GetStackSize() << 1, ...)` for a bigger stack.
|
||||||
*
|
*
|
||||||
* Unlike pthread_attr_setstacksize(), this function permits just
|
* Unlike pthread_attr_setstacksize(), this function permits just
|
||||||
* about any parameters and will change the values and allocation
|
* about any parameters and will change the values and allocation
|
||||||
* as needed to conform to the mandatory requirements of the host
|
* as needed to conform to the mandatory requirements of the host
|
||||||
* operating system.
|
* operating system even if it doesn't meet the stricter needs of
|
||||||
|
* Cosmopolitan Libc userspace libraries. For example with malloc
|
||||||
|
* allocations, things like page size alignment, shall be handled
|
||||||
|
* automatically for compatibility with existing codebases.
|
||||||
*
|
*
|
||||||
* @param stackaddr is address of stack allocated by caller, and
|
* @param stackaddr is address of stack allocated by caller, and
|
||||||
* may be NULL in which case default behavior is restored
|
* may be NULL in which case default behavior is restored
|
||||||
|
|
118
libc/thread/pthread_getname_np.c
Normal file
118
libc/thread/pthread_getname_np.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/intrin/asmflag.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/pr.h"
|
||||||
|
#include "libc/thread/posixthread.internal.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets name of thread registered with system, e.g.
|
||||||
|
*
|
||||||
|
* char name[64];
|
||||||
|
* pthread_getname_np(thread, name, sizeof(name));
|
||||||
|
*
|
||||||
|
* If the thread doesn't have a name, then empty string is returned.
|
||||||
|
* This implementation guarantees `buf` is always modified, even on
|
||||||
|
* error, and will always be nul-terminated. If `size` is 0 then this
|
||||||
|
* function returns 0. Your `buf` is also chomped to remove newlines.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or errno on error
|
||||||
|
* @raise ERANGE if `size` wasn't large enough, in which case your
|
||||||
|
* result will still be returned truncated if possible
|
||||||
|
* @raise ENOSYS on MacOS, Windows, FreeBSD, and OpenBSD
|
||||||
|
*/
|
||||||
|
int pthread_getname_np(pthread_t thread, char *name, size_t size) {
|
||||||
|
int e, fd, rc, tid, len;
|
||||||
|
|
||||||
|
if (!size) return 0;
|
||||||
|
bzero(name, size);
|
||||||
|
tid = ((struct PosixThread *)thread)->spawn.ptid;
|
||||||
|
|
||||||
|
if (IsLinux()) {
|
||||||
|
// TASK_COMM_LEN is 16 on Linux so we're just being paranoid.
|
||||||
|
char buf[256] = {0};
|
||||||
|
if (tid == gettid()) {
|
||||||
|
e = errno;
|
||||||
|
if (prctl(PR_GET_NAME, buf) == -1) {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char path[128], *p = path;
|
||||||
|
p = stpcpy(p, "/proc/self/task/");
|
||||||
|
p = FormatUint32(p, tid);
|
||||||
|
p = stpcpy(p, "/comm");
|
||||||
|
e = errno;
|
||||||
|
if ((fd = sys_open(path, O_RDONLY | O_CLOEXEC, 0)) == -1) {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = sys_read(fd, buf, sizeof(buf) - 1);
|
||||||
|
rc |= sys_close(fd);
|
||||||
|
if (rc == -1) {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
_chomp(buf);
|
||||||
|
}
|
||||||
|
if ((len = strlen(buf))) {
|
||||||
|
memcpy(name, buf, MIN(len, size - 1));
|
||||||
|
}
|
||||||
|
if (len > size - 1) {
|
||||||
|
return ERANGE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else if (IsNetbsd()) {
|
||||||
|
char cf;
|
||||||
|
int ax, dx;
|
||||||
|
// NetBSD doesn't document the subtleties of its nul-terminator
|
||||||
|
// behavior, so like Linux we shall take the paranoid approach.
|
||||||
|
asm volatile(CFLAG_ASM("syscall")
|
||||||
|
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
|
||||||
|
: "1"(324 /* _lwp_getname */), "D"(tid), "S"(name),
|
||||||
|
"d"(size - 1)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
if (!cf) {
|
||||||
|
// if size + our nul + kernel's nul is the buffer size, then we
|
||||||
|
// can't say with absolute confidence truncation didn't happen.
|
||||||
|
if (strlen(name) + 1 + 1 <= size) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return ERANGE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ax;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
118
libc/thread/pthread_setname_np.c
Normal file
118
libc/thread/pthread_setname_np.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/asmflag.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/pr.h"
|
||||||
|
#include "libc/thread/posixthread.internal.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers custom name of thread with system, e.g.
|
||||||
|
*
|
||||||
|
* void *worker(void *arg) {
|
||||||
|
* pthread_setname_np(pthread_self(), "justine");
|
||||||
|
* pause();
|
||||||
|
* return 0;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* int main(int argc, char *argv[]) {
|
||||||
|
* pthread_t id;
|
||||||
|
* pthread_create(&id, 0, worker, 0);
|
||||||
|
* pthread_join(id, 0);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ProTip: The `htop` software is good at displaying thread names.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or errno on error
|
||||||
|
* @raise ERANGE if length of `name` exceeded system limit, in which
|
||||||
|
* case the name may have still been set with os using truncation
|
||||||
|
* @raise ENOSYS on MacOS, Windows, and OpenBSD
|
||||||
|
* @see pthread_getname_np()
|
||||||
|
*/
|
||||||
|
int pthread_setname_np(pthread_t thread, const char *name) {
|
||||||
|
char path[128], *p;
|
||||||
|
int e, fd, rc, tid, len;
|
||||||
|
|
||||||
|
tid = ((struct PosixThread *)thread)->spawn.ptid;
|
||||||
|
len = strlen(name);
|
||||||
|
|
||||||
|
if (IsLinux()) {
|
||||||
|
if (tid == gettid()) {
|
||||||
|
e = errno;
|
||||||
|
if (prctl(PR_SET_NAME, name) == -1) {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = path;
|
||||||
|
p = stpcpy(p, "/proc/self/task/");
|
||||||
|
p = FormatUint32(p, tid);
|
||||||
|
p = stpcpy(p, "/comm");
|
||||||
|
e = errno;
|
||||||
|
if ((fd = sys_open(path, O_WRONLY | O_CLOEXEC, 0)) == -1) {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = sys_write(fd, name, len);
|
||||||
|
rc |= sys_close(fd);
|
||||||
|
if (rc == -1) {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len > 15) {
|
||||||
|
// linux is documented as truncating here. we still set the name
|
||||||
|
// since the limit might be raised in the future checking return
|
||||||
|
// value of this function is a bummer. Grep it for TASK_COMM_LEN
|
||||||
|
return ERANGE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else if (IsFreebsd()) {
|
||||||
|
char cf;
|
||||||
|
int ax, dx;
|
||||||
|
asm volatile(CFLAG_ASM("syscall")
|
||||||
|
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
|
||||||
|
: "1"(323 /* thr_set_name */), "D"(tid), "S"(name)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
return !cf ? 0 : ax;
|
||||||
|
|
||||||
|
} else if (IsNetbsd()) {
|
||||||
|
char cf;
|
||||||
|
int ax, dx;
|
||||||
|
asm volatile(CFLAG_ASM("syscall")
|
||||||
|
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
|
||||||
|
: "1"(323 /* _lwp_setname */), "D"(tid), "S"(name)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
return !cf ? 0 : ax;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ LIBC_THREAD_A_DIRECTDEPS = \
|
||||||
LIBC_INTRIN \
|
LIBC_INTRIN \
|
||||||
LIBC_MEM \
|
LIBC_MEM \
|
||||||
LIBC_RUNTIME \
|
LIBC_RUNTIME \
|
||||||
|
LIBC_STR \
|
||||||
LIBC_SYSV \
|
LIBC_SYSV \
|
||||||
LIBC_SYSV_CALLS \
|
LIBC_SYSV_CALLS \
|
||||||
LIBC_NEXGEN32E
|
LIBC_NEXGEN32E
|
||||||
|
|
88
test/libc/thread/pthread_setname_np_test.c
Normal file
88
test/libc/thread/pthread_setname_np_test.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/atomic.h"
|
||||||
|
#include "libc/intrin/pthread.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
static void *SetName(void *arg) {
|
||||||
|
ASSERT_EQ(0, pthread_setname_np(pthread_self(), "justine"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(pthread_setname_np, SetName_SystemCallSucceeds) {
|
||||||
|
pthread_t id;
|
||||||
|
if (!IsLinux() || !IsNetbsd() || !IsFreebsd()) return;
|
||||||
|
ASSERT_EQ(0, pthread_create(&id, 0, SetName, 0));
|
||||||
|
ASSERT_EQ(0, pthread_join(id, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *SetGetNameOfSelf(void *arg) {
|
||||||
|
char me[16];
|
||||||
|
ASSERT_EQ(0, pthread_setname_np(pthread_self(), "justine"));
|
||||||
|
ASSERT_EQ(0, pthread_getname_np(pthread_self(), me, sizeof(me)));
|
||||||
|
EXPECT_STREQ("justine", me);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(pthread_setname_np, SetGetNameOfSelf) {
|
||||||
|
pthread_t id;
|
||||||
|
if (!IsLinux() || !IsNetbsd()) return;
|
||||||
|
ASSERT_EQ(0, pthread_create(&id, 0, SetGetNameOfSelf, 0));
|
||||||
|
ASSERT_EQ(0, pthread_join(id, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *GetDefaultName(void *arg) {
|
||||||
|
char me[16];
|
||||||
|
ASSERT_EQ(0, pthread_getname_np(pthread_self(), me, sizeof(me)));
|
||||||
|
EXPECT_STREQ("", me);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(pthread_setname_np, GetDefaultName_IsEmptyString) {
|
||||||
|
pthread_t id;
|
||||||
|
if (!IsLinux() || !IsNetbsd()) return;
|
||||||
|
ASSERT_EQ(0, pthread_create(&id, 0, GetDefaultName, 0));
|
||||||
|
ASSERT_EQ(0, pthread_join(id, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
_Atomic(char) sync1, sync2;
|
||||||
|
|
||||||
|
static void *GetNameOfOtherThreadWorker(void *arg) {
|
||||||
|
pthread_setname_np(pthread_self(), "justine");
|
||||||
|
atomic_store(&sync1, 1);
|
||||||
|
while (!atomic_load(&sync2)) pthread_yield();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(pthread_setname_np, GetNameOfOtherThread) {
|
||||||
|
char me[16];
|
||||||
|
pthread_t id;
|
||||||
|
if (!IsLinux() || !IsNetbsd()) return;
|
||||||
|
ASSERT_EQ(0, pthread_create(&id, 0, GetNameOfOtherThreadWorker, 0));
|
||||||
|
while (!atomic_load(&sync1)) pthread_yield();
|
||||||
|
ASSERT_EQ(0, pthread_getname_np(id, me, sizeof(me)));
|
||||||
|
EXPECT_STREQ("justine", me);
|
||||||
|
ASSERT_EQ(0, pthread_setname_np(id, "tunney"));
|
||||||
|
ASSERT_EQ(0, pthread_getname_np(id, me, sizeof(me)));
|
||||||
|
EXPECT_STREQ("tunney", me);
|
||||||
|
atomic_store(&sync2, 1);
|
||||||
|
ASSERT_EQ(0, pthread_join(id, 0));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue