diff mbox series

[v4,07/21] nptl: mips: Fix Race conditions in pthread cancellation [BZ#12683]

Message ID 20200403203201.7494-8-adhemerval.zanella@linaro.org
State New
Headers show
Series nptl: Fix Race conditions in pthread cancellation [BZ#12683] | expand

Commit Message

develop--- via Libc-alpha April 3, 2020, 8:31 p.m. UTC
This patch adds the mips modifications required for the BZ#12683.
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 code pessimization and add a requirement on all architectures
to support {INLINE,INTERNAL)_SYSCALL with 7 argument, its 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). As
default 6 arguments cancellable syscalls are use.

Checked on mips-linux-gnu, mips64-linux-gnu, and mips64-n32-linux-gnu.
---
 nptl/libc-cancellation.c                      |   7 +-
 nptl/pthreadP.h                               |   3 +-
 sysdeps/mips/nptl/tcb-offsets.sym             |   3 +
 sysdeps/unix/sysdep.h                         |  37 +++--
 .../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   | 130 ++++++++++++++++++
 sysdeps/unix/sysv/linux/mips/mips64/sysdep.h  |  52 +++----
 sysdeps/unix/sysv/linux/syscall_cancel.c      |   6 +-
 10 files changed, 354 insertions(+), 44 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 mbox series

Patch

diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index e695d67417..94cd40aac8 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -23,7 +23,7 @@  long int
 __syscall_cancel (__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 a6 __SYSCALL_CANCEL7_ARG_DEF)
 {
   struct pthread *pd = THREAD_SELF;
   long int result;
@@ -31,7 +31,8 @@  __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
   /* If cancellation is not enabled, call the syscall directly.  */
   if (pd->cancelstate == PTHREAD_CANCEL_DISABLE)
     {
-      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_ARG7);
       if (INTERNAL_SYSCALL_ERROR_P (result))
 	return -INTERNAL_SYSCALL_ERRNO (result);
       return result;
@@ -40,7 +41,7 @@  __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
   /* 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_ARG7);
 
   if (result == -EINTR
       && __pthread_self_cancelled ()
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index a20b136f14..3b5db3c14a 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -288,7 +288,8 @@  extern void __nptl_unwind_freeres (void) attribute_hidden;
 
 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);
+     __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6
+     __SYSCALL_CANCEL7_ARG_DEF);
 libc_hidden_proto (__syscall_cancel_arch);
 
 extern _Noreturn void __syscall_do_cancel (void)
diff --git a/sysdeps/mips/nptl/tcb-offsets.sym b/sysdeps/mips/nptl/tcb-offsets.sym
index 9ea25b94a8..fb14294594 100644
--- a/sysdeps/mips/nptl/tcb-offsets.sym
+++ b/sysdeps/mips/nptl/tcb-offsets.sym
@@ -8,3 +8,6 @@ 
 
 MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads)
 TID_OFFSET			thread_offsetof (tid)
+
+-- Not strictly offsets, used on syscall_cancel.S
+TCB_CANCELED_BITMASK		CANCELED_BITMASK
diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
index c19cffabee..bd18f6ad82 100644
--- a/sysdeps/unix/sysdep.h
+++ b/sysdeps/unix/sysdep.h
@@ -121,30 +121,51 @@ 
 /* Cancellation macros.  */
 #include <syscall_types.h>
 
+/* 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 arg7
+# define __SYSCALL_CANCEL7_ARG		, 0
+# define __SYSCALL_CANCEL7_ARG7		, arg7
+#else
+# define __SYSCALL_CANCEL7_ARG_DEF
+# define __SYSCALL_CANCEL7_ARG
+# define __SYSCALL_CANCEL7_ARG7
+#endif
+
 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);
+			   __syscall_arg_t arg6 __SYSCALL_CANCEL7_ARG_DEF);
 libc_hidden_proto (__syscall_cancel);
 
 #define __SYSCALL_CANCEL0(name) \
-  __syscall_cancel (__NR_##name, 0, 0, 0, 0, 0, 0)
+  __syscall_cancel (__NR_##name, 0, 0, 0, 0, 0, 0 \
+		      __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL1(name, a1) \
-  __syscall_cancel (__NR_##name, __SSC (a1), 0, 0, 0, 0, 0)
+  __syscall_cancel (__NR_##name, __SSC (a1), 0, 0, 0, 0, 0 \
+		    __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL2(name, a1, a2) \
-  __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), 0, 0, 0, 0)
+  __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), 0, 0, 0, 0 \
+		    __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL3(name, a1, a2, a3) \
   __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), __SSC (a3), \
-		     0, 0, 0)
+		    0, 0, 0 __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL4(name, a1, a2, a3, a4) \
   __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), __SSC (a3), \
-		     __SSC(a4), 0, 0)
+		    __SSC (a4), 0, 0 __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \
   __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), __SSC (a3), \
-		     __SSC(a4), __SSC (a5), 0)
+		    __SSC (a4), __SSC (a5), 0 __SYSCALL_CANCEL7_ARG)
 #define __SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \
   __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), __SSC (a3), \
-		     __SSC (a4), __SSC (a5), __SSC (a6))
+		    __SSC (a4), __SSC (a5), __SSC (a6) \
+		    __SYSCALL_CANCEL7_ARG)
+#define __SYSCALL_CANCEL7(name, a1, a2, a3, a4, a5, a6, a7) \
+  __syscall_cancel (__NR_##name, __SSC (a1), __SSC (a2), __SSC (a3), \
+		    __SSC (a4), __SSC (a5), __SSC (a6), __SSC (a7))
 
 #define __SYSCALL_CANCEL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
 #define __SYSCALL_CANCEL_NARGS(...) \
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..52ae003100
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips32/syscall_cancel.S
@@ -0,0 +1,128 @@ 
+/* Cancellable syscall wrapper.  Linux/mips32 version.
+   Copyright (C) 2020 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* 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)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
index c5bcd90c25..7a60cfeb87 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 <sysdeps/unix/sysv/linux/mips/sysdep.h>
 #include <sysdeps/unix/sysv/linux/sysdep.h>
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..63d2877893
--- /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) 2020 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
+   <https://www.gnu.org/licenses/>.  */
+
+#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..28bdf41d3d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/syscall_cancel.S
@@ -0,0 +1,130 @@ 
+/* Cancellable syscall wrapper.  Linux/mips64 version.
+   Copyright (C) 2020 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* 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)  */
+
+#if _MIPS_SIM == _ABIN32
+# define FRAME_SIZE 16
+# define MASK       0x80010000
+# define RA_OFF     8
+# define S0_OFF     0
+#else
+# define FRAME_SIZE 32
+# define MASK       0x90010000
+# define RA_OFF     24
+# define S0_OFF     8
+#endif
+#define ADDIU      LONG_ADDIU
+#define ADDU       LONG_ADDU
+#define SUBU       LONG_SUBU
+#define LOAD_L     LONG_L
+
+	.text
+NESTED (__syscall_cancel_arch, FRAME_SIZE, ra)
+	.mask	MASK, -SZREG
+	.fmask	0x00000000, 0
+	ADDIU	sp, sp, -FRAME_SIZE
+	cfi_def_cfa_offset (FRAME_SIZE)
+	sd	gp, 16(sp)
+	cfi_offset (gp, -16)
+#if _MIPS_SIM == _ABI64
+	lui	gp, %hi(%neg(%gp_rel(__syscall_cancel_arch)))
+	ADDU	gp, gp, t9
+	daddiu	gp, gp, %lo(%neg(%gp_rel(__syscall_cancel_arch)))
+#endif
+	sd	ra, RA_OFF(sp)
+	sd	s0, S0_OFF(sp)
+	cfi_offset (ra, -RA_OFF)
+	cfi_offset (s0, -S0_OFF)
+
+	.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:
+#if _MIPS_SIM == _ABI64
+	ld	gp, 16(sp)
+#endif
+	ld	ra, RA_OFF(sp)
+	ld	s0, S0_OFF(sp)
+
+	.set	noreorder
+	.set	nomacro
+	jr	ra
+	daddiu	sp, sp, FRAME_SIZE
+	.set	macro
+	.set	reorder
+
+	cfi_remember_state
+	cfi_def_cfa_offset (0)
+#if _MIPS_SIM == _ABI64
+	cfi_restore (gp)
+#endif
+	.align	3
+2:
+	cfi_restore_state
+#if _MIPS_SIM == _ABI64
+	ld	t9, %got_disp(__syscall_do_cancel)(gp)
+	.reloc	3f, R_MIPS_JALR, __syscall_do_cancel
+3:	jalr	t9
+#else
+	jal	__syscall_do_cancel
+#endif
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h
index 1882fe4e73..9a3dcd800a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/sysdep.h
@@ -41,15 +41,7 @@ 
 
 #else   /* ! __ASSEMBLER__ */
 
-#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 <syscall_types.h>
 
 /* Note that the original Linux syscall restart convention required the
    instruction immediately preceding SYSCALL to initialize $v0 with the
@@ -117,7 +109,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");			\
@@ -141,8 +133,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");			\
@@ -167,9 +159,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");			\
@@ -196,10 +188,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");			\
@@ -226,11 +218,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");			\
@@ -258,12 +250,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 003e485b5c..5385c9510e 100644
--- a/sysdeps/unix/sysv/linux/syscall_cancel.c
+++ b/sysdeps/unix/sysv/linux/syscall_cancel.c
@@ -42,7 +42,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 (			\
@@ -53,7 +54,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);