diff options
Diffstat (limited to 'lib/libthr')
95 files changed, 1089 insertions, 937 deletions
diff --git a/lib/libthr/Makefile b/lib/libthr/Makefile index dde2a9dce94e..c87be9475390 100644 --- a/lib/libthr/Makefile +++ b/lib/libthr/Makefile @@ -1,17 +1,22 @@ -# -# All library objects contain FreeBSD revision strings by default; they may be -# excluded as a space-saving measure. To produce a library that does -# not contain these strings, add -DSTRIP_FBSDID (see <sys/cdefs.h>) to CFLAGS -# below. - PACKAGE= clibs SHLIBDIR?= /lib +LIBADD= c sys +.if defined(COMPAT_libcompat) +# XXX: work around gcc -m32 + bfd ld path issue for DT_NEEDED symbols. +# https://sourceware.org/bugzilla/show_bug.cgi?id=31395 +LDFLAGS+= -Wl,--rpath=/usr/lib${COMPAT_libcompat} +.endif + .include <src.opts.mk> MK_SSP= no +# SSP forced off already implies FORTIFY_SOURCE=0, but we must make sure that +# one cannot turn it back on. +FORTIFY_SOURCE= 0 LIB=thr SHLIB_MAJOR= 3 + NO_WTHREAD_SAFETY=1 NO_WCAST_ALIGN.gcc=1 # for gcc 4.2 CFLAGS+=-DPTHREAD_KERNEL @@ -26,6 +31,10 @@ CFLAGS+=-I${SRCTOP}/lib/libthread_db CFLAGS.thr_stack.c+= -Wno-cast-align CFLAGS.rtld_malloc.c+= -Wno-cast-align +# Disable compiler builtins so that the compiler does not optimize away rtld's +# attempts to force early PLT resolution for certain functions that may be +# replaced by builtins. +CFLAGS.thr_rtld.c+= -fno-builtin CFLAGS.thr_symbols.c+= -Wno-missing-variable-declarations .if ${MK_ASAN} != "no" # False-positive ASAN error claiming the local "struct sigaction act;" is @@ -44,6 +53,8 @@ CFLAGS+=-D_PTHREAD_FORCED_UNWIND .endif LDFLAGS+=-Wl,-znodelete +LDFLAGS+=-Wl,-zinitfirst +LDFLAGS+=-Wl,--auxiliary,libsys.so.7 VERSION_DEF=${SRCTOP}/lib/libc/Versions.def SYMBOL_MAPS=${.CURDIR}/pthread.map @@ -67,15 +78,20 @@ PRECIOUSLIB= .include "${.CURDIR}/thread/Makefile.inc" SRCS+= rtld_malloc.c +LIBSYS_SRCTOP= ${.CURDIR:H}/libsys +.if exists(${LIBSYS_SRCTOP}/${MACHINE_CPUARCH}/_umtx_op_err.S) +.PATH: ${LIBSYS_SRCTOP}/${MACHINE_CPUARCH} +.else +.PATH: ${LIBSYS_SRCTOP} +.endif +OBJS+= _umtx_op_err.o + .if ${MK_INSTALLLIB} != "no" SYMLINKS+=lib${LIB}.a ${LIBDIR}/libpthread.a .endif .if !defined(NO_PIC) SYMLINKS+=lib${LIB}.so ${LIBDIR}/libpthread.so .endif -.if ${MK_PROFILE} != "no" -SYMLINKS+=lib${LIB}_p.a ${LIBDIR}/libpthread_p.a -.endif HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/lib/libthr/Makefile.depend b/lib/libthr/Makefile.depend index 6ef78fac5cbf..e0d18fcef3a4 100644 --- a/lib/libthr/Makefile.depend +++ b/lib/libthr/Makefile.depend @@ -6,6 +6,7 @@ DIRDEPS = \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ + lib/libsys \ .include <dirdeps.mk> diff --git a/lib/libthr/arch/aarch64/Makefile.inc b/lib/libthr/arch/aarch64/Makefile.inc index 8b137891791f..e69de29bb2d1 100644 --- a/lib/libthr/arch/aarch64/Makefile.inc +++ b/lib/libthr/arch/aarch64/Makefile.inc @@ -1 +0,0 @@ - diff --git a/lib/libthr/arch/aarch64/include/pthread_md.h b/lib/libthr/arch/aarch64/include/pthread_md.h index 75e6abf445ba..4316955f1d3d 100644 --- a/lib/libthr/arch/aarch64/include/pthread_md.h +++ b/lib/libthr/arch/aarch64/include/pthread_md.h @@ -49,4 +49,11 @@ _get_curthread(void) return (_tcb_get()->tcb_thread); } +static __inline void +_thr_resolve_machdep(void) +{ +} + +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/aarch64/include/pthread_tls.h b/lib/libthr/arch/aarch64/include/pthread_tls.h deleted file mode 100644 index 4e02f8d4e03f..000000000000 --- a/lib/libthr/arch/aarch64/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_AARCH64_PTHREAD_TLS_H -#define _ARCH_AARCH64_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/amd64/Makefile.inc b/lib/libthr/arch/amd64/Makefile.inc index 24e5dd7c9b03..fe80e1a73cc9 100644 --- a/lib/libthr/arch/amd64/Makefile.inc +++ b/lib/libthr/arch/amd64/Makefile.inc @@ -1,8 +1,7 @@ - -SRCS+= _umtx_op_err.S - # With the current compiler and libthr code, using SSE in libthr # does not provide enough performance improvement to outweigh # the extra context switch cost. This can measurably impact # performance when the application also does not use enough SSE. CFLAGS+=${CFLAGS_NO_SIMD} + +SRCS+= thr_machdep.c diff --git a/lib/libthr/arch/amd64/amd64/_umtx_op_err.S b/lib/libthr/arch/amd64/amd64/_umtx_op_err.S deleted file mode 100644 index c5fb2f26d6f6..000000000000 --- a/lib/libthr/arch/amd64/amd64/_umtx_op_err.S +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * Copyright (C) 2008 David Xu <davidxu@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Neither the name of the author nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/syscall.h> -#include <machine/asm.h> - -#define RSYSCALL_ERR(x) ENTRY(__CONCAT(x, _err)); \ - mov __CONCAT($SYS_,x),%rax; \ - KERNCALL; \ - ret; \ - END(__CONCAT(x, _err)); - -#define KERNCALL movq %rcx, %r10; syscall - -RSYSCALL_ERR(_umtx_op) - - .section .note.GNU-stack,"",%progbits diff --git a/lib/libthr/arch/amd64/amd64/thr_machdep.c b/lib/libthr/arch/amd64/amd64/thr_machdep.c new file mode 100644 index 000000000000..d23e1689779c --- /dev/null +++ b/lib/libthr/arch/amd64/amd64/thr_machdep.c @@ -0,0 +1,48 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + */ + +#define _WANT_P_OSREL +#include <sys/param.h> +#include <errno.h> +#include <machine/sysarch.h> + +#include "libc_private.h" +#include "thr_private.h" + +void +__thr_setup_tsd(struct pthread *thread) +{ + void *base; + int error; + + if (__getosreldate() < P_OSREL_TLSBASE) { + amd64_set_tlsbase(thread->tcb); + return; + } + + /* + * Make tlsbase handling more compatible with code, like Go + * runtime, which wants to manage fsbase itself, and which do + * not need assistance in setting fsbase for signal handlers. + * + * If the main thread did not used amd64_set_tlsbase(), which + * means that rtld/libc was not utilized, do not use + * amd64_set_tlsbase() either. Also do not mark new threads + * as using C runtime with the THR_C_RUNTIME flag. + */ + error = sysarch(AMD64_GET_TLSBASE, &base); + if (error != 0 && errno == ESRCH) { + __thr_new_flags &= ~THR_C_RUNTIME; + amd64_set_fsbase(thread->tcb); + } else { + amd64_set_tlsbase(thread->tcb); + } +} diff --git a/lib/libthr/arch/amd64/include/pthread_md.h b/lib/libthr/arch/amd64/include/pthread_md.h index fa0802e64ebb..02b73d90f006 100644 --- a/lib/libthr/arch/amd64/include/pthread_md.h +++ b/lib/libthr/arch/amd64/include/pthread_md.h @@ -47,11 +47,16 @@ _get_curthread(void) { struct pthread *thr; - __asm __volatile("movq %%fs:%1, %0" : "=r" (thr) - : "m" (*(volatile u_long *)offsetof(struct tcb, tcb_thread))); + __asm __volatile("movq %%fs:%c1, %0" : "=r" (thr) + : "i" (offsetof(struct tcb, tcb_thread))); return (thr); } -#define HAS__UMTX_OP_ERR 1 +static __inline void +_thr_resolve_machdep(void) +{ +} + +void __thr_setup_tsd(struct pthread *thread); #endif diff --git a/lib/libthr/arch/amd64/include/pthread_tls.h b/lib/libthr/arch/amd64/include/pthread_tls.h deleted file mode 100644 index 2af0aeda4c85..000000000000 --- a/lib/libthr/arch/amd64/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_AMD64_PTHREAD_TLS_H -#define _ARCH_AMD64_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase -= offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/arm/Makefile.inc b/lib/libthr/arch/arm/Makefile.inc new file mode 100644 index 000000000000..4e770cf6b90f --- /dev/null +++ b/lib/libthr/arch/arm/Makefile.inc @@ -0,0 +1,3 @@ +.PATH: ${.CURDIR}/arch/arm +SRCS+= \ + thr_rtld_arm.c diff --git a/lib/libthr/arch/arm/include/pthread_md.h b/lib/libthr/arch/arm/include/pthread_md.h index d616868bdee4..b90568e249ee 100644 --- a/lib/libthr/arch/arm/include/pthread_md.h +++ b/lib/libthr/arch/arm/include/pthread_md.h @@ -48,4 +48,6 @@ _get_curthread(void) return (NULL); } +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/arm/include/pthread_tls.h b/lib/libthr/arch/arm/include/pthread_tls.h deleted file mode 100644 index 27a07f69f474..000000000000 --- a/lib/libthr/arch/arm/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_ARM_PTHREAD_TLS_H -#define _ARCH_ARM_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/arm/thr_rtld_arm.c b/lib/libthr/arch/arm/thr_rtld_arm.c new file mode 100644 index 000000000000..35f5fe56cfff --- /dev/null +++ b/lib/libthr/arch/arm/thr_rtld_arm.c @@ -0,0 +1,67 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Michal Meloun <mmel@freebsd.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <string.h> + +#include "thr_private.h" + +int __aeabi_idiv(int , int ); +unsigned __aeabi_uidiv(unsigned, unsigned ); + +struct {int q; int r;} __aeabi_idivmod(int, int ); +struct {unsigned q; unsigned r;} __aeabi_uidivmod(unsigned, unsigned); + +struct {int64_t q; int64_t r;} __aeabi_ldivmod(int64_t, int64_t); +struct {uint64_t q; uint64_t r;} __aeabi_uldivmod(uint64_t, uint64_t); + +void __aeabi_memset(void *dest, size_t n, int c); +void __aeabi_memclr(void *dest, size_t n); +void __aeabi_memmove(void *dest, void *src, size_t n); +void __aeabi_memcpy(void *dest, void *src, size_t n); +void __aeabi_memcmp(void *dest, void *src, size_t n); + +void +_thr_resolve_machdep(void) +{ + char tmp[2]; + + __aeabi_idiv(1, 1); + __aeabi_uidiv(1, 1); + + __aeabi_idivmod(1, 1); + __aeabi_uidivmod(1, 1); + + __aeabi_ldivmod(1, 1); + __aeabi_uldivmod(1, 1); + + __aeabi_memset(tmp, 1, 0); + __aeabi_memclr(tmp, 1); + __aeabi_memmove(tmp, tmp + 1, 1); + __aeabi_memcpy(tmp, tmp + 1, 1); + __aeabi_memcmp(tmp, tmp + 1, 1); +} diff --git a/lib/libthr/arch/i386/Makefile.inc b/lib/libthr/arch/i386/Makefile.inc index 24e5dd7c9b03..f8013ea914ed 100644 --- a/lib/libthr/arch/i386/Makefile.inc +++ b/lib/libthr/arch/i386/Makefile.inc @@ -1,6 +1,3 @@ - -SRCS+= _umtx_op_err.S - # With the current compiler and libthr code, using SSE in libthr # does not provide enough performance improvement to outweigh # the extra context switch cost. This can measurably impact diff --git a/lib/libthr/arch/i386/i386/_umtx_op_err.S b/lib/libthr/arch/i386/i386/_umtx_op_err.S deleted file mode 100644 index 460bd72604aa..000000000000 --- a/lib/libthr/arch/i386/i386/_umtx_op_err.S +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (C) 2008 David Xu <davidxu@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Neither the name of the author nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <machine/asm.h> -#include <sys/syscall.h> - -#define SYSCALL_ERR(x) \ - ENTRY(__CONCAT(x, _err)); \ - mov __CONCAT($SYS_,x),%eax; \ - int $0x80; \ - ret; \ - END(__CONCAT(x, _err)) - -SYSCALL_ERR(_umtx_op) - - .section .note.GNU-stack,"",%progbits diff --git a/lib/libthr/arch/i386/include/pthread_md.h b/lib/libthr/arch/i386/include/pthread_md.h index 2a396abe3824..43f84c3d0393 100644 --- a/lib/libthr/arch/i386/include/pthread_md.h +++ b/lib/libthr/arch/i386/include/pthread_md.h @@ -47,11 +47,16 @@ _get_curthread(void) { struct pthread *thr; - __asm __volatile("movl %%gs:%1, %0" : "=r" (thr) - : "m" (*(volatile u_int *)offsetof(struct tcb, tcb_thread))); + __asm __volatile("movl %%gs:%c1, %0" : "=r" (thr) + : "i" (offsetof(struct tcb, tcb_thread))); return (thr); } -#define HAS__UMTX_OP_ERR 1 +static __inline void +_thr_resolve_machdep(void) +{ +} + +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) #endif diff --git a/lib/libthr/arch/i386/include/pthread_tls.h b/lib/libthr/arch/i386/include/pthread_tls.h deleted file mode 100644 index b2d0f2dbe845..000000000000 --- a/lib/libthr/arch/i386/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_I386_PTHREAD_TLS_H -#define _ARCH_I386_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase -= offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/powerpc/Makefile.inc b/lib/libthr/arch/powerpc/Makefile.inc deleted file mode 100644 index 663706b1b364..000000000000 --- a/lib/libthr/arch/powerpc/Makefile.inc +++ /dev/null @@ -1,2 +0,0 @@ - -SRCS+= _umtx_op_err.S diff --git a/lib/libthr/arch/powerpc/include/pthread_md.h b/lib/libthr/arch/powerpc/include/pthread_md.h index 14f1703b5460..291f2d9350d9 100644 --- a/lib/libthr/arch/powerpc/include/pthread_md.h +++ b/lib/libthr/arch/powerpc/include/pthread_md.h @@ -49,6 +49,11 @@ _get_curthread(void) return (NULL); } -#define HAS__UMTX_OP_ERR 1 +static __inline void +_thr_resolve_machdep(void) +{ +} + +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/powerpc/include/pthread_tls.h b/lib/libthr/arch/powerpc/include/pthread_tls.h deleted file mode 100644 index e53164436018..000000000000 --- a/lib/libthr/arch/powerpc/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_POWERPC_PTHREAD_TLS_H -#define _ARCH_POWERPC_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/powerpc/powerpc/_umtx_op_err.S b/lib/libthr/arch/powerpc/powerpc/_umtx_op_err.S deleted file mode 100644 index a954962515f6..000000000000 --- a/lib/libthr/arch/powerpc/powerpc/_umtx_op_err.S +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Brandon Bergren <bdragon@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <machine/asm.h> -#include <sys/syscall.h> - - .text - .align 2 -ENTRY(_umtx_op_err) - li %r0, SYS__umtx_op - sc - blr -END(_umtx_op_err) - - .section .note.GNU-stack,"",%progbits diff --git a/lib/libthr/arch/riscv/include/pthread_md.h b/lib/libthr/arch/riscv/include/pthread_md.h index 343f4cae8486..01dcc9c02b8c 100644 --- a/lib/libthr/arch/riscv/include/pthread_md.h +++ b/lib/libthr/arch/riscv/include/pthread_md.h @@ -56,4 +56,11 @@ _get_curthread(void) return (NULL); } +static __inline void +_thr_resolve_machdep(void) +{ +} + +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/riscv/include/pthread_tls.h b/lib/libthr/arch/riscv/include/pthread_tls.h deleted file mode 100644 index 0af1ddd4cfaf..000000000000 --- a/lib/libthr/arch/riscv/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_RISCV_PTHREAD_TLS_H -#define _ARCH_RISCV_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/libthr.3 b/lib/libthr/libthr.3 index 7d0c7669654a..b84176abcd32 100644 --- a/lib/libthr/libthr.3 +++ b/lib/libthr/libthr.3 @@ -1,5 +1,5 @@ .\" Copyright (c) 2005 Robert N. M. Watson -.\" Copyright (c) 2014,2015,2021 The FreeBSD Foundation, Inc. +.\" Copyright (c) 2014,2015,2021 The FreeBSD Foundation .\" All rights reserved. .\" .\" Part of this documentation was written by @@ -217,7 +217,7 @@ recycle it at any moment, making this sysctl less useful than it sounds. .It Dv kern.ipc.umtx_max_robust The maximal number of robust mutexes allowed for one thread. The kernel will not unlock more mutexes than specified, see -.Xr _umtx_op +.Xr _umtx_op 2 for more details. The default value is large enough for most useful applications. .It Dv debug.umtx.robust_faults_verbose @@ -325,15 +325,15 @@ anyway. .Sh SEE ALSO .Xr ktrace 1 , .Xr ld-elf.so.1 1 , -.Xr getrlimit 2 , +.Xr _umtx_op 2 , .Xr errno 2 , +.Xr getrlimit 2 , .Xr thr_exit 2 , .Xr thr_kill 2 , .Xr thr_kill2 2 , .Xr thr_new 2 , .Xr thr_self 2 , .Xr thr_set_name 2 , -.Xr _umtx_op 2 , .Xr dlclose 3 , .Xr dlopen 3 , .Xr getenv 3 , diff --git a/lib/libthr/plockstat.d b/lib/libthr/plockstat.d index de620d893651..39d8946f33d3 100644 --- a/lib/libthr/plockstat.d +++ b/lib/libthr/plockstat.d @@ -1,6 +1,5 @@ /* * Copyright (c) 2010 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Rui Paulo under sponsorship from the * FreeBSD Foundation. diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 348fd48df398..3a5353a32dc3 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -136,7 +136,6 @@ FBSDprivate_1.0 { __pthread_mutex_lock; __pthread_mutex_timedlock; __pthread_mutex_trylock; - __pthread_distribute_static_tls; _pthread_atfork; _pthread_barrier_destroy; _pthread_barrier_init; @@ -298,6 +297,9 @@ FBSDprivate_1.0 { /* ABI bug workaround, indicate that pli->rtli_version is valid */ _pli_rtli_version; + + /* Expose stub for libsys filter */ + _umtx_op_err; }; FBSD_1.1 { @@ -334,3 +336,9 @@ FBSD_1.6 { pthread_peekjoin_np; pthread_setname_np; }; + +FBSD_1.8 { + pthread_signals_block_np; + pthread_signals_unblock_np; + pthread_sigqueue; +}; diff --git a/lib/libthr/sys/Makefile.inc b/lib/libthr/sys/Makefile.inc index 7043b2e7c62d..98d7b2ac7bd3 100644 --- a/lib/libthr/sys/Makefile.inc +++ b/lib/libthr/sys/Makefile.inc @@ -1,4 +1,3 @@ - .PATH: ${.CURDIR}/sys SRCS+= thr_error.c diff --git a/lib/libthr/sys/thr_error.c b/lib/libthr/sys/thr_error.c index 7ce3a84fab6b..ec7a57bf6610 100644 --- a/lib/libthr/sys/thr_error.c +++ b/lib/libthr/sys/thr_error.c @@ -39,8 +39,7 @@ #include "libc_private.h" #include "thr_private.h" -#undef errno -extern int errno; +extern int __libsys_errno; __weak_reference(__error_threaded, __error); int * @@ -53,5 +52,5 @@ __error_threaded(void) if (curthread != NULL && curthread != _thr_initial) return (&curthread->error); } - return (&errno); + return (&__libsys_errno); } diff --git a/lib/libthr/tests/Makefile b/lib/libthr/tests/Makefile index 8b7850b94265..017b740157dc 100644 --- a/lib/libthr/tests/Makefile +++ b/lib/libthr/tests/Makefile @@ -1,4 +1,3 @@ - PACKAGE= tests WARNS?= 3 @@ -34,7 +33,9 @@ NETBSD_ATF_TESTS_SH+= cancel_test NETBSD_ATF_TESTS_SH+= exit_test NETBSD_ATF_TESTS_SH+= resolv_test +ATF_TESTS_C+= atfork_test ATF_TESTS_C+= umtx_op_test +ATF_TESTS_C+= pthread_sigqueue_test LIBADD+= pthread LIBADD.fpu_test+= m diff --git a/lib/libthr/tests/atfork_test.c b/lib/libthr/tests/atfork_test.c new file mode 100644 index 000000000000..cb0fcb7e62db --- /dev/null +++ b/lib/libthr/tests/atfork_test.c @@ -0,0 +1,280 @@ +/*- + * + * Copyright (C) 2024 Kyle Evans <kevans@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + * + */ + +#include <sys/wait.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +#include <atf-c.h> + +#define EXIT_NOPREPARE 1 +#define EXIT_CALLEDPARENT 2 +#define EXIT_NOCHILD 3 +#define EXIT_BADORDER 4 + +static int child; +static int forked; +static int parent; + +/* + * We'll disable prefork unless we're specifically running the preinit test to + * be sure that we don't mess up any other tests' results. + */ +static bool prefork_enabled; + +static void +prefork(void) +{ + if (prefork_enabled) + forked++; +} + +static void +registrar(void) +{ + pthread_atfork(prefork, NULL, NULL); +} + +static __attribute__((section(".preinit_array"), used)) +void (*preinitfn)(void) = ®istrar; + +/* + * preinit_atfork() just enables the prepare handler that we registered in a + * .preinit_array entry and checks that forking actually invoked that callback. + * We don't bother testing all three callbacks here because the implementation + * doesn't really lend itself to the kind of error where we only have a partial + * set of callbacks registered. + */ +ATF_TC(preinit_atfork); +ATF_TC_HEAD(preinit_atfork, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks that atfork callbacks may be registered in .preinit_array functions"); +} +ATF_TC_BODY(preinit_atfork, tc) +{ + pid_t p; + + (void)signal(SIGCHLD, SIG_IGN); + prefork_enabled = true; + p = fork(); + + ATF_REQUIRE(p >= 0); + if (p == 0) + _exit(0); + + prefork_enabled = false; + + ATF_REQUIRE(forked != 0); +} + +static void +basic_prepare(void) +{ + ATF_REQUIRE(parent == 0); + forked++; +} + +static void +basic_parent(void) +{ + ATF_REQUIRE(forked != 0); + parent++; +} + +static void +basic_child(void) +{ + if (!forked) + _exit(EXIT_NOPREPARE); + if (parent != 0) + _exit(EXIT_CALLEDPARENT); + child++; +} + +/* + * In the basic test, we'll register just once and set some globals to confirm + * that the prepare/parent callbacks were executed as expected. The child will + * use its exit status to communicate to us if the callback was not executed + * properly since we cannot assert there. This is a subset of the + * multi-callback test, but separated out so that it's more obvious from running + * the atfork_test if pthread_atfork() is completely broken or just + * out-of-order. + */ +ATF_TC(basic_atfork); +ATF_TC_HEAD(basic_atfork, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks invocation of all three atfork callbacks"); +} +ATF_TC_BODY(basic_atfork, tc) +{ + pid_t p, wpid; + int status; + + pthread_atfork(basic_prepare, basic_parent, basic_child); + + p = fork(); + + ATF_REQUIRE(p >= 0); + if (p == 0) + _exit(child != 0 ? 0 : EXIT_NOCHILD); + + /* + * The child can't use any of our standard atf-c(3) macros, so we have + * to rely on the exit status to convey any shenanigans. + */ + while ((wpid = waitpid(p, &status, 0)) != p) { + ATF_REQUIRE_ERRNO(EINTR, wpid == -1); + if (wpid == -1) + continue; + } + + ATF_REQUIRE_MSG(WIFEXITED(status), + "child did not exit cleanly, status %x", status); + + status = WEXITSTATUS(status); + ATF_REQUIRE_MSG(status == 0, "atfork in child %s", + status == EXIT_NOPREPARE ? "did not see `prepare` execute" : + (status == EXIT_CALLEDPARENT ? "observed `parent` executing" : + (status == EXIT_NOCHILD ? "did not see `child` execute" : + "mystery"))); + + ATF_REQUIRE(forked != 0); + ATF_REQUIRE(parent != 0); + ATF_REQUIRE(child == 0); +} + +static void +multi_assert(bool cond, bool can_assert) +{ + if (can_assert) + ATF_REQUIRE((cond)); + else if (!(cond)) + _exit(EXIT_BADORDER); +} + +static void +multi_bump(int *var, int bit, bool can_assert) +{ + int mask, val; + + mask = (1 << (bit - 1)); + val = *var; + + /* + * Every bit below this one must be set, and none of the upper bits + * should be set. + */ + multi_assert((val & mask) == 0, can_assert); + if (bit == 1) + multi_assert(val == 0, can_assert); + else + multi_assert((val & ~mask) == (mask - 1), can_assert); + + *var |= mask; +} + +static void +multi_prepare1(void) +{ + /* + * The bits are flipped for prepare because it's supposed to be called + * in the reverse order of registration. + */ + multi_bump(&forked, 2, true); +} +static void +multi_prepare2(void) +{ + multi_bump(&forked, 1, true); +} + +static void +multi_parent1(void) +{ + multi_bump(&parent, 1, true); +} +static void +multi_parent2(void) +{ + multi_bump(&parent, 2, true); +} + +static void +multi_child1(void) +{ + multi_bump(&child, 1, false); +} +static void +multi_child2(void) +{ + multi_bump(&child, 2, false); +} + +/* + * The multi-atfork test works much like the basic one, but it registers + * multiple times and enforces an order. The child still does just as strict + * of tests as the parent and continues to communicate the results of those + * tests back via its exit status. + */ +ATF_TC(multi_atfork); +ATF_TC_HEAD(multi_atfork, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks that multiple callbacks are called in the documented order"); +} +ATF_TC_BODY(multi_atfork, tc) +{ + pid_t p, wpid; + int status; + + pthread_atfork(multi_prepare1, multi_parent1, multi_child1); + pthread_atfork(multi_prepare2, multi_parent2, multi_child2); + + p = fork(); + + ATF_REQUIRE(p >= 0); + if (p == 0) + _exit(child != 0 ? 0 : EXIT_NOCHILD); + + /* + * The child can't use any of our standard atf-c(3) macros, so we have + * to rely on the exit status to convey any shenanigans. + */ + while ((wpid = waitpid(p, &status, 0)) != p) { + ATF_REQUIRE_ERRNO(EINTR, wpid == -1); + if (wpid == -1) + continue; + } + + ATF_REQUIRE_MSG(WIFEXITED(status), + "child did not exit cleanly, status %x", status); + + status = WEXITSTATUS(status); + ATF_REQUIRE_MSG(status == 0, "atfork in child %s", + status == EXIT_BADORDER ? "called in wrong order" : + (status == EXIT_NOCHILD ? "did not see `child` execute" : + "mystery")); + + ATF_REQUIRE(forked != 0); + ATF_REQUIRE(parent != 0); + ATF_REQUIRE(child == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, preinit_atfork); + ATF_TP_ADD_TC(tp, basic_atfork); + ATF_TP_ADD_TC(tp, multi_atfork); + return (atf_no_error()); +} diff --git a/lib/libthr/tests/dlopen/Makefile b/lib/libthr/tests/dlopen/Makefile index acc565056f4a..3427f67025b2 100644 --- a/lib/libthr/tests/dlopen/Makefile +++ b/lib/libthr/tests/dlopen/Makefile @@ -1,4 +1,3 @@ - TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libpthread/dlopen WARNS?= 2 diff --git a/lib/libthr/tests/dlopen/dso/Makefile b/lib/libthr/tests/dlopen/dso/Makefile index c2052e82c0ed..74d8ada35ff1 100644 --- a/lib/libthr/tests/dlopen/dso/Makefile +++ b/lib/libthr/tests/dlopen/dso/Makefile @@ -1,7 +1,7 @@ - TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libpthread/dlopen/dso WARNS?= 3 +PACKAGE= tests SHLIB= h_pthread_dlopen SHLIB_MAJOR= 1 SHLIB_NAME= h_pthread_dlopen.so.${SHLIB_MAJOR} diff --git a/lib/libthr/tests/pthread_sigqueue_test.c b/lib/libthr/tests/pthread_sigqueue_test.c new file mode 100644 index 000000000000..053a8dac4039 --- /dev/null +++ b/lib/libthr/tests/pthread_sigqueue_test.c @@ -0,0 +1,120 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2024 The FreeBSD Foundation + * + * This software was developed by Konstantin Belousov <kib@FreeBSD.org> + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <unistd.h> + +#define NTHREADS 330 +static int value[NTHREADS]; +static pthread_t thr[NTHREADS]; +static pthread_barrier_t barrier; + +static void +handler(int signo __unused, siginfo_t *info, void *data __unused) +{ + pthread_t self; + int i; + + /* + * Formally this is thread-unsafe but we know context from + * where the signal is sent. + */ + self = pthread_self(); + for (i = 0; i < NTHREADS; i++) { + if (pthread_equal(self, thr[i])) { + value[i] = info->si_value.sival_int; + pthread_exit(NULL); + } + } +} + +static void * +threadfunc(void *arg __unused) +{ + pthread_barrier_wait(&barrier); + for (;;) + pause(); +} + +ATF_TC(pthread_sigqueue); +ATF_TC_HEAD(pthread_sigqueue, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks pthread_sigqueue(3) sigval delivery"); +} + +ATF_TC_BODY(pthread_sigqueue, tc) +{ + struct sigaction sa; + union sigval sv; + int error, i; + + error = pthread_barrier_init(&barrier, NULL, NTHREADS + 1); + ATF_REQUIRE_EQ(0, error); + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + + if (sigaction(SIGUSR1, &sa, NULL) != 0) + atf_tc_fail("sigaction failed"); + + memset(&sv, 0, sizeof(sv)); + + for (i = 0; i < NTHREADS; i++) { + error = pthread_create(&thr[i], NULL, threadfunc, NULL); + ATF_REQUIRE_EQ(0, error); + } + error = pthread_barrier_wait(&barrier); + ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD); + + for (i = 0; i < NTHREADS; i++) { + sv.sival_int = i + 1000; + error = pthread_sigqueue(thr[i], SIGUSR1, sv); + ATF_REQUIRE_EQ(0, error); + error = pthread_join(thr[i], NULL); + ATF_REQUIRE_EQ(0, error); + } + for (i = 0; i < NTHREADS; i++) + ATF_REQUIRE_EQ(i + 1000, value[i]); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, pthread_sigqueue); + return atf_no_error(); +} diff --git a/lib/libthr/tests/umtx_op_test.c b/lib/libthr/tests/umtx_op_test.c index 7bffc2d5bfbf..8f964f9a923b 100644 --- a/lib/libthr/tests/umtx_op_test.c +++ b/lib/libthr/tests/umtx_op_test.c @@ -25,7 +25,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/umtx.h> @@ -36,7 +35,7 @@ /* * This is an implementation detail of _umtx_op(2), pulled from * sys/kern/kern_umtx.c. The relevant bug observed that requests above the - * batch side would not function as intended, so it's important that this + * batch size would not function as intended, so it's important that this * reflects the BATCH_SIZE configured there. */ #define UMTX_OP_BATCH_SIZE 128 diff --git a/lib/libthr/thread/Makefile.inc b/lib/libthr/thread/Makefile.inc index 33b95e9dd76d..c7442284bd51 100644 --- a/lib/libthr/thread/Makefile.inc +++ b/lib/libthr/thread/Makefile.inc @@ -1,4 +1,3 @@ - # thr sources .PATH: ${.CURDIR}/thread @@ -47,6 +46,7 @@ SRCS+= \ thr_setprio.c \ thr_setschedparam.c \ thr_sig.c \ + thr_sigqueue.c \ thr_single_np.c \ thr_sleepq.c \ thr_spec.c \ diff --git a/lib/libthr/thread/thr_affinity.c b/lib/libthr/thread/thr_affinity.c index 89f654ebffc2..78c89e146a79 100644 --- a/lib/libthr/thread/thr_affinity.c +++ b/lib/libthr/thread/thr_affinity.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread_np.h> #include <sys/param.h> diff --git a/lib/libthr/thread/thr_attr.c b/lib/libthr/thread/thr_attr.c index 9740bed6ebd3..1d0bc8cb7b91 100644 --- a/lib/libthr/thread/thr_attr.c +++ b/lib/libthr/thread/thr_attr.c @@ -93,7 +93,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> @@ -113,26 +112,14 @@ __weak_reference(_thr_attr_destroy, pthread_attr_destroy); int _thr_attr_destroy(pthread_attr_t *attr) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL) - /* Invalid argument: */ - ret = EINVAL; - else { - if ((*attr)->cpuset != NULL) - free((*attr)->cpuset); - /* Free the memory allocated to the attribute object: */ - free(*attr); + return (EINVAL); - /* - * Leave the attribute pointer NULL now that the memory - * has been freed: - */ - *attr = NULL; - ret = 0; - } - return (ret); + free((*attr)->cpuset); + free(*attr); + *attr = NULL; + return (0); } __weak_reference(_thr_attr_get_np, pthread_attr_get_np); @@ -141,36 +128,53 @@ __weak_reference(_thr_attr_get_np, _pthread_attr_get_np); int _thr_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) { + struct pthread_attr *dst; struct pthread *curthread; - struct pthread_attr attr, *dst; - int ret; - size_t kern_size; + cpuset_t *cpuset; + size_t kern_size; + int error; if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) return (EINVAL); + kern_size = _get_kern_cpuset_size(); if (dst->cpuset == NULL) { - dst->cpuset = calloc(1, kern_size); - dst->cpusetsize = kern_size; - } + if ((cpuset = malloc(kern_size)) == NULL) + return (ENOMEM); + } else + cpuset = dst->cpuset; + curthread = _get_curthread(); - if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) - return (ret); - attr = pthread->attr; - if (pthread->flags & THR_FLAGS_DETACHED) - attr.flags |= PTHREAD_DETACHED; - ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), - dst->cpusetsize, dst->cpuset); - if (ret == -1) - ret = errno; - THR_THREAD_UNLOCK(curthread, pthread); - if (ret == 0) { - memcpy(&dst->pthread_attr_start_copy, - &attr.pthread_attr_start_copy, - offsetof(struct pthread_attr, pthread_attr_end_copy) - - offsetof(struct pthread_attr, pthread_attr_start_copy)); + /* Arg 0 is to include dead threads. */ + if ((error = _thr_find_thread(curthread, pthread, 0)) != 0) + goto free_and_exit; + + error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), + kern_size, cpuset); + if (error == -1) { + THR_THREAD_UNLOCK(curthread, pthread); + error = errno; + goto free_and_exit; } - return (ret); + + /* + * From this point on, we can't fail, so we can start modifying 'dst'. + */ + + *dst = pthread->attr; + if ((pthread->flags & THR_FLAGS_DETACHED) != 0) + dst->flags |= PTHREAD_DETACHED; + + THR_THREAD_UNLOCK(curthread, pthread); + + dst->cpuset = cpuset; + dst->cpusetsize = kern_size; + return (0); + +free_and_exit: + if (dst->cpuset == NULL) + free(cpuset); + return (error); } __weak_reference(_thr_attr_getdetachstate, pthread_attr_getdetachstate); @@ -179,22 +183,15 @@ __weak_reference(_thr_attr_getdetachstate, _pthread_attr_getdetachstate); int _thr_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || detachstate == NULL) - ret = EINVAL; - else { - /* Check if the detached flag is set: */ - if ((*attr)->flags & PTHREAD_DETACHED) - /* Return detached: */ - *detachstate = PTHREAD_CREATE_DETACHED; - else - /* Return joinable: */ - *detachstate = PTHREAD_CREATE_JOINABLE; - ret = 0; - } - return (ret); + return (EINVAL); + + if (((*attr)->flags & PTHREAD_DETACHED) != 0) + *detachstate = PTHREAD_CREATE_DETACHED; + else + *detachstate = PTHREAD_CREATE_JOINABLE; + return (0); } __weak_reference(_thr_attr_getguardsize, pthread_attr_getguardsize); @@ -204,17 +201,12 @@ int _thr_attr_getguardsize(const pthread_attr_t * __restrict attr, size_t * __restrict guardsize) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || guardsize == NULL) - ret = EINVAL; - else { - /* Return the guard size: */ - *guardsize = (*attr)->guardsize_attr; - ret = 0; - } - return (ret); + return (EINVAL); + + *guardsize = (*attr)->guardsize_attr; + return (0); } __weak_reference(_thr_attr_getinheritsched, pthread_attr_getinheritsched); @@ -224,14 +216,12 @@ int _thr_attr_getinheritsched(const pthread_attr_t * __restrict attr, int * __restrict sched_inherit) { - int ret = 0; - if ((attr == NULL) || (*attr == NULL)) - ret = EINVAL; - else - *sched_inherit = (*attr)->sched_inherit; + if (attr == NULL || *attr == NULL) + return (EINVAL); - return (ret); + *sched_inherit = (*attr)->sched_inherit; + return (0); } __weak_reference(_thr_attr_getschedparam, pthread_attr_getschedparam); @@ -241,14 +231,12 @@ int _thr_attr_getschedparam(const pthread_attr_t * __restrict attr, struct sched_param * __restrict param) { - int ret = 0; - if ((attr == NULL) || (*attr == NULL) || (param == NULL)) - ret = EINVAL; - else - param->sched_priority = (*attr)->prio; + if (attr == NULL || *attr == NULL || param == NULL) + return (EINVAL); - return (ret); + param->sched_priority = (*attr)->prio; + return (0); } __weak_reference(_thr_attr_getschedpolicy, pthread_attr_getschedpolicy); @@ -258,14 +246,12 @@ int _thr_attr_getschedpolicy(const pthread_attr_t * __restrict attr, int * __restrict policy) { - int ret = 0; - if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) - ret = EINVAL; - else - *policy = (*attr)->sched_policy; + if (attr == NULL || *attr == NULL || policy == NULL) + return (EINVAL); - return (ret); + *policy = (*attr)->sched_policy; + return (0); } __weak_reference(_thr_attr_getscope, pthread_attr_getscope); @@ -275,17 +261,13 @@ int _thr_attr_getscope(const pthread_attr_t * __restrict attr, int * __restrict contentionscope) { - int ret = 0; - - if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) - /* Return an invalid argument: */ - ret = EINVAL; - else - *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? - PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; + if (attr == NULL || *attr == NULL || contentionscope == NULL) + return (EINVAL); - return (ret); + *contentionscope = ((*attr)->flags & PTHREAD_SCOPE_SYSTEM) != 0 ? + PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; + return (0); } __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); @@ -294,19 +276,14 @@ int _pthread_attr_getstack(const pthread_attr_t * __restrict attr, void ** __restrict stackaddr, size_t * __restrict stacksize) { - int ret; - - /* Check for invalid arguments: */ - if (attr == NULL || *attr == NULL || stackaddr == NULL - || stacksize == NULL ) - ret = EINVAL; - else { - /* Return the stack address and size */ - *stackaddr = (*attr)->stackaddr_attr; - *stacksize = (*attr)->stacksize_attr; - ret = 0; - } - return (ret); + + if (attr == NULL || *attr == NULL || stackaddr == NULL || + stacksize == NULL) + return (EINVAL); + + *stackaddr = (*attr)->stackaddr_attr; + *stacksize = (*attr)->stacksize_attr; + return (0); } __weak_reference(_thr_attr_getstackaddr, pthread_attr_getstackaddr); @@ -315,17 +292,12 @@ __weak_reference(_thr_attr_getstackaddr, _pthread_attr_getstackaddr); int _thr_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL) - ret = EINVAL; - else { - /* Return the stack address: */ - *stackaddr = (*attr)->stackaddr_attr; - ret = 0; - } - return (ret); + return (EINVAL); + + *stackaddr = (*attr)->stackaddr_attr; + return (0); } __weak_reference(_thr_attr_getstacksize, pthread_attr_getstacksize); @@ -335,17 +307,12 @@ int _thr_attr_getstacksize(const pthread_attr_t * __restrict attr, size_t * __restrict stacksize) { - int ret; - - /* Check for invalid arguments: */ - if (attr == NULL || *attr == NULL || stacksize == NULL) - ret = EINVAL; - else { - /* Return the stack size: */ - *stacksize = (*attr)->stacksize_attr; - ret = 0; - } - return (ret); + + if (attr == NULL || *attr == NULL || stacksize == NULL) + return (EINVAL); + + *stacksize = (*attr)->stacksize_attr; + return (0); } __weak_reference(_thr_attr_init, pthread_attr_init); @@ -354,40 +321,30 @@ __weak_reference(_thr_attr_init, _pthread_attr_init); int _thr_attr_init(pthread_attr_t *attr) { - int ret; - pthread_attr_t pattr; + pthread_attr_t pattr; _thr_check_init(); - /* Allocate memory for the attribute object: */ - if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) - /* Insufficient memory: */ - ret = ENOMEM; - else { - /* Initialise the attribute object with the defaults: */ - memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); - - /* Return a pointer to the attribute object: */ - *attr = pattr; - ret = 0; - } - return (ret); + if ((pattr = malloc(sizeof(*pattr))) == NULL) + return (ENOMEM); + + memcpy(pattr, &_pthread_attr_default, sizeof(*pattr)); + *attr = pattr; + return (0); } -__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); +__weak_reference(_pthread_attr_setcreatesuspend_np, \ + pthread_attr_setcreatesuspend_np); int _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) { - int ret; - if (attr == NULL || *attr == NULL) { - ret = EINVAL; - } else { - (*attr)->suspend = THR_CREATE_SUSPENDED; - ret = 0; - } - return (ret); + if (attr == NULL || *attr == NULL) + return (EINVAL); + + (*attr)->suspend = THR_CREATE_SUSPENDED; + return (0); } __weak_reference(_thr_attr_setdetachstate, pthread_attr_setdetachstate); @@ -396,24 +353,17 @@ __weak_reference(_thr_attr_setdetachstate, _pthread_attr_setdetachstate); int _thr_attr_setdetachstate(pthread_attr_t *attr, int detachstate) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || (detachstate != PTHREAD_CREATE_DETACHED && detachstate != PTHREAD_CREATE_JOINABLE)) - ret = EINVAL; - else { - /* Check if detached state: */ - if (detachstate == PTHREAD_CREATE_DETACHED) - /* Set the detached flag: */ - (*attr)->flags |= PTHREAD_DETACHED; - else - /* Reset the detached flag: */ - (*attr)->flags &= ~PTHREAD_DETACHED; - ret = 0; - } - return (ret); + return (EINVAL); + + if (detachstate == PTHREAD_CREATE_DETACHED) + (*attr)->flags |= PTHREAD_DETACHED; + else + (*attr)->flags &= ~PTHREAD_DETACHED; + return (0); } __weak_reference(_thr_attr_setguardsize, pthread_attr_setguardsize); @@ -422,17 +372,12 @@ __weak_reference(_thr_attr_setguardsize, _pthread_attr_setguardsize); int _thr_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) { - int ret; - /* Check for invalid arguments. */ if (attr == NULL || *attr == NULL) - ret = EINVAL; - else { - /* Save the stack size. */ - (*attr)->guardsize_attr = guardsize; - ret = 0; - } - return (ret); + return (EINVAL); + + (*attr)->guardsize_attr = guardsize; + return (0); } __weak_reference(_thr_attr_setinheritsched, pthread_attr_setinheritsched); @@ -441,17 +386,14 @@ __weak_reference(_thr_attr_setinheritsched, _pthread_attr_setinheritsched); int _thr_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) { - int ret = 0; - if ((attr == NULL) || (*attr == NULL)) - ret = EINVAL; - else if (sched_inherit != PTHREAD_INHERIT_SCHED && - sched_inherit != PTHREAD_EXPLICIT_SCHED) - ret = ENOTSUP; - else - (*attr)->sched_inherit = sched_inherit; + if (attr == NULL || *attr == NULL || + (sched_inherit != PTHREAD_INHERIT_SCHED && + sched_inherit != PTHREAD_EXPLICIT_SCHED)) + return (EINVAL); - return (ret); + (*attr)->sched_inherit = sched_inherit; + return (0); } __weak_reference(_thr_attr_setschedparam, pthread_attr_setschedparam); @@ -463,18 +405,15 @@ _thr_attr_setschedparam(pthread_attr_t * __restrict attr, { int policy; - if ((attr == NULL) || (*attr == NULL)) + if (attr == NULL || *attr == NULL || param == NULL) return (EINVAL); - if (param == NULL) - return (ENOTSUP); - policy = (*attr)->sched_policy; if (policy == SCHED_FIFO || policy == SCHED_RR) { if (param->sched_priority < _thr_priorities[policy-1].pri_min || param->sched_priority > _thr_priorities[policy-1].pri_max) - return (ENOTSUP); + return (EINVAL); } else { /* * Ignore it for SCHED_OTHER now, patches for glib ports @@ -494,17 +433,14 @@ __weak_reference(_thr_attr_setschedpolicy, _pthread_attr_setschedpolicy); int _thr_attr_setschedpolicy(pthread_attr_t *attr, int policy) { - int ret = 0; - if ((attr == NULL) || (*attr == NULL)) - ret = EINVAL; - else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { - ret = ENOTSUP; - } else { - (*attr)->sched_policy = policy; - (*attr)->prio = _thr_priorities[policy-1].pri_default; - } - return (ret); + if (attr == NULL || *attr == NULL || + policy < SCHED_FIFO || policy > SCHED_RR) + return (EINVAL); + + (*attr)->sched_policy = policy; + (*attr)->prio = _thr_priorities[policy-1].pri_default; + return (0); } __weak_reference(_thr_attr_setscope, pthread_attr_setscope); @@ -513,41 +449,33 @@ __weak_reference(_thr_attr_setscope, _pthread_attr_setscope); int _thr_attr_setscope(pthread_attr_t *attr, int contentionscope) { - int ret = 0; - - if ((attr == NULL) || (*attr == NULL)) { - /* Return an invalid argument: */ - ret = EINVAL; - } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && - (contentionscope != PTHREAD_SCOPE_SYSTEM)) { - ret = EINVAL; - } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { - (*attr)->flags |= contentionscope; - } else { + + if (attr == NULL || *attr == NULL || + (contentionscope != PTHREAD_SCOPE_PROCESS && + contentionscope != PTHREAD_SCOPE_SYSTEM)) + return (EINVAL); + + if (contentionscope == PTHREAD_SCOPE_SYSTEM) + (*attr)->flags |= PTHREAD_SCOPE_SYSTEM; + else (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; - } - return (ret); + return (0); } __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); int _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, - size_t stacksize) + size_t stacksize) { - int ret; - - /* Check for invalid arguments: */ - if (attr == NULL || *attr == NULL || stackaddr == NULL - || stacksize < PTHREAD_STACK_MIN) - ret = EINVAL; - else { - /* Save the stack address and stack size */ - (*attr)->stackaddr_attr = stackaddr; - (*attr)->stacksize_attr = stacksize; - ret = 0; - } - return (ret); + + if (attr == NULL || *attr == NULL || stackaddr == NULL || + stacksize < PTHREAD_STACK_MIN) + return (EINVAL); + + (*attr)->stackaddr_attr = stackaddr; + (*attr)->stacksize_attr = stacksize; + return (0); } __weak_reference(_thr_attr_setstackaddr, pthread_attr_setstackaddr); @@ -556,17 +484,12 @@ __weak_reference(_thr_attr_setstackaddr, _pthread_attr_setstackaddr); int _thr_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL) - ret = EINVAL; - else { - /* Save the stack address: */ - (*attr)->stackaddr_attr = stackaddr; - ret = 0; - } - return(ret); + return (EINVAL); + + (*attr)->stackaddr_attr = stackaddr; + return (0); } __weak_reference(_thr_attr_setstacksize, pthread_attr_setstacksize); @@ -575,17 +498,12 @@ __weak_reference(_thr_attr_setstacksize, _pthread_attr_setstacksize); int _thr_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { - int ret; - /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) - ret = EINVAL; - else { - /* Save the stack size: */ - (*attr)->stacksize_attr = stacksize; - ret = 0; - } - return (ret); + return (EINVAL); + + (*attr)->stacksize_attr = stacksize; + return (0); } static size_t @@ -608,71 +526,70 @@ _get_kern_cpuset_size(void) } __weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np); + int _pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize, - const cpuset_t *cpusetp) + const cpuset_t *cpusetp) { pthread_attr_t attr; - int ret; + size_t kern_size; if (pattr == NULL || (attr = (*pattr)) == NULL) - ret = EINVAL; - else { - if (cpusetsize == 0 || cpusetp == NULL) { - if (attr->cpuset != NULL) { - free(attr->cpuset); - attr->cpuset = NULL; - attr->cpusetsize = 0; - } - return (0); - } - size_t kern_size = _get_kern_cpuset_size(); - /* Kernel rejects small set, we check it here too. */ - if (cpusetsize < kern_size) - return (ERANGE); - if (cpusetsize > kern_size) { - /* Kernel checks invalid bits, we check it here too. */ - size_t i; - for (i = kern_size; i < cpusetsize; ++i) { - if (((const char *)cpusetp)[i]) - return (EINVAL); - } - } - if (attr->cpuset == NULL) { - attr->cpuset = calloc(1, kern_size); - if (attr->cpuset == NULL) - return (errno); - attr->cpusetsize = kern_size; + return (EINVAL); + + if (cpusetsize == 0 || cpusetp == NULL) { + if (attr->cpuset != NULL) { + free(attr->cpuset); + attr->cpuset = NULL; + attr->cpusetsize = 0; } - memcpy(attr->cpuset, cpusetp, kern_size); - ret = 0; + return (0); + } + + kern_size = _get_kern_cpuset_size(); + /* Kernel rejects small set, we check it here too. */ + if (cpusetsize < kern_size) + return (ERANGE); + if (cpusetsize > kern_size) { + /* Kernel checks invalid bits, we check it here too. */ + size_t i; + + for (i = kern_size; i < cpusetsize; ++i) + if (((const char *)cpusetp)[i] != 0) + return (EINVAL); + } + if (attr->cpuset == NULL) { + attr->cpuset = malloc(kern_size); + if (attr->cpuset == NULL) + return (errno); + attr->cpusetsize = kern_size; } - return (ret); + memcpy(attr->cpuset, cpusetp, kern_size); + return (0); } __weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np); + int _pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize, - cpuset_t *cpusetp) + cpuset_t *cpusetp) { pthread_attr_t attr; - int ret = 0; if (pattr == NULL || (attr = (*pattr)) == NULL) - ret = EINVAL; - else { - /* Kernel rejects small set, we check it here too. */ - size_t kern_size = _get_kern_cpuset_size(); - if (cpusetsize < kern_size) - return (ERANGE); - if (attr->cpuset != NULL) - memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, - attr->cpusetsize)); - else - memset(cpusetp, -1, kern_size); - if (cpusetsize > kern_size) - memset(((char *)cpusetp) + kern_size, 0, - cpusetsize - kern_size); - } - return (ret); + return (EINVAL); + + /* Kernel rejects small set, we check it here too. */ + size_t kern_size = _get_kern_cpuset_size(); + if (cpusetsize < kern_size) + return (ERANGE); + if (attr->cpuset != NULL) + memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, + attr->cpusetsize)); + else + memset(cpusetp, -1, kern_size); + if (cpusetsize > kern_size) + memset(((char *)cpusetp) + kern_size, 0, + cpusetsize - kern_size); + return (0); } diff --git a/lib/libthr/thread/thr_autoinit.c b/lib/libthr/thread/thr_autoinit.c index f18f53517e06..b0b4e601eff7 100644 --- a/lib/libthr/thread/thr_autoinit.c +++ b/lib/libthr/thread/thr_autoinit.c @@ -33,7 +33,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <pthread.h> #include "thr_private.h" diff --git a/lib/libthr/thread/thr_barrier.c b/lib/libthr/thread/thr_barrier.c index 8f5936409c05..13dec864e2f6 100644 --- a/lib/libthr/thread/thr_barrier.c +++ b/lib/libthr/thread/thr_barrier.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <stdlib.h> diff --git a/lib/libthr/thread/thr_barrierattr.c b/lib/libthr/thread/thr_barrierattr.c index 7af7e40f9159..6e5de86973f2 100644 --- a/lib/libthr/thread/thr_barrierattr.c +++ b/lib/libthr/thread/thr_barrierattr.c @@ -28,7 +28,6 @@ * DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <stdlib.h> diff --git a/lib/libthr/thread/thr_cancel.c b/lib/libthr/thread/thr_cancel.c index 86632e41449b..4189a2640d14 100644 --- a/lib/libthr/thread/thr_cancel.c +++ b/lib/libthr/thread/thr_cancel.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include "un-namespace.h" @@ -84,25 +83,25 @@ int _thr_setcancelstate(int state, int *oldstate) { struct pthread *curthread = _get_curthread(); - int oldval; + int oldval, val; - oldval = curthread->cancel_enable; switch (state) { case PTHREAD_CANCEL_DISABLE: - curthread->cancel_enable = 0; + val = 0; break; case PTHREAD_CANCEL_ENABLE: - curthread->cancel_enable = 1; - if (curthread->cancel_async) - testcancel(curthread); + val = 1; break; default: return (EINVAL); } - if (oldstate) { + oldval = atomic_swap_int(&curthread->cancel_enable, val); + if (state == PTHREAD_CANCEL_ENABLE && curthread->cancel_async) + testcancel(curthread); + if (oldstate != NULL) { *oldstate = oldval ? PTHREAD_CANCEL_ENABLE : - PTHREAD_CANCEL_DISABLE; + PTHREAD_CANCEL_DISABLE; } return (0); } @@ -126,9 +125,9 @@ _thr_setcanceltype(int type, int *oldtype) return (EINVAL); } - if (oldtype) { + if (oldtype != NULL) { *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS : - PTHREAD_CANCEL_DEFERRED; + PTHREAD_CANCEL_DEFERRED; } return (0); } @@ -167,9 +166,8 @@ void _thr_cancel_leave(struct pthread *curthread, int maycancel) { curthread->cancel_point = 0; - if (__predict_false(SHOULD_CANCEL(curthread) && - !THR_IN_CRITICAL(curthread) && maycancel)) - _pthread_exit(PTHREAD_CANCELED); + if (maycancel) + testcancel(curthread); } void diff --git a/lib/libthr/thread/thr_clean.c b/lib/libthr/thread/thr_clean.c index ba699f0376d8..43fd570fd1df 100644 --- a/lib/libthr/thread/thr_clean.c +++ b/lib/libthr/thread/thr_clean.c @@ -30,7 +30,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <signal.h> #include <errno.h> diff --git a/lib/libthr/thread/thr_concurrency.c b/lib/libthr/thread/thr_concurrency.c index cc0d1075b92d..64c605f7d058 100644 --- a/lib/libthr/thread/thr_concurrency.c +++ b/lib/libthr/thread/thr_concurrency.c @@ -32,7 +32,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c index bec7933537b3..0eb3dac068ca 100644 --- a/lib/libthr/thread/thr_cond.c +++ b/lib/libthr/thread/thr_cond.c @@ -30,7 +30,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <stdlib.h> #include <errno.h> @@ -64,6 +63,7 @@ __weak_reference(__thr_cond_wait, pthread_cond_wait); __weak_reference(__thr_cond_wait, __pthread_cond_wait); __weak_reference(_thr_cond_wait, _pthread_cond_wait); __weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait); +__weak_reference(_thr_cond_timedwait, _pthread_cond_timedwait); __weak_reference(_thr_cond_init, pthread_cond_init); __weak_reference(_thr_cond_init, _pthread_cond_init); __weak_reference(_thr_cond_destroy, pthread_cond_destroy); diff --git a/lib/libthr/thread/thr_condattr.c b/lib/libthr/thread/thr_condattr.c index c5f675f0023d..dc56363fc084 100644 --- a/lib/libthr/thread/thr_condattr.c +++ b/lib/libthr/thread/thr_condattr.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <stdlib.h> #include <string.h> @@ -95,6 +94,7 @@ _pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) if (attr == NULL || *attr == NULL) return (EINVAL); if (clock_id != CLOCK_REALTIME && + clock_id != CLOCK_TAI && clock_id != CLOCK_VIRTUAL && clock_id != CLOCK_PROF && clock_id != CLOCK_MONOTONIC) { diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c index 4b9f45ac49de..e56dbcfe30e1 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -27,11 +27,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> +#define _WANT_P_OSREL #include "namespace.h" #include <sys/types.h> #include <sys/rtprio.h> #include <sys/signalvar.h> +#include <sys/exterrvar.h> #include <errno.h> #include <link.h> #include <stdlib.h> @@ -44,9 +45,13 @@ #include "libc_private.h" #include "thr_private.h" +int __getosreldate(void); + static int create_stack(struct pthread_attr *pattr); static void thread_start(struct pthread *curthread); +int __thr_new_flags = THR_C_RUNTIME; + __weak_reference(_pthread_create, pthread_create); int @@ -147,7 +152,7 @@ _pthread_create(pthread_t * __restrict thread, _thr_stack_fix_protection(new_thread); /* Return thread pointer eariler so that new thread can use it. */ - (*thread) = new_thread; + *thread = new_thread; if (SHOULD_REPORT_EVENT(curthread, TD_CREATE) || cpusetp != NULL) { THR_THREAD_LOCK(curthread, new_thread); locked = 1; @@ -161,7 +166,7 @@ _pthread_create(pthread_t * __restrict thread, param.tls_size = sizeof(struct tcb); param.child_tid = &new_thread->tid; param.parent_tid = &new_thread->tid; - param.flags = 0; + param.flags = __thr_new_flags; if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM) param.flags |= THR_SYSTEM_SCOPE; if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) @@ -227,8 +232,8 @@ _pthread_create(pthread_t * __restrict thread, THR_THREAD_UNLOCK(curthread, new_thread); } out: - if (ret) - (*thread) = 0; + if (ret != 0) + *thread = NULL; return (ret); } @@ -286,6 +291,10 @@ thread_start(struct pthread *curthread) curthread->attr.stacksize_attr; #endif + curthread->uexterr.ver = UEXTERROR_VER; + if (__getosreldate() >= P_OSREL_EXTERRCTL) + exterrctl(EXTERRCTL_ENABLE, 0, &curthread->uexterr); + /* Run the current thread's start routine with argument: */ _pthread_exit(curthread->start_routine(curthread->arg)); diff --git a/lib/libthr/thread/thr_ctrdtr.c b/lib/libthr/thread/thr_ctrdtr.c index ae8fa38d3cb0..6fa462a81d86 100644 --- a/lib/libthr/thread/thr_ctrdtr.c +++ b/lib/libthr/thread/thr_ctrdtr.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <rtld_tls.h> diff --git a/lib/libthr/thread/thr_detach.c b/lib/libthr/thread/thr_detach.c index 214d5e76262e..c7a60bb26129 100644 --- a/lib/libthr/thread/thr_detach.c +++ b/lib/libthr/thread/thr_detach.c @@ -27,7 +27,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/types.h> #include <errno.h> diff --git a/lib/libthr/thread/thr_equal.c b/lib/libthr/thread/thr_equal.c index 2a4cc9f6d049..e5b2ab881138 100644 --- a/lib/libthr/thread/thr_equal.c +++ b/lib/libthr/thread/thr_equal.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include "un-namespace.h" diff --git a/lib/libthr/thread/thr_event.c b/lib/libthr/thread/thr_event.c index afe0b307423c..f0b1805894fb 100644 --- a/lib/libthr/thread/thr_event.c +++ b/lib/libthr/thread/thr_event.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "thr_private.h" void diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c index 001b30f6671a..5a9dcf99fa21 100644 --- a/lib/libthr/thread/thr_exit.c +++ b/lib/libthr/thread/thr_exit.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #ifdef _PTHREAD_FORCED_UNWIND diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index fc7d77180e8b..aa54b0444cf4 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -57,7 +57,6 @@ * */ -#include <sys/cdefs.h> #include <sys/syscall.h> #include "namespace.h" #include <errno.h> @@ -85,20 +84,24 @@ _thr_atfork(void (*prepare)(void), void (*parent)(void), struct pthread *curthread; struct pthread_atfork *af; - _thr_check_init(); - if ((af = malloc(sizeof(struct pthread_atfork))) == NULL) return (ENOMEM); - curthread = _get_curthread(); af->prepare = prepare; af->parent = parent; af->child = child; - THR_CRITICAL_ENTER(curthread); - _thr_rwl_wrlock(&_thr_atfork_lock); - TAILQ_INSERT_TAIL(&_thr_atfork_list, af, qe); - _thr_rwl_unlock(&_thr_atfork_lock); - THR_CRITICAL_LEAVE(curthread); + + if (_thr_initial != NULL) { + curthread = _get_curthread(); + THR_CRITICAL_ENTER(curthread); + _thr_rwl_wrlock(&_thr_atfork_lock); + TAILQ_INSERT_TAIL(&_thr_atfork_list, af, qe); + _thr_rwl_unlock(&_thr_atfork_lock); + THR_CRITICAL_LEAVE(curthread); + } else { + TAILQ_INSERT_TAIL(&_thr_atfork_list, af, qe); + } + return (0); } diff --git a/lib/libthr/thread/thr_getcpuclockid.c b/lib/libthr/thread/thr_getcpuclockid.c index 0281fc626882..dee3a2a9447a 100644 --- a/lib/libthr/thread/thr_getcpuclockid.c +++ b/lib/libthr/thread/thr_getcpuclockid.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> diff --git a/lib/libthr/thread/thr_getprio.c b/lib/libthr/thread/thr_getprio.c index 5ab147af212c..d338287342ac 100644 --- a/lib/libthr/thread/thr_getprio.c +++ b/lib/libthr/thread/thr_getprio.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> diff --git a/lib/libthr/thread/thr_getschedparam.c b/lib/libthr/thread/thr_getschedparam.c index 557bcc834950..3abe9be6937b 100644 --- a/lib/libthr/thread/thr_getschedparam.c +++ b/lib/libthr/thread/thr_getschedparam.c @@ -32,7 +32,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/types.h> #include <sys/rtprio.h> diff --git a/lib/libthr/thread/thr_getthreadid_np.c b/lib/libthr/thread/thr_getthreadid_np.c index 1fe927435b02..ffecd0bc7ea9 100644 --- a/lib/libthr/thread/thr_getthreadid_np.c +++ b/lib/libthr/thread/thr_getthreadid_np.c @@ -25,7 +25,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include <pthread_np.h> @@ -37,7 +36,7 @@ __weak_reference(_thr_getthreadid_np, _pthread_getthreadid_np); __weak_reference(_thr_getthreadid_np, pthread_getthreadid_np); /* - * Provide the equivelant to AIX pthread_getthreadid_np() function. + * Provide the equivalent to AIX pthread_getthreadid_np() function. */ int _thr_getthreadid_np(void) diff --git a/lib/libthr/thread/thr_info.c b/lib/libthr/thread/thr_info.c index 41ab7f0bcf0c..f6bf81203f9c 100644 --- a/lib/libthr/thread/thr_info.c +++ b/lib/libthr/thread/thr_info.c @@ -33,7 +33,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/errno.h> #include <stdlib.h> diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c index b59678c3f6c3..0f9e3749d75f 100644 --- a/lib/libthr/thread/thr_init.c +++ b/lib/libthr/thread/thr_init.c @@ -33,7 +33,7 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> +#define _WANT_P_OSREL #include "namespace.h" #include <sys/param.h> #include <sys/auxv.h> @@ -60,6 +60,7 @@ #include "libc_private.h" #include "thr_private.h" +int __getosreldate(void); char *_usrstack; struct pthread *_thr_initial; int _libthr_debug; @@ -169,7 +170,6 @@ STATIC_LIB_REQUIRE(_sem_trywait); STATIC_LIB_REQUIRE(_sem_wait); STATIC_LIB_REQUIRE(_sigaction); STATIC_LIB_REQUIRE(_sigprocmask); -STATIC_LIB_REQUIRE(_sigsuspend); STATIC_LIB_REQUIRE(_sigtimedwait); STATIC_LIB_REQUIRE(_sigwait); STATIC_LIB_REQUIRE(_sigwaitinfo); @@ -272,6 +272,8 @@ static pthread_func_t jmp_table[][2] = { [PJT_GETTHREADID_NP] = {DUAL_ENTRY(_thr_getthreadid_np)}, [PJT_ATTR_GET_NP] = {DUAL_ENTRY(_thr_attr_get_np)}, [PJT_GETNAME_NP] = {DUAL_ENTRY(_thr_getname_np)}, + [PJT_SUSPEND_ALL_NP] = {DUAL_ENTRY(_thr_suspend_all_np)}, + [PJT_RESUME_ALL_NP] = {DUAL_ENTRY(_thr_resume_all_np)}, }; static int init_once = 0; @@ -333,6 +335,8 @@ _libpthread_init(struct pthread *curthread) /* Set the initial thread. */ if (curthread == NULL) { first = 1; + /* Force _get_curthread() return NULL until set. */ + _tcb_get()->tcb_thread = NULL; /* Create and initialize the initial thread. */ curthread = _thr_alloc(NULL); if (curthread == NULL) @@ -349,7 +353,7 @@ _libpthread_init(struct pthread *curthread) _thread_active_threads = 1; /* Setup the thread specific data */ - _tcb_set(curthread->tcb); + __thr_setup_tsd(curthread); if (first) { _thr_initial = curthread; @@ -430,6 +434,10 @@ init_main_thread(struct pthread *thread) thread->unwind_stackend = _usrstack; #endif + thread->uexterr.ver = UEXTERROR_VER; + if (__getosreldate() >= P_OSREL_EXTERRCTL) + exterrctl(EXTERRCTL_ENABLE, EXTERRCTLF_FORCE, &thread->uexterr); + /* Others cleared to zero by thr_alloc() */ } @@ -520,7 +528,6 @@ init_private(void) env = getenv("LIBPTHREAD_QUEUE_FIFO"); if (env) _thr_queuefifo = atoi(env); - TAILQ_INIT(&_thr_atfork_list); env = getenv("LIBPTHREAD_UMTX_MIN_TIMEOUT"); if (env) { char *endptr; diff --git a/lib/libthr/thread/thr_join.c b/lib/libthr/thread/thr_join.c index 4b48249489f6..53f28daa258d 100644 --- a/lib/libthr/thread/thr_join.c +++ b/lib/libthr/thread/thr_join.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> diff --git a/lib/libthr/thread/thr_kern.c b/lib/libthr/thread/thr_kern.c index 05522569fbfb..913b0d3ef44c 100644 --- a/lib/libthr/thread/thr_kern.c +++ b/lib/libthr/thread/thr_kern.c @@ -27,7 +27,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/signalvar.h> #include <sys/rtprio.h> diff --git a/lib/libthr/thread/thr_kill.c b/lib/libthr/thread/thr_kill.c index dd7beddd5c33..5fb40b3bc496 100644 --- a/lib/libthr/thread/thr_kill.c +++ b/lib/libthr/thread/thr_kill.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <signal.h> diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c index 72018d94f496..cbf16179f619 100644 --- a/lib/libthr/thread/thr_list.c +++ b/lib/libthr/thread/thr_list.c @@ -27,17 +27,17 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/queue.h> +#include <machine/tls.h> + #include <stdlib.h> #include <string.h> #include <pthread.h> #include "libc_private.h" #include "thr_private.h" -#include "static_tls.h" /*#define DEBUG_THREAD_LIST */ #ifdef DEBUG_THREAD_LIST @@ -150,16 +150,18 @@ _thr_alloc(struct pthread *curthread) if (thread == NULL) { if (total_threads > MAX_THREADS) return (NULL); - atomic_fetchadd_int(&total_threads, 1); - thread = calloc(1, sizeof(struct pthread)); + atomic_add_int(&total_threads, 1); + thread = __thr_aligned_alloc_offset(_Alignof(struct pthread), + sizeof(struct pthread), 0); if (thread == NULL) { - atomic_fetchadd_int(&total_threads, -1); + atomic_add_int(&total_threads, -1); return (NULL); } + memset(thread, 0, sizeof(*thread)); if ((thread->sleepqueue = _sleepq_alloc()) == NULL || (thread->wake_addr = _thr_alloc_wake_addr()) == NULL) { thr_destroy(curthread, thread); - atomic_fetchadd_int(&total_threads, -1); + atomic_add_int(&total_threads, -1); return (NULL); } } else { @@ -177,7 +179,7 @@ _thr_alloc(struct pthread *curthread) thread->tcb = tcb; } else { thr_destroy(curthread, thread); - atomic_fetchadd_int(&total_threads, -1); + atomic_add_int(&total_threads, -1); thread = NULL; } return (thread); @@ -203,7 +205,7 @@ _thr_free(struct pthread *curthread, struct pthread *thread) thread->tcb = NULL; if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) { thr_destroy(curthread, thread); - atomic_fetchadd_int(&total_threads, -1); + atomic_add_int(&total_threads, -1); } else { /* * Add the thread to the free thread list, this also avoids @@ -223,7 +225,7 @@ thr_destroy(struct pthread *curthread __unused, struct pthread *thread) _sleepq_free(thread->sleepqueue); if (thread->wake_addr != NULL) _thr_release_wake_addr(thread->wake_addr); - free(thread); + __thr_free(thread); } /* @@ -361,35 +363,3 @@ _thr_find_thread(struct pthread *curthread, struct pthread *thread, THREAD_LIST_UNLOCK(curthread); return (ret); } - -#include "pthread_tls.h" - -static void -thr_distribute_static_tls(uintptr_t tlsbase, void *src, size_t len, - size_t total_len) -{ - - memcpy((void *)tlsbase, src, len); - memset((char *)tlsbase + len, 0, total_len - len); -} - -void -__pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - struct pthread *curthread, *thrd; - uintptr_t tlsbase; - - if (!_thr_is_inited()) { - tlsbase = _libc_get_static_tls_base(offset); - thr_distribute_static_tls(tlsbase, src, len, total_len); - return; - } - curthread = _get_curthread(); - THREAD_LIST_RDLOCK(curthread); - TAILQ_FOREACH(thrd, &_thread_list, tle) { - tlsbase = _get_static_tls_base(thrd, offset); - thr_distribute_static_tls(tlsbase, src, len, total_len); - } - THREAD_LIST_UNLOCK(curthread); -} diff --git a/lib/libthr/thread/thr_main_np.c b/lib/libthr/thread/thr_main_np.c index 9dd8b1820acd..1d34dc21b84c 100644 --- a/lib/libthr/thread/thr_main_np.c +++ b/lib/libthr/thread/thr_main_np.c @@ -27,7 +27,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include <pthread_np.h> diff --git a/lib/libthr/thread/thr_malloc.c b/lib/libthr/thread/thr_malloc.c index d60fbc1b1fe8..48af9d1ea929 100644 --- a/lib/libthr/thread/thr_malloc.c +++ b/lib/libthr/thread/thr_malloc.c @@ -2,7 +2,6 @@ * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Konstantin Belousov <kib@FreeBSD.org> * under sponsorship from the FreeBSD Foundation. @@ -29,7 +28,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/mman.h> #include <rtld_malloc.h> @@ -122,6 +120,19 @@ __thr_malloc(size_t nbytes) } void * +__thr_aligned_alloc_offset(size_t align, size_t size, size_t offset) +{ + struct pthread *curthread; + void *res; + + curthread = _get_curthread(); + thr_malloc_lock(curthread); + res = __crt_aligned_alloc_offset(align, size, offset); + thr_malloc_unlock(curthread); + return (res); +} + +void * __thr_realloc(void *cp, size_t nbytes) { struct pthread *curthread; diff --git a/lib/libthr/thread/thr_multi_np.c b/lib/libthr/thread/thr_multi_np.c index cbd3f31fddf0..bac58ca85dca 100644 --- a/lib/libthr/thread/thr_multi_np.c +++ b/lib/libthr/thread/thr_multi_np.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include <pthread_np.h> diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c index 5dd624a269e4..32bdc4afe65f 100644 --- a/lib/libthr/thread/thr_mutex.c +++ b/lib/libthr/thread/thr_mutex.c @@ -38,7 +38,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <stdlib.h> #include <errno.h> @@ -620,6 +619,7 @@ __Tthr_mutex_trylock(pthread_mutex_t *mutex) uint32_t id; int ret, robust; + _thr_check_init(); ret = check_and_init_mutex(mutex, &m); if (ret != 0) return (ret); diff --git a/lib/libthr/thread/thr_mutexattr.c b/lib/libthr/thread/thr_mutexattr.c index 6d38f164df52..d78aad518ee8 100644 --- a/lib/libthr/thread/thr_mutexattr.c +++ b/lib/libthr/thread/thr_mutexattr.c @@ -59,7 +59,6 @@ * */ -#include <sys/cdefs.h> #include "namespace.h" #include <string.h> #include <stdlib.h> diff --git a/lib/libthr/thread/thr_once.c b/lib/libthr/thread/thr_once.c index 065781907771..89b76ee58c1e 100644 --- a/lib/libthr/thread/thr_once.c +++ b/lib/libthr/thread/thr_once.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include "un-namespace.h" diff --git a/lib/libthr/thread/thr_printf.c b/lib/libthr/thread/thr_printf.c index 5304cc00c5c8..e1edffe5acb2 100644 --- a/lib/libthr/thread/thr_printf.c +++ b/lib/libthr/thread/thr_printf.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <stdarg.h> #include <string.h> #include <unistd.h> diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 3475029f8996..d7b889930365 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -37,10 +37,10 @@ */ #include <sys/types.h> #include <sys/time.h> -#include <sys/cdefs.h> #include <sys/queue.h> #include <sys/param.h> #include <sys/cpuset.h> +#include <sys/exterrvar.h> #include <machine/atomic.h> #include <errno.h> #include <limits.h> @@ -261,7 +261,6 @@ struct pthread_atfork { }; struct pthread_attr { -#define pthread_attr_start_copy sched_policy int sched_policy; int sched_inherit; int prio; @@ -271,7 +270,6 @@ struct pthread_attr { void *stackaddr_attr; size_t stacksize_attr; size_t guardsize_attr; -#define pthread_attr_end_copy cpuset cpuset_t *cpuset; size_t cpusetsize; }; @@ -565,8 +563,12 @@ struct pthread { /* Deferred threads from pthread_cond_signal. */ unsigned int *defer_waiters[MAX_DEFER_WAITERS]; -#define _pthread_endzero wake_addr + /* rtld thread-local dlerror message and seen control */ + char dlerror_msg[512]; + int dlerror_seen; + +#define _pthread_endzero wake_addr struct wake_addr *wake_addr; #define WAKE_ADDR(td) ((td)->wake_addr) @@ -576,9 +578,7 @@ struct pthread { /* pthread_set/get_name_np */ char *name; - /* rtld thread-local dlerror message and seen control */ - char dlerror_msg[512]; - int dlerror_seen; + struct uexterror uexterr; }; #define THR_SHOULD_GC(thrd) \ @@ -779,6 +779,8 @@ extern struct pthread *_single_thread __hidden; extern bool _thr_after_fork __hidden; +extern int __thr_new_flags; + /* * Function prototype definitions. */ @@ -843,6 +845,8 @@ void _thr_signal_postfork(void) __hidden; void _thr_signal_postfork_child(void) __hidden; void _thr_suspend_all_lock(struct pthread *) __hidden; void _thr_suspend_all_unlock(struct pthread *) __hidden; +void _thr_suspend_all_np(void) __hidden; +void _thr_resume_all_np(void) __hidden; void _thr_try_gc(struct pthread *, struct pthread *) __hidden; int _rtp_to_schedparam(const struct rtprio *rtp, int *policy, struct sched_param *param) __hidden; @@ -867,8 +871,8 @@ int _pthread_mutexattr_setrobust(pthread_mutexattr_t * _Nonnull, int); /* #include <fcntl.h> */ #ifdef _SYS_FCNTL_H_ #ifndef _LIBC_PRIVATE_H_ -int __sys_fcntl(int, int, ...); -int __sys_openat(int, const char *, int, ...); +int __sys_fcntl(int, int, intptr_t); +int __sys_openat(int, const char *, int, int); #endif /* _LIBC_PRIVATE_H_ */ #endif /* _SYS_FCNTL_H_ */ @@ -982,8 +986,6 @@ void __pthread_cxa_finalize(struct dl_phdr_info *phdr_info); void _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_stack_fix_protection(struct pthread *thrd); -void __pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len); int *__error_threaded(void) __hidden; void __thr_interpose_libc(void) __hidden; @@ -1015,6 +1017,7 @@ void __thr_pshared_destroy(void *key) __hidden; void __thr_pshared_atfork_pre(void) __hidden; void __thr_pshared_atfork_post(void) __hidden; +void *__thr_aligned_alloc_offset(size_t align, size_t size, size_t offset); void *__thr_calloc(size_t num, size_t size); void __thr_free(void *cp); void *__thr_malloc(size_t nbytes); @@ -1105,6 +1108,8 @@ int __Tthr_mutex_lock(pthread_mutex_t *); int __Tthr_mutex_trylock(pthread_mutex_t *); bool __thr_get_main_stack_base(char **base); bool __thr_get_main_stack_lim(size_t *lim); +int _Tthr_sigqueue(pthread_t pthread, int sig, const union sigval value); +void _thr_resolve_machdep(void); __END_DECLS __NULLABILITY_PRAGMA_POP diff --git a/lib/libthr/thread/thr_pshared.c b/lib/libthr/thread/thr_pshared.c index 42b1430907ad..d20d66e21ea3 100644 --- a/lib/libthr/thread/thr_pshared.c +++ b/lib/libthr/thread/thr_pshared.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/queue.h> diff --git a/lib/libthr/thread/thr_pspinlock.c b/lib/libthr/thread/thr_pspinlock.c index 37f14d22909d..4820490ab6af 100644 --- a/lib/libthr/thread/thr_pspinlock.c +++ b/lib/libthr/thread/thr_pspinlock.c @@ -30,7 +30,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <stdlib.h> diff --git a/lib/libthr/thread/thr_resume_np.c b/lib/libthr/thread/thr_resume_np.c index 6dac28ab1f4b..c5669fd4f0ff 100644 --- a/lib/libthr/thread/thr_resume_np.c +++ b/lib/libthr/thread/thr_resume_np.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> @@ -39,7 +38,8 @@ #include "thr_private.h" __weak_reference(_pthread_resume_np, pthread_resume_np); -__weak_reference(_pthread_resume_all_np, pthread_resume_all_np); +__weak_reference(_thr_resume_all_np, pthread_resume_all_np); +__weak_reference(_thr_resume_all_np, _pthread_resume_all_np); static void resume_common(struct pthread *thread); @@ -60,7 +60,7 @@ _pthread_resume_np(pthread_t thread) } void -_pthread_resume_all_np(void) +_thr_resume_all_np(void) { struct pthread *curthread = _get_curthread(); struct pthread *thread; diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index 9026abf941e2..3cfdfc548cf2 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -26,11 +26,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> /* * A lockless rwlock for rtld. */ -#include <sys/cdefs.h> #include <sys/mman.h> #include <sys/syscall.h> #include <link.h> @@ -41,8 +39,7 @@ #include "rtld_lock.h" #include "thr_private.h" -#undef errno -extern int errno; +extern int __libsys_errno; static int _thr_rtld_clr_flag(int); static void *_thr_rtld_lock_create(void); @@ -53,8 +50,11 @@ static int _thr_rtld_set_flag(int); static void _thr_rtld_wlock_acquire(void *); struct rtld_lock { - struct urwlock lock; - char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock)]; + struct urwlock lock; + struct pthread *wowner; + u_int rlocks; + char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock) - + sizeof(struct pthread *) - sizeof(u_int)]; }; static struct rtld_lock lock_place[MAX_RTLD_LOCKS] __aligned(CACHE_LINE_SIZE); @@ -98,14 +98,14 @@ _thr_rtld_lock_destroy(void *lock) if (curthread != _thr_initial) \ errsave = curthread->error; \ else \ - errsave = errno; \ + errsave = __libsys_errno; \ } #define RESTORE_ERRNO() { \ if (curthread != _thr_initial) \ curthread->error = errsave; \ else \ - errno = errsave; \ + __libsys_errno = errsave; \ } static void @@ -119,9 +119,13 @@ _thr_rtld_rlock_acquire(void *lock) SAVE_ERRNO(); l = (struct rtld_lock *)lock; - THR_CRITICAL_ENTER(curthread); - while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) - ; + if (l->wowner == curthread) { + l->rlocks++; + } else { + THR_CRITICAL_ENTER(curthread); + while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) + ; + } curthread->rdlock_count++; RESTORE_ERRNO(); } @@ -140,6 +144,7 @@ _thr_rtld_wlock_acquire(void *lock) THR_CRITICAL_ENTER(curthread); while (_thr_rwlock_wrlock(&l->lock, NULL) != 0) ; + l->wowner = curthread; RESTORE_ERRNO(); } @@ -167,6 +172,14 @@ _thr_rtld_lock_release(void *lock) l->lock.rw_blocked_readers = 0; l->lock.rw_blocked_writers = 0; } + if ((state & URWLOCK_WRITE_OWNER) != 0) { + if (l->rlocks > 0) { + l->rlocks--; + return; + } else { + l->wowner = NULL; + } + } if (_thr_rwlock_unlock(&l->lock) == 0) { if ((state & URWLOCK_WRITE_OWNER) == 0) curthread->rdlock_count--; @@ -222,22 +235,23 @@ _thr_rtld_init(void) struct RtldLockInfo li; struct pthread *curthread; ucontext_t *uc; - long dummy = -1; int uc_len; + char dummy[2] = {}; curthread = _get_curthread(); /* force to resolve _umtx_op PLT */ - _umtx_op_err((struct umtx *)&dummy, UMTX_OP_WAKE, 1, 0, 0); + _umtx_op_err(&dummy, UMTX_OP_WAKE, 1, 0, 0); /* force to resolve errno() PLT */ __error(); /* force to resolve memcpy PLT */ - memcpy(&dummy, &dummy, sizeof(dummy)); + memcpy(&dummy[0], &dummy[1], 1); mprotect(NULL, 0, 0); _rtld_get_stack_prot(); + thr_wake(-1); li.rtli_version = RTLI_VERSION; li.lock_create = _thr_rtld_lock_create; @@ -277,6 +291,9 @@ _thr_rtld_init(void) _thr_signal_block_check_fast(); _thr_signal_block_setup(curthread); + /* resolve machine depended functions, if any */ + _thr_resolve_machdep(); + uc_len = __getcontextx_size(); uc = alloca(uc_len); getcontext(uc); diff --git a/lib/libthr/thread/thr_rwlock.c b/lib/libthr/thread/thr_rwlock.c index f8d5fa4f673f..084181ba922a 100644 --- a/lib/libthr/thread/thr_rwlock.c +++ b/lib/libthr/thread/thr_rwlock.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <errno.h> #include <limits.h> #include <stdlib.h> @@ -60,7 +59,7 @@ __weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); static int init_static(struct pthread *thread, pthread_rwlock_t *rwlock); static int init_rwlock(pthread_rwlock_t *rwlock, pthread_rwlock_t *rwlock_out); -static int __always_inline +static __always_inline int check_and_init_rwlock(pthread_rwlock_t *rwlock, pthread_rwlock_t *rwlock_out) { if (__predict_false(*rwlock == THR_PSHARED_PTR || diff --git a/lib/libthr/thread/thr_rwlockattr.c b/lib/libthr/thread/thr_rwlockattr.c index 068ad7d3acbf..34bbbb20e611 100644 --- a/lib/libthr/thread/thr_rwlockattr.c +++ b/lib/libthr/thread/thr_rwlockattr.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <stdlib.h> diff --git a/lib/libthr/thread/thr_self.c b/lib/libthr/thread/thr_self.c index f5b1ce8fdb98..cbdadb13ccc4 100644 --- a/lib/libthr/thread/thr_self.c +++ b/lib/libthr/thread/thr_self.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include "un-namespace.h" diff --git a/lib/libthr/thread/thr_sem.c b/lib/libthr/thread/thr_sem.c index c7b5ac009a8c..76180604c183 100644 --- a/lib/libthr/thread/thr_sem.c +++ b/lib/libthr/thread/thr_sem.c @@ -30,7 +30,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/types.h> #include <sys/queue.h> diff --git a/lib/libthr/thread/thr_setprio.c b/lib/libthr/thread/thr_setprio.c index 6ee60ffeb205..fddf664457bd 100644 --- a/lib/libthr/thread/thr_setprio.c +++ b/lib/libthr/thread/thr_setprio.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include "un-namespace.h" diff --git a/lib/libthr/thread/thr_setschedparam.c b/lib/libthr/thread/thr_setschedparam.c index e3e4174c753b..49ec2ae7a7fd 100644 --- a/lib/libthr/thread/thr_setschedparam.c +++ b/lib/libthr/thread/thr_setschedparam.c @@ -32,7 +32,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/param.h> #include <errno.h> diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c index e082f0601be1..4bff5497a804 100644 --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/param.h> #include <sys/auxv.h> @@ -38,6 +37,7 @@ #include <stdlib.h> #include <string.h> #include <pthread.h> +#include <pthread_np.h> #include "un-namespace.h" #include "libc_private.h" @@ -164,6 +164,24 @@ _thr_signal_block_setup(struct pthread *curthread) __sys_sigfastblock(SIGFASTBLOCK_SETPTR, &curthread->fsigblock); } +void +pthread_signals_block_np(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + _thr_signal_block(curthread); +} + +void +pthread_signals_unblock_np(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + _thr_signal_unblock(curthread); +} + int _thr_send_sig(struct pthread *thread, int sig) { @@ -186,8 +204,7 @@ thr_remove_thr_signals(const sigset_t *set, sigset_t *newset) } static void -sigcancel_handler(int sig __unused, - siginfo_t *info __unused, ucontext_t *ucp) +sigcancel_handler(int sig __unused, siginfo_t *info __unused, ucontext_t *ucp) { struct pthread *curthread = _get_curthread(); int err; @@ -248,7 +265,6 @@ static void handle_signal(struct sigaction *actp, int sig, siginfo_t *info, ucontext_t *ucp) { struct pthread *curthread = _get_curthread(); - ucontext_t uc2; __siginfohandler_t *sigfunc; int cancel_point; int cancel_async; @@ -308,13 +324,11 @@ handle_signal(struct sigaction *actp, int sig, siginfo_t *info, ucontext_t *ucp) curthread->cancel_point = cancel_point; curthread->cancel_enable = cancel_enable; - memcpy(&uc2, ucp, sizeof(uc2)); - SIGDELSET(uc2.uc_sigmask, SIGCANCEL); + SIGDELSET(ucp->uc_sigmask, SIGCANCEL); /* reschedule cancellation */ - check_cancel(curthread, &uc2); + check_cancel(curthread, ucp); errno = err; - syscall(SYS_sigreturn, &uc2); } void @@ -358,9 +372,11 @@ check_cancel(struct pthread *curthread, ucontext_t *ucp) * on getting a signal before it agrees to return. */ if (curthread->cancel_point) { - if (curthread->in_sigsuspend && ucp) { - SIGADDSET(ucp->uc_sigmask, SIGCANCEL); - curthread->unblock_sigcancel = 1; + if (curthread->in_sigsuspend) { + if (ucp != NULL) { + SIGADDSET(ucp->uc_sigmask, SIGCANCEL); + curthread->unblock_sigcancel = 1; + } _thr_send_sig(curthread, SIGCANCEL); } else thr_wake(curthread->tid); @@ -369,8 +385,8 @@ check_cancel(struct pthread *curthread, ucontext_t *ucp) * asynchronous cancellation mode, act upon * immediately. */ - _pthread_exit_mask(PTHREAD_CANCELED, - ucp? &ucp->uc_sigmask : NULL); + _pthread_exit_mask(PTHREAD_CANCELED, ucp != NULL ? + &ucp->uc_sigmask : NULL); } } @@ -401,6 +417,7 @@ check_deferred_signal(struct pthread *curthread) /* remove signal */ curthread->deferred_siginfo.si_signo = 0; handle_signal(&act, info.si_signo, &info, uc); + syscall(SYS_sigreturn, uc); } static void @@ -408,9 +425,8 @@ check_suspend(struct pthread *curthread) { uint32_t cycle; - if (__predict_true((curthread->flags & - (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) - != THR_FLAGS_NEED_SUSPEND)) + if (__predict_true((curthread->flags & (THR_FLAGS_NEED_SUSPEND | + THR_FLAGS_SUSPENDED)) != THR_FLAGS_NEED_SUSPEND)) return; if (curthread == _single_thread) return; @@ -667,15 +683,7 @@ _thr_sigmask(int how, const sigset_t *set, sigset_t *oset) } int -_sigsuspend(const sigset_t * set) -{ - sigset_t newset; - - return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset))); -} - -int -__thr_sigsuspend(const sigset_t * set) +__thr_sigsuspend(const sigset_t *set) { struct pthread *curthread; sigset_t newset; @@ -701,7 +709,7 @@ __thr_sigsuspend(const sigset_t * set) int _sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout) + const struct timespec *timeout) { sigset_t newset; @@ -716,7 +724,7 @@ _sigtimedwait(const sigset_t *set, siginfo_t *info, */ int __thr_sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout) + const struct timespec *timeout) { struct pthread *curthread = _get_curthread(); sigset_t newset; diff --git a/lib/libthr/thread/thr_sigqueue.c b/lib/libthr/thread/thr_sigqueue.c new file mode 100644 index 000000000000..6f7ad8c63bad --- /dev/null +++ b/lib/libthr/thread/thr_sigqueue.c @@ -0,0 +1,79 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Copyright 2024 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * <kib@FreeBSD.org> under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "namespace.h" +#include <errno.h> +#include <signal.h> +#include <pthread.h> +#include "un-namespace.h" + +#include "thr_private.h" + +__weak_reference(_Tthr_sigqueue, _pthread_sigqueue); +__weak_reference(_Tthr_sigqueue, pthread_sigqueue); + +int +_Tthr_sigqueue(pthread_t pthread, int sig, const union sigval value) +{ + struct pthread *curthread; + int e, ret; + + if (sig < 0 || sig > _SIG_MAXSIG) + return (EINVAL); + + curthread = _get_curthread(); + ret = 0; + + if (curthread == pthread) { + if (sig > 0) { + e = sigqueue(pthread->tid, sig | __SIGQUEUE_TID, + value); + if (e == -1) + ret = errno; + } + } else if ((ret = _thr_find_thread(curthread, pthread, + 0)) == 0) { + if (sig > 0) { + e = sigqueue(pthread->tid, sig | __SIGQUEUE_TID, + value); + if (e == -1) + ret = errno; + } + THR_THREAD_UNLOCK(curthread, pthread); + } + + return (ret); +} diff --git a/lib/libthr/thread/thr_single_np.c b/lib/libthr/thread/thr_single_np.c index e772fb5d3bb7..3aa7adba954d 100644 --- a/lib/libthr/thread/thr_single_np.c +++ b/lib/libthr/thread/thr_single_np.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include <pthread_np.h> diff --git a/lib/libthr/thread/thr_sleepq.c b/lib/libthr/thread/thr_sleepq.c index b3feef8c9381..9c680acd0ac0 100644 --- a/lib/libthr/thread/thr_sleepq.c +++ b/lib/libthr/thread/thr_sleepq.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <stdlib.h> #include "thr_private.h" @@ -63,7 +62,7 @@ _sleepq_alloc(void) { struct sleepqueue *sq; - sq = calloc(1, sizeof(struct sleepqueue)); + sq = __thr_calloc(1, sizeof(struct sleepqueue)); TAILQ_INIT(&sq->sq_blocked); SLIST_INIT(&sq->sq_freeq); return (sq); @@ -72,7 +71,7 @@ _sleepq_alloc(void) void _sleepq_free(struct sleepqueue *sq) { - free(sq); + __thr_free(sq); } void diff --git a/lib/libthr/thread/thr_spec.c b/lib/libthr/thread/thr_spec.c index ee58bb37f6f7..44a124785085 100644 --- a/lib/libthr/thread/thr_spec.c +++ b/lib/libthr/thread/thr_spec.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <sys/mman.h> #include <signal.h> diff --git a/lib/libthr/thread/thr_spinlock.c b/lib/libthr/thread/thr_spinlock.c index 13744569b94f..bf3401c92780 100644 --- a/lib/libthr/thread/thr_spinlock.c +++ b/lib/libthr/thread/thr_spinlock.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <pthread.h> #include <libc_private.h> diff --git a/lib/libthr/thread/thr_stack.c b/lib/libthr/thread/thr_stack.c index 5e888bbfe9b6..d249bb5606fd 100644 --- a/lib/libthr/thread/thr_stack.c +++ b/lib/libthr/thread/thr_stack.c @@ -27,7 +27,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/auxv.h> #include <sys/mman.h> @@ -127,10 +126,7 @@ static char *last_stack = NULL; static inline size_t round_up(size_t size) { - if (size % _thr_page_size != 0) - size = ((size / _thr_page_size) + 1) * - _thr_page_size; - return size; + return (roundup2(size, _thr_page_size)); } void diff --git a/lib/libthr/thread/thr_suspend_np.c b/lib/libthr/thread/thr_suspend_np.c index b594ea562480..cf4e9e8a96b1 100644 --- a/lib/libthr/thread/thr_suspend_np.c +++ b/lib/libthr/thread/thr_suspend_np.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> @@ -42,7 +41,8 @@ static int suspend_common(struct pthread *, struct pthread *, int); __weak_reference(_pthread_suspend_np, pthread_suspend_np); -__weak_reference(_pthread_suspend_all_np, pthread_suspend_all_np); +__weak_reference(_thr_suspend_all_np, pthread_suspend_all_np); +__weak_reference(_thr_suspend_all_np, _pthread_suspend_all_np); /* Suspend a thread: */ int @@ -102,7 +102,7 @@ _thr_suspend_all_unlock(struct pthread *curthread) } void -_pthread_suspend_all_np(void) +_thr_suspend_all_np(void) { struct pthread *curthread = _get_curthread(); struct pthread *thread; diff --git a/lib/libthr/thread/thr_switch_np.c b/lib/libthr/thread/thr_switch_np.c index cbf959f161e3..59a9a4c7e1a3 100644 --- a/lib/libthr/thread/thr_switch_np.c +++ b/lib/libthr/thread/thr_switch_np.c @@ -32,7 +32,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <errno.h> #include <pthread.h> @@ -41,10 +40,13 @@ #include "thr_private.h" - __weak_reference(_pthread_switch_add_np, pthread_switch_add_np); __weak_reference(_pthread_switch_delete_np, pthread_switch_delete_np); +typedef void (*pthread_switch_routine_t)(pthread_t, pthread_t); +int _pthread_switch_add_np(pthread_switch_routine_t routine); +int _pthread_switch_delete_np(pthread_switch_routine_t routine); + int _pthread_switch_add_np(pthread_switch_routine_t routine __unused) { diff --git a/lib/libthr/thread/thr_symbols.c b/lib/libthr/thread/thr_symbols.c index 7d5adcbbfb0b..f2de1f777558 100644 --- a/lib/libthr/thread/thr_symbols.c +++ b/lib/libthr/thread/thr_symbols.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <stddef.h> #include <pthread.h> diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index d68ca60e5993..188374a30070 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -65,11 +65,10 @@ * */ -#include <sys/cdefs.h> #include "namespace.h" -#include <sys/types.h> -#include <sys/mman.h> #include <sys/param.h> +#include <sys/exterrvar.h> +#include <sys/mman.h> #include <sys/select.h> #include <sys/signalvar.h> #include <sys/socket.h> @@ -189,22 +188,19 @@ __thr_connect(int fd, const struct sockaddr *name, socklen_t namelen) * if it is canceled. */ static int -__thr_fcntl(int fd, int cmd, ...) +__thr_fcntl(int fd, int cmd, __intptr_t arg) { struct pthread *curthread; int ret; - va_list ap; curthread = _get_curthread(); - va_start(ap, cmd); if (cmd == F_OSETLKW || cmd == F_SETLKW) { _thr_cancel_enter(curthread); - ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); + ret = __sys_fcntl(fd, cmd, arg); _thr_cancel_leave(curthread, ret == -1); } else { - ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); + ret = __sys_fcntl(fd, cmd, arg); } - va_end(ap); return (ret); } @@ -295,23 +291,11 @@ __thr_nanosleep(const struct timespec *time_to_sleep, * If the thread is canceled, file is not opened. */ static int -__thr_openat(int fd, const char *path, int flags, ...) +__thr_openat(int fd, const char *path, int flags, int mode) { struct pthread *curthread; - int mode, ret; - va_list ap; + int ret; - - /* Check if the file is being created: */ - if ((flags & O_CREAT) != 0) { - /* Get the creation mode: */ - va_start(ap, flags); - mode = va_arg(ap, int); - va_end(ap); - } else { - mode = 0; - } - curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_openat(fd, path, flags, mode); @@ -636,6 +620,15 @@ __thr_writev(int fd, const struct iovec *iov, int iovcnt) return (ret); } +static int +__thr_uexterr_gettext(char *buf, size_t bufsz) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + return (__uexterr_format(&curthread->uexterr, buf, bufsz)); +} + void __thr_interpose_libc(void) { @@ -644,6 +637,16 @@ __thr_interpose_libc(void) #define SLOT(name) \ *(__libc_interposing_slot(INTERPOS_##name)) = \ (interpos_func_t)__thr_##name; + SLOT(system); + SLOT(tcdrain); + SLOT(spinlock); + SLOT(spinunlock); + SLOT(map_stacks_exec); +#undef SLOT + +#define SLOT(name) \ + *(__libc_interposing_slot(INTERPOS_##name)) = \ + (interpos_func_t)__thr_##name; SLOT(accept); SLOT(accept4); SLOT(aio_suspend); @@ -672,20 +675,16 @@ __thr_interpose_libc(void) SLOT(sigtimedwait); SLOT(sigwaitinfo); SLOT(swapcontext); - SLOT(system); - SLOT(tcdrain); SLOT(wait4); SLOT(write); SLOT(writev); - SLOT(spinlock); - SLOT(spinunlock); SLOT(kevent); SLOT(wait6); SLOT(ppoll); - SLOT(map_stacks_exec); SLOT(fdatasync); SLOT(clock_nanosleep); SLOT(pdfork); + SLOT(uexterr_gettext); #undef SLOT *(__libc_interposing_slot( INTERPOS__pthread_mutex_init_calloc_cb)) = diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c index 37b378e74405..bbc68d0e30c6 100644 --- a/lib/libthr/thread/thr_umtx.c +++ b/lib/libthr/thread/thr_umtx.c @@ -26,20 +26,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "thr_private.h" #include "thr_umtx.h" -#ifndef HAS__UMTX_OP_ERR -int _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2) -{ - - if (_umtx_op(obj, op, val, uaddr, uaddr2) == -1) - return (errno); - return (0); -} -#endif - void _thr_umutex_init(struct umutex *mtx) { diff --git a/lib/libthr/thread/thr_umtx.h b/lib/libthr/thread/thr_umtx.h index a56997871ed1..89f70e4ab14f 100644 --- a/lib/libthr/thread/thr_umtx.h +++ b/lib/libthr/thread/thr_umtx.h @@ -39,7 +39,6 @@ #endif #define DEFAULT_URWLOCK {0,0,0,0,{0,0,0,0}} -int _umtx_op_err(void *, int op, u_long, void *, void *) __hidden; int __thr_umutex_lock(struct umutex *mtx, uint32_t id) __hidden; int __thr_umutex_lock_spin(struct umutex *mtx, uint32_t id) __hidden; int __thr_umutex_timedlock(struct umutex *mtx, uint32_t id, diff --git a/lib/libthr/thread/thr_yield.c b/lib/libthr/thread/thr_yield.c index b391e69cabc1..057fc789de02 100644 --- a/lib/libthr/thread/thr_yield.c +++ b/lib/libthr/thread/thr_yield.c @@ -29,7 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "namespace.h" #include <pthread.h> #include <sched.h> |