diff --git a/libc/fmt/__xpg_strerror_r.c b/libc/fmt/__xpg_strerror_r.c new file mode 100644 index 000000000..888619bc5 --- /dev/null +++ b/libc/fmt/__xpg_strerror_r.c @@ -0,0 +1,23 @@ +/*-*- 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/fmt/fmt.h" + +int __xpg_strerror_r(int a, char *b, size_t c) { + return strerror_r(a, b, c); +} diff --git a/libc/intrin/pthread.h b/libc/intrin/pthread.h index 258564574..487b214a1 100644 --- a/libc/intrin/pthread.h +++ b/libc/intrin/pthread.h @@ -4,6 +4,8 @@ #include "libc/calls/struct/timespec.h" #include "libc/dce.h" +#define PTHREAD_KEYS_MAX 64 + #define PTHREAD_ONCE_INIT 0 #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL @@ -24,6 +26,8 @@ COSMOPOLITAN_C_START_ typedef unsigned long *pthread_t; typedef int pthread_once_t; +typedef unsigned pthread_key_t; +typedef void (*pthread_key_dtor)(void *); typedef struct { int attr; @@ -105,6 +109,10 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *); int pthread_rwlock_trywrlock(pthread_rwlock_t *); int pthread_rwlock_timedwrlock(pthread_rwlock_t *, const struct timespec *); int pthread_rwlock_unlock(pthread_rwlock_t *); +int pthread_key_create(pthread_key_t *, pthread_key_dtor); +int pthread_key_delete(pthread_key_t); +int pthread_setspecific(pthread_key_t, void *); +void *pthread_getspecific(pthread_key_t); #define pthread_mutexattr_init(pAttr) ((pAttr)->attr = PTHREAD_MUTEX_DEFAULT, 0) #define pthread_mutexattr_destroy(pAttr) ((pAttr)->attr = 0) diff --git a/libc/str/str.h b/libc/str/str.h index fbf461e9a..d91a19ef0 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -266,6 +266,7 @@ char *strerrno(int) nosideeffect libcesque; char *strerdoc(int) nosideeffect libcesque; int strerror_r(int, char *, size_t) dontthrow nocallback; int strerror_wr(int, uint32_t, char *, size_t) dontthrow nocallback; +int __xpg_strerror_r(int, char *, size_t) dontthrow nocallback; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/thread/create.c b/libc/thread/create.c index 7e1518f84..00513dc35 100644 --- a/libc/thread/create.c +++ b/libc/thread/create.c @@ -22,6 +22,7 @@ #include "libc/errno.h" #include "libc/intrin/setjmp.internal.h" #include "libc/macros.internal.h" +#include "libc/nexgen32e/threaded.h" #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -101,6 +102,7 @@ int cthread_create(cthread_t *ptd, const cthread_attr_t *attr, int rc, tid; cthread_t td; cthread_attr_t default_attr; + __threaded = true; cthread_zombies_reap(); cthread_attr_init(&default_attr); if ((td = cthread_allocate(attr ? attr : &default_attr))) { diff --git a/libc/thread/ctor.S b/libc/thread/ctor.S new file mode 100644 index 000000000..d8fddefc8 --- /dev/null +++ b/libc/thread/ctor.S @@ -0,0 +1,27 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 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/macros.internal.h" + + .init.start 400,_main_thread_ctor + push %rdi + push %rsi + call _main_thread_init + pop %rsi + pop %rdi + .init.end 400,_main_thread_ctor diff --git a/libc/thread/init.c b/libc/thread/init.c index 51262c110..c4da0ceff 100644 --- a/libc/thread/init.c +++ b/libc/thread/init.c @@ -29,7 +29,7 @@ #include "libc/sysv/consts/prot.h" #include "libc/thread/thread.h" -static textstartup void _main_thread_init(void) { +textstartup void _main_thread_init(void) { _Static_assert(offsetof(struct cthread_descriptor_t, self) == 0x00, ""); _Static_assert(offsetof(struct cthread_descriptor_t, self2) == 0x30, ""); _Static_assert(offsetof(struct cthread_descriptor_t, tid) == 0x38, ""); @@ -65,10 +65,4 @@ static textstartup void _main_thread_init(void) { // Set FS __install_tls((char *)td); - assert(cthread_self()->tid == gettid()); - __threaded = true; } - -const void *const _main_thread_ctor[] initarray = { - _main_thread_init, -}; diff --git a/libc/thread/internal.h b/libc/thread/internal.h new file mode 100644 index 000000000..346c11399 --- /dev/null +++ b/libc/thread/internal.h @@ -0,0 +1,14 @@ +#ifndef COSMOPOLITAN_LIBC_THREAD_INTERNAL_H_ +#define COSMOPOLITAN_LIBC_THREAD_INTERNAL_H_ +#include "libc/intrin/pthread.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +extern uint64_t _pthread_key_usage[(PTHREAD_KEYS_MAX + 63) / 64]; +extern pthread_key_dtor _pthread_key_dtor[PTHREAD_KEYS_MAX]; + +void _pthread_key_destruct(void *[PTHREAD_KEYS_MAX]); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_THREAD_INTERNAL_H_ */ diff --git a/libc/thread/key.c b/libc/thread/key.c new file mode 100644 index 000000000..954369123 --- /dev/null +++ b/libc/thread/key.c @@ -0,0 +1,22 @@ +/*-*- 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/thread/internal.h" + +uint64_t _pthread_key_usage[(PTHREAD_KEYS_MAX + 63) / 64]; +pthread_key_dtor _pthread_key_dtor[PTHREAD_KEYS_MAX]; diff --git a/libc/thread/pthread_getspecific.c b/libc/thread/pthread_getspecific.c new file mode 100644 index 000000000..4ee71c174 --- /dev/null +++ b/libc/thread/pthread_getspecific.c @@ -0,0 +1,34 @@ +/*-*- 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/errno.h" +#include "libc/nexgen32e/gettls.h" +#include "libc/thread/thread.h" + +STATIC_YOINK("_main_thread_ctor"); + +/** + * Gets value of TLS slot for current thread. + */ +void *pthread_getspecific(pthread_key_t key) { + if (key < PTHREAD_KEYS_MAX) { + return ((cthread_t)__get_tls_inline())->key[key]; + } else { + return 0; + } +} diff --git a/libc/thread/pthread_key_create.c b/libc/thread/pthread_key_create.c new file mode 100644 index 000000000..88981bb97 --- /dev/null +++ b/libc/thread/pthread_key_create.c @@ -0,0 +1,51 @@ +/*-*- 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/errno.h" +#include "libc/nexgen32e/bsr.h" +#include "libc/nexgen32e/gettls.h" +#include "libc/runtime/runtime.h" +#include "libc/thread/internal.h" +#include "libc/thread/thread.h" + +STATIC_YOINK("_main_thread_ctor"); + +/** + * Allocates TLS slot. + */ +int pthread_key_create(pthread_key_t *key, pthread_key_dtor dtor) { + int i, j; + for (i = 0; i < (PTHREAD_KEYS_MAX + 63) / 64; ++i) { + if (~_pthread_key_usage[i]) { + j = bsrl(~_pthread_key_usage[i]); + _pthread_key_usage[i] |= 1ul << j; + _pthread_key_dtor[i * 64 + j] = dtor; + *key = i * 64 + j; + return 0; + } + } + return EAGAIN; +} + +static textexit void _pthread_key_atexit(void) { + _pthread_key_destruct(((cthread_t)__get_tls())->key); +} + +__attribute__((__constructor__)) static textstartup void _pthread_key_init() { + atexit(_pthread_key_atexit); +} diff --git a/libc/thread/pthread_key_delete.c b/libc/thread/pthread_key_delete.c new file mode 100644 index 000000000..998e78ac0 --- /dev/null +++ b/libc/thread/pthread_key_delete.c @@ -0,0 +1,34 @@ +/*-*- 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/errno.h" +#include "libc/thread/internal.h" +#include "libc/thread/thread.h" + +/** + * Deletes TLS slot. + */ +int pthread_key_delete(pthread_key_t key) { + if (key < PTHREAD_KEYS_MAX) { + _pthread_key_usage[key / 64] &= ~(1ul << (key % 64)); + _pthread_key_dtor[key] = 0; + return 0; + } else { + return EINVAL; + } +} diff --git a/libc/thread/pthread_key_destruct.c b/libc/thread/pthread_key_destruct.c new file mode 100644 index 000000000..3c5a913fe --- /dev/null +++ b/libc/thread/pthread_key_destruct.c @@ -0,0 +1,41 @@ +/*-*- 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/nexgen32e/bsr.h" +#include "libc/thread/internal.h" +#include "libc/thread/thread.h" + +void _pthread_key_destruct(void *key[PTHREAD_KEYS_MAX]) { + int i, j; + uint64_t x; + void *value; + pthread_key_dtor dtor; +StartOver: + for (i = 0; i < (PTHREAD_KEYS_MAX + 63) / 64; ++i) { + x = _pthread_key_usage[i]; + while (x) { + j = bsrl(x); + if ((dtor = _pthread_key_dtor[i * 64 + j]) && (value = key[i * 64 + j])) { + key[i * 64 + j] = 0; + dtor(value); + goto StartOver; + } + x &= ~(1ul << j); + } + } +} diff --git a/libc/thread/pthread_setspecific.c b/libc/thread/pthread_setspecific.c new file mode 100644 index 000000000..da8a77409 --- /dev/null +++ b/libc/thread/pthread_setspecific.c @@ -0,0 +1,35 @@ +/*-*- 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/errno.h" +#include "libc/nexgen32e/gettls.h" +#include "libc/thread/thread.h" + +STATIC_YOINK("_main_thread_ctor"); + +/** + * Sets value of TLS slot for current thread. + */ +int pthread_setspecific(pthread_key_t key, void *val) { + if (key < PTHREAD_KEYS_MAX) { + ((cthread_t)__get_tls_inline())->key[key] = val; + return 0; + } else { + return EINVAL; + } +} diff --git a/libc/thread/thread.h b/libc/thread/thread.h index 2fbd9a449..757204a57 100644 --- a/libc/thread/thread.h +++ b/libc/thread/thread.h @@ -1,6 +1,7 @@ #ifndef COSMOPOLITAN_LIBC_THREAD_THREAD_H_ #define COSMOPOLITAN_LIBC_THREAD_THREAD_H_ #include "libc/calls/struct/timespec.h" +#include "libc/intrin/pthread.h" #include "libc/runtime/runtime.h" #define CTHREAD_CREATE_DETACHED 1 @@ -33,6 +34,7 @@ struct cthread_descriptor_t { char *top, *bottom; } stack, alloc; jmp_buf exiter; + void *key[PTHREAD_KEYS_MAX]; }; typedef struct cthread_descriptor_t *cthread_t; diff --git a/test/libc/thread/pthread_key_create_test.c b/test/libc/thread/pthread_key_create_test.c new file mode 100644 index 000000000..ced6cf725 --- /dev/null +++ b/test/libc/thread/pthread_key_create_test.c @@ -0,0 +1,38 @@ +/*-*- 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/mem/mem.h" +#include "libc/testlib/testlib.h" +#include "libc/thread/thread.h" + +TEST(pthread_key_create, testRunsDtors_becauseNoLeakReport) { + void *x; + pthread_key_t key; + x = malloc(123); + EXPECT_EQ(0, pthread_key_create(&key, free)); + EXPECT_EQ(0, pthread_setspecific(key, x)); + EXPECT_EQ(x, pthread_getspecific(key)); + x = malloc(123); + EXPECT_EQ(0, pthread_key_create(&key, free)); + EXPECT_EQ(0, pthread_setspecific(key, x)); + EXPECT_EQ(x, pthread_getspecific(key)); + x = malloc(123); + EXPECT_EQ(0, pthread_key_create(&key, free)); + EXPECT_EQ(0, pthread_setspecific(key, x)); + EXPECT_EQ(x, pthread_getspecific(key)); +}