From patchwork Mon Apr 10 20:46:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 67590 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 89DEA38768B0 for ; Mon, 10 Apr 2023 20:48:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 89DEA38768B0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1681159703; bh=29PHTplQNOS5RrJ+3dP2DQybI8fVakMcif4d7thzSGo=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=UKVL1SVxeRl6nxBTzIJ2xuXp1yKzOQshI/1mC/n/9EVaXN4mTYF1qpA7+oYOJ16NN HZ/iK44kCNnZvQ7tkgDCMAXt0PHQvss5tc4r3YBsBh6zAnIbuU3eodrYIUGFAqOgdD E3lx9PuiOC27o1ukigS9+g8j9Fr9Kx2QXvCQKDuI= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-oi1-x229.google.com (mail-oi1-x229.google.com [IPv6:2607:f8b0:4864:20::229]) by sourceware.org (Postfix) with ESMTPS id 9FE5A3856DD6 for ; Mon, 10 Apr 2023 20:46:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9FE5A3856DD6 Received: by mail-oi1-x229.google.com with SMTP id r14so30341716oiw.12 for ; Mon, 10 Apr 2023 13:46:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681159601; x=1683751601; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=29PHTplQNOS5RrJ+3dP2DQybI8fVakMcif4d7thzSGo=; b=xccaIJTBZGfdY1JelotToMJT/0xLdRS988CJBLBbNM+UOMN0DKLWDnqeQSz+nd7ahn OaAUCzaclwsrPHv32tnVjVYYdzcsDanvLZUjs2qJLJwMhXD03JSCqJLCucKD0ilki/lQ h/xtOT1k+Jf+30F16QujCUyrgLKNxdNWA+J+KoKk7M3nL1MP+YBIATXPo/qbI7omsltM rF3LQEyQaWkRJ49bMIb1J3uB5iRvvLRcSMv0INYsKnnKTJyfZykYHQEHoHKojI0AH08k Zfl1bdRt03Zz5dR8aTrfDO9EUutS8Cc9iZLAxhTe/joipDI42GfsByZoHmeVhcXvr2k0 wo4g== X-Gm-Message-State: AAQBX9fJPEed9KkG78hN9AKZMFPIbp88REPm0oLJS7z4Y3nhjZ0Vvm/0 WrJWme+VPxjTuuf9G3Wje4cpjz0snUJcPVLCiI92gw== X-Google-Smtp-Source: AKy350Zc07Cl07Kwu+TQeOqIdfxyOQbtfPjgcEtBTJIvvin9H3gtDtG6Ts4Bxr+WWTWpvHl/GmkDsw== X-Received: by 2002:a05:6808:a8b:b0:389:5164:9db2 with SMTP id q11-20020a0568080a8b00b0038951649db2mr5369797oij.48.1681159599447; Mon, 10 Apr 2023 13:46:39 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c2:55a1:d59a:609a:284:6ed]) by smtp.gmail.com with ESMTPSA id p5-20020acabf05000000b003896f132821sm4865732oif.41.2023.04.10.13.46.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 13:46:38 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v5 20/22] mips: Fix Race conditions in pthread cancellation [BZ#12683] Date: Mon, 10 Apr 2023 17:46:12 -0300 Message-Id: <20230410204614.4129551-12-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230410204614.4129551-1-adhemerval.zanella@linaro.org> References: <20230410195907.4123869-1-adhemerval.zanella@linaro.org> <20230410204614.4129551-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" It adds the arch-specific cancellation syscall bridge and adjust the cancellable syscall bridge to accept 7 arguments (as required by mips o32). To avoid add a requirement on all architectures to support {INLINE,INTERNAL)_SYSCALL with 7 argument, mips support is added through a flag, HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS, which changes the signature and prototype of the requires macros and functions (SYSCALL_CANCEL, __syscall_cancel and __syscall_cancel_arch). Checked on mips-linux-gnu, mips64-linux-gnu, and mips64-n32-linux-gnu. --- nptl/cancellation.c | 11 +- sysdeps/nptl/pthreadP.h | 4 +- sysdeps/unix/sysdep.h | 69 +++++++--- .../sysv/linux/mips/mips32/syscall_cancel.S | 128 ++++++++++++++++++ sysdeps/unix/sysv/linux/mips/mips32/sysdep.h | 4 + .../linux/mips/mips64/n32/syscall_types.h | 28 ++++ .../sysv/linux/mips/mips64/syscall_cancel.S | 108 +++++++++++++++ sysdeps/unix/sysv/linux/mips/mips64/sysdep.h | 52 +++---- sysdeps/unix/sysv/linux/syscall_cancel.c | 6 +- 9 files changed, 354 insertions(+), 56 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n32/syscall_types.h create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/syscall_cancel.S diff --git a/nptl/cancellation.c b/nptl/cancellation.c index eee5b6b758..3162492b80 100644 --- a/nptl/cancellation.c +++ b/nptl/cancellation.c @@ -25,6 +25,7 @@ long int __internal_syscall_cancel (__syscall_arg_t a1, __syscall_arg_t a2, __syscall_arg_t a3, __syscall_arg_t a4, __syscall_arg_t a5, __syscall_arg_t a6, + __SYSCALL_CANCEL7_ARG_DEF __syscall_arg_t nr) { long int result; @@ -36,7 +37,8 @@ __internal_syscall_cancel (__syscall_arg_t a1, __syscall_arg_t a2, int ch = atomic_load_relaxed (&pd->cancelhandling); if (SINGLE_THREAD_P || !cancel_enabled (ch) || cancel_exiting (ch)) { - result = INTERNAL_SYSCALL_NCS_CALL (nr, a1, a2, a3, a4, a5, a6); + result = INTERNAL_SYSCALL_NCS_CALL (nr, a1, a2, a3, a4, a5, a6 + __SYSCALL_CANCEL7_ARCH_ARG7); if (INTERNAL_SYSCALL_ERROR_P (result)) return -INTERNAL_SYSCALL_ERRNO (result); return result; @@ -45,7 +47,7 @@ __internal_syscall_cancel (__syscall_arg_t a1, __syscall_arg_t a2, /* Call the arch-specific entry points that contains the globals markers to be checked by SIGCANCEL handler. */ result = __syscall_cancel_arch (&pd->cancelhandling, nr, a1, a2, a3, a4, a5, - a6); + a6 __SYSCALL_CANCEL7_ARCH_ARG7); /* If the cancellable syscall was interrupted by SIGCANCEL and it has not side-effect, cancel the thread if cancellation is enabled. */ @@ -63,9 +65,10 @@ long int __syscall_cancel (__syscall_arg_t a1, __syscall_arg_t a2, __syscall_arg_t a3, __syscall_arg_t a4, __syscall_arg_t a5, __syscall_arg_t a6, - __syscall_arg_t nr) + __SYSCALL_CANCEL7_ARG_DEF __syscall_arg_t nr) { - int r = __internal_syscall_cancel (a1, a2, a3, a4, a5, a6, nr); + int r = __internal_syscall_cancel (a1, a2, a3, a4, a5, a6, + __SYSCALL_CANCEL7_ARG nr); return __glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (r)) ? SYSCALL_ERROR_LABEL (INTERNAL_SYSCALL_ERRNO (r)) : r; diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h index 15a7a063e5..a9d351b9b8 100644 --- a/sysdeps/nptl/pthreadP.h +++ b/sysdeps/nptl/pthreadP.h @@ -276,8 +276,8 @@ __do_cancel (void *result) extern long int __syscall_cancel_arch (volatile int *, __syscall_arg_t nr, __syscall_arg_t arg1, __syscall_arg_t arg2, __syscall_arg_t arg3, - __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6) - attribute_hidden; + __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6 + __SYSCALL_CANCEL7_ARCH_ARG_DEF) attribute_hidden; extern _Noreturn void __syscall_do_cancel (void) attribute_hidden; diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h index 32bc85592e..1cb1f1d9b7 100644 --- a/sysdeps/unix/sysdep.h +++ b/sysdeps/unix/sysdep.h @@ -137,34 +137,59 @@ /* Cancellation macros. */ #include +/* Adjust both the __syscall_cancel and the SYSCALL_CANCEL macro to support + 7 arguments instead of default 6 (curently only mip32). It avoid add + the requirement to each architecture to support 7 argument macros + {INTERNAL,INLINE}_SYSCALL. */ +#ifdef HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS +# define __SYSCALL_CANCEL7_ARG_DEF __syscall_arg_t a7, +# define __SYSCALL_CANCEL7_ARCH_ARG_DEF ,__syscall_arg_t a7 +# define __SYSCALL_CANCEL7_ARG 0, +# define __SYSCALL_CANCEL7_ARG7 a7, +# define __SYSCALL_CANCEL7_ARCH_ARG7 , a7 +#else +# define __SYSCALL_CANCEL7_ARG_DEF +# define __SYSCALL_CANCEL7_ARCH_ARG_DEF +# define __SYSCALL_CANCEL7_ARG +# define __SYSCALL_CANCEL7_ARG7 +# define __SYSCALL_CANCEL7_ARCH_ARG7 +#endif long int __internal_syscall_cancel (__syscall_arg_t a1, __syscall_arg_t a2, __syscall_arg_t a3, __syscall_arg_t a4, __syscall_arg_t a5, __syscall_arg_t a6, + __SYSCALL_CANCEL7_ARG_DEF __syscall_arg_t nr) attribute_hidden; -long int __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t arg1, - __syscall_arg_t arg2, __syscall_arg_t arg3, - __syscall_arg_t arg4, __syscall_arg_t arg5, - __syscall_arg_t arg6) attribute_hidden; +long int __syscall_cancel (__syscall_arg_t arg1, __syscall_arg_t arg2, + __syscall_arg_t arg3, __syscall_arg_t arg4, + __syscall_arg_t arg5, __syscall_arg_t arg6, + __SYSCALL_CANCEL7_ARG_DEF + __syscall_arg_t nr) attribute_hidden; #define __SYSCALL_CANCEL0(name) \ - __syscall_cancel (0, 0, 0, 0, 0, 0, __NR_##name) + __syscall_cancel (0, 0, 0, 0, 0, 0, __SYSCALL_CANCEL7_ARG __NR_##name) #define __SYSCALL_CANCEL1(name, a1) \ - __syscall_cancel (__SSC (a1), 0, 0, 0, 0, 0, __NR_##name) + __syscall_cancel (__SSC (a1), 0, 0, 0, 0, 0, \ + __SYSCALL_CANCEL7_ARG __NR_##name) #define __SYSCALL_CANCEL2(name, a1, a2) \ - __syscall_cancel (__SSC (a1), __SSC (a2), 0, 0, 0, 0, __NR_##name) + __syscall_cancel (__SSC (a1), __SSC (a2), 0, 0, 0, 0, \ + __SYSCALL_CANCEL7_ARG __NR_##name) #define __SYSCALL_CANCEL3(name, a1, a2, a3) \ __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), 0, 0, 0, \ - __NR_##name) + __SYSCALL_CANCEL7_ARG __NR_##name) #define __SYSCALL_CANCEL4(name, a1, a2, a3, a4) \ __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), \ - __SSC(a4), 0, 0, __NR_##name) + __SSC(a4), 0, 0, __SYSCALL_CANCEL7_ARG __NR_##name) #define __SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \ __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), __SSC(a4), \ - __SSC (a5), 0, __NR_##name) + __SSC (a5), 0, __SYSCALL_CANCEL7_ARG __NR_##name) #define __SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \ __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), __SSC (a4), \ - __SSC (a5), __SSC (a6), __NR_##name) + __SSC (a5), __SSC (a6), __SYSCALL_CANCEL7_ARG \ + __NR_##name) +#define __SYSCALL_CANCEL7(name, a1, a2, a3, a4, a5, a6, a7) \ + __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), __SSC (a4), \ + __SSC (a5), __SSC (a6), __SSC (a7), __NR_##name) #define __SYSCALL_CANCEL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n #define __SYSCALL_CANCEL_NARGS(...) \ @@ -181,25 +206,33 @@ long int __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t arg1, __SYSCALL_CANCEL_DISP (__SYSCALL_CANCEL, __VA_ARGS__) #define __INTERNAL_SYSCALL_CANCEL0(name) \ - __internal_syscall_cancel (0, 0, 0, 0, 0, 0, __NR_##name) + __internal_syscall_cancel (0, 0, 0, 0, 0, 0, __SYSCALL_CANCEL7_ARG \ + __NR_##name) #define __INTERNAL_SYSCALL_CANCEL1(name, a1) \ - __internal_syscall_cancel (__SSC (a1), 0, 0, 0, 0, 0, __NR_##name) + __internal_syscall_cancel (__SSC (a1), 0, 0, 0, 0, 0, \ + __SYSCALL_CANCEL7_ARG __NR_##name) #define __INTERNAL_SYSCALL_CANCEL2(name, a1, a2) \ __internal_syscall_cancel (__SSC (a1), __SSC (a2), 0, 0, 0, 0, \ - __NR_##name) + __SYSCALL_CANCEL7_ARG __NR_##name) #define __INTERNAL_SYSCALL_CANCEL3(name, a1, a2, a3) \ __internal_syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), 0, \ - 0, 0, __NR_##name) + 0, 0, __SYSCALL_CANCEL7_ARG __NR_##name) #define __INTERNAL_SYSCALL_CANCEL4(name, a1, a2, a3, a4) \ __internal_syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), \ - __SSC(a4), 0, 0, __NR_##name) + __SSC(a4), 0, 0, \ + __SYSCALL_CANCEL7_ARG __NR_##name) #define __INTERNAL_SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \ __internal_syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), \ - __SSC(a4), __SSC (a5), 0, __NR_##name) + __SSC(a4), __SSC (a5), 0, \ + __SYSCALL_CANCEL7_ARG __NR_##name) #define __INTERNAL_SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \ __internal_syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), \ __SSC (a4), __SSC (a5), __SSC (a6), \ - __NR_##name) + __SYSCALL_CANCEL7_ARG __NR_##name) +#define __INTERNAL_SYSCALL_CANCEL7(name, a1, a2, a3, a4, a5, a6, a7) \ + __internal_syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), \ + __SSC (a4), __SSC (a5), __SSC (a6), \ + __SSC (a7), __NR_##name) /* Issue a cancellable syscall defined by syscall number NAME plus any other argument required. If an error occurs its value is returned as an negative diff --git a/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S b/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S new file mode 100644 index 0000000000..eb3b2ed005 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S @@ -0,0 +1,128 @@ +/* Cancellable syscall wrapper. Linux/mips32 version. + Copyright (C) 2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +/* long int __syscall_cancel_arch (int *cancelhandling, + __syscall_arg_t nr, + __syscall_arg_t arg1, + __syscall_arg_t arg2, + __syscall_arg_t arg3, + __syscall_arg_t arg4, + __syscall_arg_t arg5, + __syscall_arg_t arg6, + __syscall_arg_t arg7) */ + +#define FRAME_SIZE 56 + +NESTED (__syscall_cancel_arch, FRAME_SIZE, fp) + .mask 0xc0070000,-SZREG + .fmask 0x00000000,0 + + PTR_ADDIU sp, -FRAME_SIZE + cfi_def_cfa_offset (FRAME_SIZE) + + sw fp, 48(sp) + sw ra, 52(sp) + sw s2, 44(sp) + sw s1, 40(sp) + sw s0, 36(sp) +#ifdef __PIC__ + .cprestore 16 +#endif + cfi_offset (ra, -4) + cfi_offset (fp, -8) + cfi_offset (s2, -12) + cfi_offset (s1, -16) + cfi_offset (s0, -20) + + move fp ,sp + cfi_def_cfa_register (fp) + + .globl __syscall_cancel_arch_start +__syscall_cancel_arch_start: + + lw v0, 0(a0) + andi v0, v0, TCB_CANCELED_BITMASK + bne v0, zero, 2f + + addiu sp, sp, -16 + addiu v0, sp, 16 + sw v0, 24(fp) + + move s0, a1 + move a0, a2 + move a1, a3 + lw a2, 72(fp) + lw a3, 76(fp) + lw v0, 84(fp) + lw s1, 80(fp) + lw s2, 88(fp) + + .set noreorder + subu sp, 32 + sw s1, 16(sp) + sw v0, 20(sp) + sw s2, 24(sp) + move v0, s0 + syscall + + .globl __syscall_cancel_arch_end +__syscall_cancel_arch_end: + addiu sp, sp, 32 + .set reorder + + beq a3, zero, 1f + subu v0, zero, v0 +1: + move sp, fp + cfi_remember_state + cfi_def_cfa_register (sp) + lw ra, 52(fp) + lw fp, 48(sp) + lw s2, 44(sp) + lw s1, 40(sp) + lw s0, 36(sp) + + .set noreorder + .set nomacro + jr ra + addiu sp,sp,FRAME_SIZE + + .set macro + .set reorder + + cfi_def_cfa_offset (0) + cfi_restore (s0) + cfi_restore (s1) + cfi_restore (s2) + cfi_restore (fp) + cfi_restore (ra) + +2: + cfi_restore_state +#ifdef __PIC__ + PTR_LA t9, __syscall_do_cancel + jalr t9 +#else + jal __syscall_do_cancel +#endif + +END (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h index 1318083195..3ba5334d66 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h @@ -18,6 +18,10 @@ #ifndef _LINUX_MIPS_MIPS32_SYSDEP_H #define _LINUX_MIPS_MIPS32_SYSDEP_H 1 +/* mips32 have cancelable syscalls with 7 arguments (currently only + sync_file_range). */ +#define HAVE_CANCELABLE_SYSCALL_WITH_7_ARGS 1 + /* There is some commonality. */ #include #include diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/syscall_types.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/syscall_types.h new file mode 100644 index 0000000000..b3a8b0b634 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/syscall_types.h @@ -0,0 +1,28 @@ +/* Types and macros used for syscall issuing. MIPS64n32 version. + Copyright (C) 2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYSCALL_TYPES_H +#define _SYSCALL_TYPES_H + +typedef long long int __syscall_arg_t; + +/* Convert X to a long long, without losing any bits if it is one + already or warning if it is a 32-bit pointer. */ +#define __SSC(__x) ((__syscall_arg_t) (__typeof__ ((__x) - (__x))) (__x)) + +#endif diff --git a/sysdeps/unix/sysv/linux/mips/mips64/syscall_cancel.S b/sysdeps/unix/sysv/linux/mips/mips64/syscall_cancel.S new file mode 100644 index 0000000000..f172041324 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/mips64/syscall_cancel.S @@ -0,0 +1,108 @@ +/* Cancellable syscall wrapper. Linux/mips64 version. + Copyright (C) 2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +/* long int __syscall_cancel_arch (int *cancelhandling, + __syscall_arg_t nr, + __syscall_arg_t arg1, + __syscall_arg_t arg2, + __syscall_arg_t arg3, + __syscall_arg_t arg4, + __syscall_arg_t arg5, + __syscall_arg_t arg6, + __syscall_arg_t arg7) */ + +#define FRAME_SIZE 32 + + .text +NESTED (__syscall_cancel_arch, FRAME_SIZE, ra) + .mask 0x90010000, -SZREG + .fmask 0x00000000, 0 + LONG_ADDIU sp, sp, -FRAME_SIZE + cfi_def_cfa_offset (FRAME_SIZE) + sd gp, 16(sp) + cfi_offset (gp, -16) + lui gp, %hi(%neg(%gp_rel(__syscall_cancel_arch))) + LONG_ADDU gp, gp, t9 + sd ra, 24(sp) + sd s0, 8(sp) + cfi_offset (ra, -8) + cfi_offset (s0, -24) + LONG_ADDIU gp, gp, %lo(%neg(%gp_rel(__syscall_cancel_arch))) + + .global __syscall_cancel_arch_start +__syscall_cancel_arch_start: + + lw v0, 0(a0) + andi v0, v0, TCB_CANCELED_BITMASK + .set noreorder + .set nomacro + bne v0, zero, 2f + move s0, a1 + .set macro + .set reorder + + move a0, a2 + move a1, a3 + move a2, a4 + move a3, a5 + move a4, a6 + move a5, a7 + + .set noreorder + move v0, s0 + syscall + .set reorder + + .global __syscall_cancel_arch_end +__syscall_cancel_arch_end: + + .set noreorder + .set nomacro + bnel a3, zero, 1f + SUBU v0, zero, v0 + .set macro + .set reorder + +1: + ld ra, 24(sp) + ld gp, 16(sp) + ld s0, 8(sp) + + .set noreorder + .set nomacro + jr ra + LONG_ADDIU sp, sp, FRAME_SIZE + .set macro + .set reorder + + cfi_remember_state + cfi_def_cfa_offset (0) + cfi_restore (s0) + cfi_restore (gp) + cfi_restore (ra) + .align 3 +2: + cfi_restore_state + LONG_L t9, %got_disp(__syscall_do_cancel)(gp) + .reloc 3f, R_MIPS_JALR, __syscall_do_cancel +3: jalr t9 +END (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h index d7ae60f596..db27bd9e4d 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h @@ -44,15 +44,7 @@ #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 -#if _MIPS_SIM == _ABIN32 -/* Convert X to a long long, without losing any bits if it is one - already or warning if it is a 32-bit pointer. */ -# define ARGIFY(X) ((long long int) (__typeof__ ((X) - (X))) (X)) -typedef long long int __syscall_arg_t; -#else -# define ARGIFY(X) ((long int) (X)) -typedef long int __syscall_arg_t; -#endif +#include /* Note that the original Linux syscall restart convention required the instruction immediately preceding SYSCALL to initialize $v0 with the @@ -120,7 +112,7 @@ typedef long int __syscall_arg_t; long int _sys_result; \ \ { \ - __syscall_arg_t _arg1 = ARGIFY (arg1); \ + __syscall_arg_t _arg1 = __SSC (arg1); \ register __syscall_arg_t __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ register __syscall_arg_t __v0 asm ("$2"); \ @@ -144,8 +136,8 @@ typedef long int __syscall_arg_t; long int _sys_result; \ \ { \ - __syscall_arg_t _arg1 = ARGIFY (arg1); \ - __syscall_arg_t _arg2 = ARGIFY (arg2); \ + __syscall_arg_t _arg1 = __SSC (arg1); \ + __syscall_arg_t _arg2 = __SSC (arg2); \ register __syscall_arg_t __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ register __syscall_arg_t __v0 asm ("$2"); \ @@ -170,9 +162,9 @@ typedef long int __syscall_arg_t; long int _sys_result; \ \ { \ - __syscall_arg_t _arg1 = ARGIFY (arg1); \ - __syscall_arg_t _arg2 = ARGIFY (arg2); \ - __syscall_arg_t _arg3 = ARGIFY (arg3); \ + __syscall_arg_t _arg1 = __SSC (arg1); \ + __syscall_arg_t _arg2 = __SSC (arg2); \ + __syscall_arg_t _arg3 = __SSC (arg3); \ register __syscall_arg_t __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ register __syscall_arg_t __v0 asm ("$2"); \ @@ -199,10 +191,10 @@ typedef long int __syscall_arg_t; long int _sys_result; \ \ { \ - __syscall_arg_t _arg1 = ARGIFY (arg1); \ - __syscall_arg_t _arg2 = ARGIFY (arg2); \ - __syscall_arg_t _arg3 = ARGIFY (arg3); \ - __syscall_arg_t _arg4 = ARGIFY (arg4); \ + __syscall_arg_t _arg1 = __SSC (arg1); \ + __syscall_arg_t _arg2 = __SSC (arg2); \ + __syscall_arg_t _arg3 = __SSC (arg3); \ + __syscall_arg_t _arg4 = __SSC (arg4); \ register __syscall_arg_t __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ register __syscall_arg_t __v0 asm ("$2"); \ @@ -229,11 +221,11 @@ typedef long int __syscall_arg_t; long int _sys_result; \ \ { \ - __syscall_arg_t _arg1 = ARGIFY (arg1); \ - __syscall_arg_t _arg2 = ARGIFY (arg2); \ - __syscall_arg_t _arg3 = ARGIFY (arg3); \ - __syscall_arg_t _arg4 = ARGIFY (arg4); \ - __syscall_arg_t _arg5 = ARGIFY (arg5); \ + __syscall_arg_t _arg1 = __SSC (arg1); \ + __syscall_arg_t _arg2 = __SSC (arg2); \ + __syscall_arg_t _arg3 = __SSC (arg3); \ + __syscall_arg_t _arg4 = __SSC (arg4); \ + __syscall_arg_t _arg5 = __SSC (arg5); \ register __syscall_arg_t __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ register __syscall_arg_t __v0 asm ("$2"); \ @@ -261,12 +253,12 @@ typedef long int __syscall_arg_t; long int _sys_result; \ \ { \ - __syscall_arg_t _arg1 = ARGIFY (arg1); \ - __syscall_arg_t _arg2 = ARGIFY (arg2); \ - __syscall_arg_t _arg3 = ARGIFY (arg3); \ - __syscall_arg_t _arg4 = ARGIFY (arg4); \ - __syscall_arg_t _arg5 = ARGIFY (arg5); \ - __syscall_arg_t _arg6 = ARGIFY (arg6); \ + __syscall_arg_t _arg1 = __SSC (arg1); \ + __syscall_arg_t _arg2 = __SSC (arg2); \ + __syscall_arg_t _arg3 = __SSC (arg3); \ + __syscall_arg_t _arg4 = __SSC (arg4); \ + __syscall_arg_t _arg5 = __SSC (arg5); \ + __syscall_arg_t _arg6 = __SSC (arg6); \ register __syscall_arg_t __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ register __syscall_arg_t __v0 asm ("$2"); \ diff --git a/sysdeps/unix/sysv/linux/syscall_cancel.c b/sysdeps/unix/sysv/linux/syscall_cancel.c index 260680c99f..5fa0706486 100644 --- a/sysdeps/unix/sysv/linux/syscall_cancel.c +++ b/sysdeps/unix/sysv/linux/syscall_cancel.c @@ -52,7 +52,8 @@ long int __syscall_cancel_arch (volatile int *ch, __syscall_arg_t nr, __syscall_arg_t a1, __syscall_arg_t a2, __syscall_arg_t a3, __syscall_arg_t a4, - __syscall_arg_t a5, __syscall_arg_t a6) + __syscall_arg_t a5, __syscall_arg_t a6 + __SYSCALL_CANCEL7_ARG_DEF) { #define ADD_LABEL(__label) \ asm volatile ( \ @@ -63,7 +64,8 @@ __syscall_cancel_arch (volatile int *ch, __syscall_arg_t nr, if (__glibc_unlikely (*ch & CANCELED_BITMASK)) __syscall_do_cancel(); - long int result = INTERNAL_SYSCALL_NCS_CALL (nr, a1, a2, a3, a4, a5, a6); + long int result = INTERNAL_SYSCALL_NCS_CALL (nr, a1, a2, a3, a4, a5, a6 + __SYSCALL_CANCEL7_ARG7); ADD_LABEL ("__syscall_cancel_arch_end"); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result))) return -INTERNAL_SYSCALL_ERRNO (result);