This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch hjl/i386 created. glibc-2.22-72-g2fce1e3


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, hjl/i386 has been created
        at  2fce1e372bcf5e4d3e8f4acad1c3c242611c24b6 (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2fce1e372bcf5e4d3e8f4acad1c3c242611c24b6

commit 2fce1e372bcf5e4d3e8f4acad1c3c242611c24b6
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Aug 13 15:06:59 2015 -0700

    Call __setcontext with HIDDEN_JUMPTARGET
    
    i386 __makecontext should call __setcontext with HIDDEN_JUMPTARGET.
    
    	[BZ #18822]
    	* sysdeps/unix/sysv/linux/i386/makecontext.S (__makecontext):
    	Don't load %ebx when calling __setcontext.  Call __setcontext
    	with HIDDEN_JUMPTARGET.
    	* sysdeps/unix/sysv/linux/i386/setcontext.S (__setcontext): Add
    	libc_hidden_def.

diff --git a/sysdeps/unix/sysv/linux/i386/makecontext.S b/sysdeps/unix/sysv/linux/i386/makecontext.S
index bcf8de6..fd1abf8 100644
--- a/sysdeps/unix/sysv/linux/i386/makecontext.S
+++ b/sysdeps/unix/sysv/linux/i386/makecontext.S
@@ -102,15 +102,10 @@ L(exitcode):
 	   parameters (see above).  */
 	leal	(%esp,%ebx,4), %esp
 
-#ifdef	PIC
-	call	1f
-1:	popl	%ebx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-#endif
 	cmpl	$0, (%esp)		/* Check the next context.  */
 	je	2f			/* If it is zero exit.  */
 
-	call	JUMPTARGET(__setcontext)
+	call	HIDDEN_JUMPTARGET(__setcontext)
 	/* If this returns (which can happen if the syscall fails) we'll
 	   exit the program with the return error value (-1).  */
 
diff --git a/sysdeps/unix/sysv/linux/i386/setcontext.S b/sysdeps/unix/sysv/linux/i386/setcontext.S
index 13609b0..75b4447 100644
--- a/sysdeps/unix/sysv/linux/i386/setcontext.S
+++ b/sysdeps/unix/sysv/linux/i386/setcontext.S
@@ -91,5 +91,6 @@ ENTRY(__setcontext)
 
 	ret
 PSEUDO_END(__setcontext)
+libc_hidden_def (__setcontext)
 
 weak_alias (__setcontext, setcontext)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=799caceddab76004cb5ada693b91f5fce5931f86

commit 799caceddab76004cb5ada693b91f5fce5931f86
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Aug 13 15:02:39 2015 -0700

    Mark __xstatXX_conv as hidden
    
    __xstat_conv, __xstat64_conv and __xstat32_conv are internal to glibc.
    They should be marked as hidden so that they can't be called without
    PLT.
    
    	[BZ #18822]
    	* sysdeps/unix/sysv/linux/xstatconv.h (__xstat_conv): Add
    	attribute_hidden.
    	(__xstat64_conv): Likewise.
    	(__xstat32_conv): Likewise.

diff --git a/sysdeps/unix/sysv/linux/xstatconv.h b/sysdeps/unix/sysv/linux/xstatconv.h
index 229e24c..d21d9a0 100644
--- a/sysdeps/unix/sysv/linux/xstatconv.h
+++ b/sysdeps/unix/sysv/linux/xstatconv.h
@@ -17,7 +17,10 @@
    <http://www.gnu.org/licenses/>.  */
 
 #ifndef STAT_IS_KERNEL_STAT
-extern int __xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf);
-extern int __xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf);
+extern int __xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
+  attribute_hidden;
+extern int __xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
+  attribute_hidden;
 #endif
-extern int __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf);
+extern int __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
+  attribute_hidden;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1ba1d2b0ec0f7b6aadd28afcff5b7136425e8a0f

commit 1ba1d2b0ec0f7b6aadd28afcff5b7136425e8a0f
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Aug 12 12:10:06 2015 -0700

    i386: Remove syscall assembly codes with 6 arguments
    
    This patch removes i386 assembly implementation for epoll_wait, mmap,
    mmap64, semtimeop now that i386 have 6 argument syscall support from
    C code and GCC 5 can inline syscalls with 6 argument.  We also compile
    epoll_pwait.c, mmap.c, mmap64.c and semtimedop.c with -fomit-frame-pointer
    since %ebp may be used to pass the 6th argument to syscall.
    
    Fo sysdeps/unix/sysv/linux/i386/mmap.c, with -O2 -march=i686
    -mtune=generic, GCC 5.2 now generates:
    
    <__mmap>:
       0:	sub    $0x10,%esp
       3:	mov    0x28(%esp),%eax
       7:	mov    %ebx,(%esp)
       a:	mov    0x18(%esp),%ecx
       e:	mov    %esi,0x4(%esp)
      12:	mov    0x14(%esp),%ebx
      16:	mov    %edi,0x8(%esp)
      1a:	mov    0x1c(%esp),%edx
      1e:	test   $0xfff,%eax
      23:	mov    0x20(%esp),%esi
      27:	mov    %ebp,0xc(%esp)
      2b:	mov    0x24(%esp),%edi
      2f:	jne    60 <__mmap+0x60>
      31:	sar    $0xc,%eax
      34:	mov    %eax,%ebp
      36:	mov    $0xc0,%eax
      3b:	call   *%gs:0x10
      42:	cmp    $0xfffff000,%eax
      47:	ja     65 <__mmap+0x65>
      49:	mov    (%esp),%ebx
      4c:	mov    0x4(%esp),%esi
      50:	mov    0x8(%esp),%edi
      54:	mov    0xc(%esp),%ebp
      58:	add    $0x10,%esp
      5b:	ret
      5c:	lea    0x0(%esi,%eiz,1),%esi
      60:	mov    $0xffffffea,%eax
      65:	mov    (%esp),%ebx
      68:	mov    0x4(%esp),%esi
      6c:	mov    0x8(%esp),%edi
      70:	mov    0xc(%esp),%ebp
      74:	add    $0x10,%esp
      77:	jmp    78 <__mmap+0x78>	78: R_386_PC32	__syscall_error
    
    vs sysdeps/unix/sysv/linux/i386/mmap.S:
    
    <__mmap>:
       0:	push   %ebp
       1:	push   %ebx
       2:	push   %esi
       3:	push   %edi
       4:	mov    0x14(%esp),%ebx
       8:	mov    0x18(%esp),%ecx
       c:	mov    0x1c(%esp),%edx
      10:	mov    0x20(%esp),%esi
      14:	mov    0x24(%esp),%edi
      18:	mov    0x28(%esp),%ebp
      1c:	test   $0xfff,%ebp
      22:	mov    $0xffffffea,%eax
      27:	jne    38 <__mmap+0x38>
      29:	shr    $0xc,%ebp
      2c:	mov    $0xc0,%eax
      31:	call   *%gs:0x10
      38:	pop    %edi
      39:	pop    %esi
      3a:	pop    %ebx
      3b:	pop    %ebp
      3c:	cmp    $0xfffff000,%eax
      41:	ja     44 <__mmap+0x44>
      43:	ret
      44:	call   45 <__mmap+0x45>	45: R_386_PC32	__x86.get_pc_thunk.cx
      49:	add    $0x2,%ecx	4b: R_386_GOTPC	_GLOBAL_OFFSET_TABLE_
      4f:	mov    0x0(%ecx),%ecx	51: R_386_TLS_GOTIE	__libc_errno
      55:	neg    %eax
      57:	mov    %eax,%gs:(%ecx)
      5a:	or     $0xffffffff,%eax
      5d:	ret
    
    The C version has:
    
       3:	mov    0x28(%esp),%eax
    ...
      1e:	test   $0xfff,%eax
    ...
      31:	sar    $0xc,%eax
      34:	mov    %eax,%ebp
    
    is due to missing $ebx register constraint for inline asm.  We have
    to use "r" constraint with
    
    register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6);
    
    and compiler chose %eax for offset (arg6) in
    
      if (offset & ((1 << MMAP_PAGE_SHIFT) - 1))
    
    	* sysdeps/unix/sysv/linux/i386/Makefile (CFLAGS-epoll_pwait.c):
    	Add -fomit-frame-pointer.
    	(CFLAGS-mmap.c): Likewise.
    	(CFLAGS-mmap64.c): Likewise.
    	(CFLAGS-semtimedop.c): Likewise.
    	* sysdeps/unix/sysv/linux/i386/mmap.c: New file.
    	* sysdeps/unix/sysv/linux/i386/epoll_pwait.S: Remove file.
    	* sysdeps/unix/sysv/linux/i386/mmap.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/mmap64.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/semtimedop.S: Likewise.

diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index e10d133..b484217 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -3,6 +3,15 @@ default-abi := 32
 
 ifeq ($(subdir),misc)
 sysdep_routines += ioperm iopl vm86
+# %ebp may be used to pass the 6th argument to syscall.
+CFLAGS-epoll_pwait.c += -fomit-frame-pointer
+CFLAGS-mmap.c += -fomit-frame-pointer
+CFLAGS-mmap64.c += -fomit-frame-pointer
+endif
+
+ifeq ($(subdir),sysvipc)
+# %ebp may be used to pass the 6th argument to syscall.
+CFLAGS-semtimedop.c += -fomit-frame-pointer
 endif
 
 ifeq ($(subdir),elf)
diff --git a/sysdeps/unix/sysv/linux/i386/epoll_pwait.S b/sysdeps/unix/sysv/linux/i386/epoll_pwait.S
deleted file mode 100644
index 65cfb98..0000000
--- a/sysdeps/unix/sysv/linux/i386/epoll_pwait.S
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (C) 2007-2015 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>
-#define _ERRNO_H
-#include <bits/errno.h>
-#define _SIGNAL_H
-#include <bits/signum.h>
-
-
-	.text
-ENTRY (epoll_pwait)
-
-#ifdef __NR_epoll_pwait
-
-	/* Save registers.  */
-	pushl %ebp
-	cfi_adjust_cfa_offset (4)
-	pushl %ebx
-	cfi_adjust_cfa_offset (4)
-	pushl %esi
-	cfi_adjust_cfa_offset (4)
-	pushl %edi
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (edi, 0)
-	cfi_rel_offset (esi, 4)
-	cfi_rel_offset (ebx, 8)
-	cfi_rel_offset (ebp, 12)
-
-	movl 20(%esp), %ebx
-	movl 24(%esp), %ecx
-	movl 28(%esp), %edx
-	movl 32(%esp), %esi
-	movl 36(%esp), %edi
-	movl $_NSIG/8, %ebp
-	movl $__NR_epoll_pwait, %eax
-
-	ENTER_KERNEL
-
-	/* Restore registers.  */
-	popl %edi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (edi)
-	popl %esi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (esi)
-	popl %ebx
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebx)
-	popl %ebp
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebp)
-
-	/* If 0 > %eax > -4096 there was an error.  */
-	cmpl $-4096, %eax
-	ja SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  */
-#else
-	movl $-ENOSYS, %eax
-	jmp SYSCALL_ERROR_LABEL
-#endif
-	ret
-PSEUDO_END (epoll_pwait)
diff --git a/sysdeps/unix/sysv/linux/i386/mmap.S b/sysdeps/unix/sysv/linux/i386/mmap.S
deleted file mode 100644
index daf807a..0000000
--- a/sysdeps/unix/sysv/linux/i386/mmap.S
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (C) 1995-2015 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>
-
-#define EINVAL	22
-
-	.text
-
-ENTRY (__mmap)
-
-	/* Save registers.  */
-	pushl %ebp
-	cfi_adjust_cfa_offset (4)
-	pushl %ebx
-	cfi_adjust_cfa_offset (4)
-	pushl %esi
-	cfi_adjust_cfa_offset (4)
-	pushl %edi
-	cfi_adjust_cfa_offset (4)
-
-	movl 20(%esp), %ebx
-	cfi_rel_offset (ebx, 8)
-	movl 24(%esp), %ecx
-	movl 28(%esp), %edx
-	movl 32(%esp), %esi
-	cfi_rel_offset (esi, 4)
-	movl 36(%esp), %edi
-	cfi_rel_offset (edi, 0)
-	movl 40(%esp), %ebp
-	cfi_rel_offset (ebp, 12)
-	testl $0xfff, %ebp
-	movl $-EINVAL, %eax
-	jne L(skip)
-	shrl $12, %ebp			/* mmap2 takes the offset in pages.  */
-
-	movl $SYS_ify(mmap2), %eax	/* System call number in %eax.  */
-
-	/* Do the system call trap.  */
-	ENTER_KERNEL
-L(skip):
-	/* Restore registers.  */
-	popl %edi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (edi)
-	popl %esi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (esi)
-	popl %ebx
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebx)
-	popl %ebp
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebp)
-
-	/* If 0 > %eax > -4096 there was an error.  */
-	cmpl $-4096, %eax
-	ja SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  */
-	ret
-
-PSEUDO_END (__mmap)
-
-weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/i386/mmap.c b/sysdeps/unix/sysv/linux/i386/mmap.c
new file mode 100644
index 0000000..e5e344c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/mmap.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2015 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 <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sysdep.h>
+
+#ifndef MMAP_PAGE_SHIFT
+#define MMAP_PAGE_SHIFT 12
+#endif
+
+__ptr_t
+__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+  if (offset & ((1 << MMAP_PAGE_SHIFT) - 1))
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, __ptr_t, );
+
+  return INLINE_SYSCALL_RETURN (mmap2, 6, __ptr_t, addr, len, prot,
+				flags, fd, offset >> MMAP_PAGE_SHIFT);
+}
+
+weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/i386/mmap64.S b/sysdeps/unix/sysv/linux/i386/mmap64.S
deleted file mode 100644
index 3cf6eb9..0000000
--- a/sysdeps/unix/sysv/linux/i386/mmap64.S
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 1995-2015 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>
-
-#define EINVAL	22
-#define ENOSYS	38
-
-#define SVRSP	16		/* saved register space */
-#define PARMS	4+SVRSP	/* space for 4 saved regs */
-#define ADDR	PARMS
-#define LEN	ADDR+4
-#define PROT	LEN+4
-#define FLAGS	PROT+4
-#define FD	FLAGS+4
-#define OFFLO	FD+4
-#define OFFHI	OFFLO+4
-
-	.text
-ENTRY (__mmap64)
-
-	/* Save registers.  */
-	pushl %ebp
-	cfi_adjust_cfa_offset (4)
-	pushl %ebx
-	cfi_adjust_cfa_offset (4)
-	pushl %esi
-	cfi_adjust_cfa_offset (4)
-	pushl %edi
-	cfi_adjust_cfa_offset (4)
-
-	movl OFFLO(%esp), %edx
-	movl OFFHI(%esp), %ecx
-	testl $0xfff, %edx
-	jne L(einval)
-	shrdl $12, %ecx, %edx		/* mmap2 takes the offset in pages.  */
-	shrl $12, %ecx
-	jne L(einval)
-	movl %edx, %ebp
-	cfi_rel_offset (ebp, 12)
-
-	movl ADDR(%esp), %ebx
-	cfi_rel_offset (ebx, 8)
-	movl LEN(%esp), %ecx
-	movl PROT(%esp), %edx
-	movl FLAGS(%esp), %esi
-	cfi_rel_offset (esi, 4)
-	movl FD(%esp), %edi
-	cfi_rel_offset (edi, 0)
-
-	movl $SYS_ify(mmap2), %eax	/* System call number in %eax.  */
-
-	/* Do the system call trap.  */
-L(do_syscall):
-	ENTER_KERNEL
-
-	/* Restore registers.  */
-	popl %edi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (edi)
-	popl %esi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (esi)
-	popl %ebx
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebx)
-	popl %ebp
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebp)
-
-	/* If 0 > %eax > -4096 there was an error.  */
-	cmpl $-4096, %eax
-	ja SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  */
-	ret
-
-	cfi_adjust_cfa_offset (16)
-	cfi_rel_offset (ebp, 12)
-	cfi_rel_offset (ebx, 8)
-	cfi_rel_offset (esi, 4)
-	cfi_rel_offset (edi, 0)
-	/* This means the offset value is too large.  */
-L(einval):
-	popl %edi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (edi)
-	popl %esi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (esi)
-	popl %ebx
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebx)
-	popl %ebp
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebp)
-	movl $-EINVAL, %eax
-	jmp SYSCALL_ERROR_LABEL
-
-PSEUDO_END (__mmap64)
-
-weak_alias (__mmap64, mmap64)
diff --git a/sysdeps/unix/sysv/linux/i386/semtimedop.S b/sysdeps/unix/sysv/linux/i386/semtimedop.S
deleted file mode 100644
index 80477b7..0000000
--- a/sysdeps/unix/sysv/linux/i386/semtimedop.S
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   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>
-
-#define SYSOP_semtimedop 4
-
-#define SVRSP	12		/* saved register space */
-#define PARMS	4+SVRSP	/* space for 3 saved regs */
-#define SEMID	PARMS
-#define SOPS	SEMID+4
-#define NSOPS	SOPS+4
-#define TIMEOUT	NSOPS+4
-
-	.text
-ENTRY (semtimedop)
-
-	pushl	%ebp
-	cfi_adjust_cfa_offset (4)
-	pushl	%ebx
-	cfi_adjust_cfa_offset (4)
-	pushl	%edi
-	cfi_adjust_cfa_offset (4)
-
-	movl	$SYSOP_semtimedop, %ebx
-	cfi_rel_offset (ebx, 4)
-	movl	SEMID(%esp), %ecx
-	movl	NSOPS(%esp), %edx
-	movl	SOPS(%esp), %edi
-	cfi_rel_offset (edi, 0)
-	movl	TIMEOUT(%esp), %ebp
-	cfi_rel_offset (ebp, 8)
-	movl	$__NR_ipc, %eax
-
-	ENTER_KERNEL
-
-	/* Restore registers.  */
-	popl	%edi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (edi)
-	popl	%ebx
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebx)
-	popl	%ebp
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (ebp)
-
-	/* If 0 > %eax > -4096 there was an error.  */
-	cmpl $-4096, %eax
-	ja SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  */
-	ret
-
-#ifdef PIC
-	.align	4
-#endif
-PSEUDO_END (semtimedop)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c0e18dc1d34748f82e31febfbda8e360cc5eb696

commit c0e18dc1d34748f82e31febfbda8e360cc5eb696
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Aug 12 09:13:29 2015 -0700

    Optimize i386 syscall inlining
    
    Define INLINE_SYSCALL_RETURN and INLINE_SYSCALL_ERROR_RETURN so
    that i386 can optimize setting errno by branching to the internal
    __syscall_error without PLT.
    
    Since GCC 5 and above can properly spill %ebx when needed, we can inline
    syscalls with 6 arguments if GCC 5 or above is used to compile glibc.
    This patch rewrites INTERNAL_SYSCALL macros and skips __libc_do_syscall
    for GCC 5.
    
    For sysdeps/unix/sysv/linux/i386/brk.c, with -O2 -march=i686
    -mtune=generic, GCC 5.2 now generates:
    
    <__brk>:
       0:	push   %ebx
       1:	mov    $0x2d,%eax
       6:	mov    0x8(%esp),%ebx
       a:	call   b <__brk+0xb>	b: R_386_PC32	__x86.get_pc_thunk.dx
       f:	add    $0x2,%edx	11: R_386_GOTPC	_GLOBAL_OFFSET_TABLE_
      15:	call   *%gs:0x10
      1c:	mov    0x0(%edx),%edx	1e: R_386_GOT32	__curbrk
      22:	cmp    %eax,%ebx
      24:	mov    %eax,(%edx)
      26:	ja     30 <__brk+0x30>
      28:	xor    %eax,%eax
      2a:	pop    %ebx
      2b:	ret
    
    instead of
    
    <__brk>:
       0:	push   %ebx
       1:	mov    0x8(%esp),%ecx
       5:	call   6 <__brk+0x6>	6: R_386_PC32	__x86.get_pc_thunk.bx
       a:	add    $0x2,%ebx	c: R_386_GOTPC	_GLOBAL_OFFSET_TABLE_
      10:	xchg   %ecx,%ebx
      12:	mov    $0x2d,%eax
      17:	call   *%gs:0x10
      1e:	xchg   %ecx,%ebx
      20:	mov    %eax,%edx
      22:	mov    0x0(%ebx),%eax	24: R_386_GOT32	__curbrk
      28:	mov    %edx,(%eax)
      2a:	xor    %eax,%eax
      2c:	cmp    %edx,%ecx
      2e:	ja     38 <__brk+0x38>
      30:	pop    %ebx
      31:	ret
    
    The new one is shorter by 2 instructions.
    
    	* sysdeps/unix/sysv/linux/i386/Makefile [$(subdir) == csu]
    	(sysdep-dl-routines): Add sysdep.
    	[$(subdir) == nptl] (libpthread-routines): Likewise.
    	[$(subdir) == rt] (librt-routines): Likewise.
    	* sysdeps/unix/sysv/linux/i386/brk.c (__brk): Add
    	INTERNAL_SYSCALL_DECL.  Use INLINE_SYSCALL_ERROR_RETURN.
    	* sysdeps/unix/sysv/linux/i386/clone.S (__clone): Don't check
    	PIC when branching to SYSCALL_ERROR_LABEL.
    	* sysdeps/unix/sysv/linux/i386/fcntl.c (__fcntl_nocancel): Use
    	INLINE_SYSCALL_RETURN and INLINE_SYSCALL_ERROR_RETURN.
    	(__libc_fcntl): Likewise.
    	* sysdeps/unix/sysv/linux/i386/fxstat.c (__fxstat): Likewise.
    	* sysdeps/unix/sysv/linux/i386/fxstatat.c (__fxstatat):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/getmsg.c (getmsg): Likewise.
    	* sysdeps/unix/sysv/linux/i386/lockf64.c (lockf64): Likewise.
    	* sysdeps/unix/sysv/linux/i386/lxstat.c (__lxstat): Likewise.
    	* sysdeps/unix/sysv/linux/i386/msgctl.c (__old_msgctl):
    	Likewise.
    	(__new_msgctl): Likewise.
    	* sysdeps/unix/sysv/linux/i386/putmsg.c (putmsg): Likewise.
    	* sysdeps/unix/sysv/linux/i386/semctl.c (__old_semctl):
    	Likewise.
    	(__new_semctl): Likewise.
    	* sysdeps/unix/sysv/linux/i386/setegid.c (setegid): Likewise.
    	* sysdeps/unix/sysv/linux/i386/seteuid.c (seteuid): Likewise.
    	* sysdeps/unix/sysv/linux/i386/setgid.c (__setgid): Likewise.
    	* sysdeps/unix/sysv/linux/i386/setgroups.c (setgroups):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/setregid.c (__setregid):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/setresgid.c (__setresgid):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/setresuid.c (__setresuid):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/setreuid.c (__setreuid):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/setuid.c (__setuid): Likewise.
    	* sysdeps/unix/sysv/linux/i386/shmctl.c (__old_shmctl):
    	Likewise.
    	(__new_shmctl): Likewise.
    	* sysdeps/unix/sysv/linux/i386/sigaction.c (__libc_sigaction):
    	Likewise.
    	* sysdeps/unix/sysv/linux/i386/xstat.c (__xstat): Likewise.
    	* sysdeps/unix/sysv/linux/i386/libc-do-syscall.S
    	(__libc_do_syscall): Defined only if !__GNUC_PREREQ (5,0).
    	* sysdeps/unix/sysv/linux/i386/sysdep.S: Removed.
    	* sysdeps/unix/sysv/linux/i386/sysdep.c: New file.
    	* sysdeps/unix/sysv/linux/i386/sysdep.h: Define assembler macros
    	only if !__GNUC_PREREQ (5,0).
    	(SYSCALL_ERROR_LABEL): Changed to __syscall_error.
    	(SYSCALL_ERROR_HANDLER): Changed to empty.
    	(SYSCALL_ERROR_ERRNO): Removed.
    	(SYSCALL_ERROR_HANDLER_TLS_STORE): Likewise.
    	(__syscall_error): New prototype.
    	(INLINE_SYSCALL_RETURN): New.
    	(INLINE_SYSCALL_ERROR_RETURN): Likewise.
    	(LOADREGS_0): Likewise.
    	(ASMARGS_0): Likewise.
    	(LOADREGS_1): Likewise.
    	(ASMARGS_1): Likewise.
    	(LOADREGS_2): Likewise.
    	(ASMARGS_2): Likewise.
    	(LOADREGS_3): Likewise.
    	(ASMARGS_3): Likewise.
    	(LOADREGS_4): Likewise.
    	(ASMARGS_4): Likewise.
    	(LOADREGS_5): Likewise.
    	(ASMARGS_5): Likewise.
    	(LOADREGS_6): Likewise.
    	(ASMARGS_6): Likewise.
    	(INTERNAL_SYSCALL_MAIN_6): Optimize for GCC 5.
    	(INTERNAL_SYSCALL_MAIN_INLINE): Likewise.
    	(INTERNAL_SYSCALL_NCS): Likewise.

diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 80da593..e10d133 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -27,3 +27,17 @@ endif
 ifeq ($(subdir),stdlib)
 gen-as-const-headers += ucontext_i.sym
 endif
+
+ifeq ($(subdir),csu)
+sysdep-dl-routines += sysdep
+endif
+
+ifeq ($(subdir),nptl)
+# pull in __syscall_error routine
+libpthread-routines += sysdep
+endif
+
+ifeq ($(subdir),rt)
+# pull in __syscall_error routine
+librt-routines += sysdep
+endif
diff --git a/sysdeps/unix/sysv/linux/i386/brk.c b/sysdeps/unix/sysv/linux/i386/brk.c
index 5b9a0ce..41b23c4 100644
--- a/sysdeps/unix/sysv/linux/i386/brk.c
+++ b/sysdeps/unix/sysv/linux/i386/brk.c
@@ -31,19 +31,11 @@ weak_alias (__curbrk, ___brk_addr)
 int
 __brk (void *addr)
 {
-  void *newbrk;
-
   INTERNAL_SYSCALL_DECL (err);
-  newbrk = (void *) INTERNAL_SYSCALL (brk, err, 1, addr);
-
+  void *newbrk = (void *) INTERNAL_SYSCALL (brk, err, 1, addr);
   __curbrk = newbrk;
-
   if (newbrk < addr)
-    {
-      __set_errno (ENOMEM);
-      return -1;
-    }
-
+    return INLINE_SYSCALL_ERROR_RETURN (-ENOMEM, int, );
   return 0;
 }
 weak_alias (__brk, brk)
diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S
index 243dbfe..2aafb3a 100644
--- a/sysdeps/unix/sysv/linux/i386/clone.S
+++ b/sysdeps/unix/sysv/linux/i386/clone.S
@@ -47,19 +47,11 @@ ENTRY (__clone)
 	/* Sanity check arguments.  */
 	movl	$-EINVAL,%eax
 	movl	FUNC(%esp),%ecx		/* no NULL function pointers */
-#ifdef PIC
-	jecxz	SYSCALL_ERROR_LABEL
-#else
 	testl	%ecx,%ecx
 	jz	SYSCALL_ERROR_LABEL
-#endif
 	movl	STACK(%esp),%ecx	/* no NULL stack pointers */
-#ifdef PIC
-	jecxz	SYSCALL_ERROR_LABEL
-#else
 	testl	%ecx,%ecx
 	jz	SYSCALL_ERROR_LABEL
-#endif
 
 	/* Insert the argument onto the new stack.  Make sure the new
 	   thread is started with an alignment of (mod 16).  */
diff --git a/sysdeps/unix/sysv/linux/i386/fcntl.c b/sysdeps/unix/sysv/linux/i386/fcntl.c
index 56f4bd1..8c46122 100644
--- a/sysdeps/unix/sysv/linux/i386/fcntl.c
+++ b/sysdeps/unix/sysv/linux/i386/fcntl.c
@@ -34,7 +34,7 @@ __fcntl_nocancel (int fd, int cmd, ...)
   arg = va_arg (ap, void *);
   va_end (ap);
 
-  return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+  return INLINE_SYSCALL_RETURN (fcntl64, 3, int, fd, cmd, arg);
 }
 #endif /* NO_CANCELLATION */
 
@@ -50,7 +50,7 @@ __libc_fcntl (int fd, int cmd, ...)
   va_end (ap);
 
   if ((cmd != F_SETLKW) && (cmd != F_SETLKW64))
-    return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+    return INLINE_SYSCALL_RETURN (fcntl64, 3, int, fd, cmd, arg);
 
   return SYSCALL_CANCEL (fcntl64, fd, cmd, arg);
 }
diff --git a/sysdeps/unix/sysv/linux/i386/fxstat.c b/sysdeps/unix/sysv/linux/i386/fxstat.c
index 2f7a8fe..a93af22 100644
--- a/sysdeps/unix/sysv/linux/i386/fxstat.c
+++ b/sysdeps/unix/sysv/linux/i386/fxstat.c
@@ -37,15 +37,18 @@ __fxstat (int vers, int fd, struct stat *buf)
   int result;
 
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (fstat, 2, fd, (struct kernel_stat *) buf);
+    return INLINE_SYSCALL_RETURN (fstat, 2, int, fd,
+				  (struct kernel_stat *) buf);
 
   {
     struct stat64 buf64;
 
-    result = INLINE_SYSCALL (fstat64, 2, fd, &buf64);
-    if (result == 0)
-      result = __xstat32_conv (vers, &buf64, buf);
-    return result;
+    INTERNAL_SYSCALL_DECL (err);
+    result = INTERNAL_SYSCALL (fstat64, err, 2, fd, &buf64);
+    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, )))
+      return INLINE_SYSCALL_ERROR_RETURN (result, int, );
+    else
+      return __xstat32_conv (vers, &buf64, buf);
   }
 }
 
diff --git a/sysdeps/unix/sysv/linux/i386/fxstatat.c b/sysdeps/unix/sysv/linux/i386/fxstatat.c
index 6f3c251..d259121 100644
--- a/sysdeps/unix/sysv/linux/i386/fxstatat.c
+++ b/sysdeps/unix/sysv/linux/i386/fxstatat.c
@@ -42,13 +42,10 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
   struct stat64 st64;
 
   result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
-  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
-    return __xstat32_conv (vers, &st64, st);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, )))
+    return INLINE_SYSCALL_ERROR_RETURN (result, int, );
   else
-    {
-      __set_errno (INTERNAL_SYSCALL_ERRNO (result, err));
-      return -1;
-    }
+    return __xstat32_conv (vers, &st64, st);
 }
 libc_hidden_def (__fxstatat)
 #ifdef XSTAT_IS_XSTAT64
diff --git a/sysdeps/unix/sysv/linux/i386/getmsg.c b/sysdeps/unix/sysv/linux/i386/getmsg.c
index 255b867..63dd1c9 100644
--- a/sysdeps/unix/sysv/linux/i386/getmsg.c
+++ b/sysdeps/unix/sysv/linux/i386/getmsg.c
@@ -30,7 +30,8 @@ getmsg (fildes, ctlptr, dataptr, flagsp)
      struct strbuf *dataptr;
      int *flagsp;
 {
-  return INLINE_SYSCALL (getpmsg, 5, fildes, ctlptr, dataptr, NULL, flagsp);
+  return INLINE_SYSCALL_RETURN (getpmsg, 5, int, fildes, ctlptr,
+				dataptr, NULL, flagsp);
 }
 #else
 # include <streams/getmsg.c>
diff --git a/sysdeps/unix/sysv/linux/i386/libc-do-syscall.S b/sysdeps/unix/sysv/linux/i386/libc-do-syscall.S
index af5c6f0..cdef3d5 100644
--- a/sysdeps/unix/sysv/linux/i386/libc-do-syscall.S
+++ b/sysdeps/unix/sysv/linux/i386/libc-do-syscall.S
@@ -18,6 +18,8 @@
 
 #include <sysdep.h>
 
+#if !__GNUC_PREREQ (5,0)
+
 /* %eax, %ecx, %edx and %esi contain the values expected by the kernel.
    %edi points to a structure with the values of %ebx, %edi and %ebp.  */
 
@@ -48,3 +50,4 @@ ENTRY (__libc_do_syscall)
 	cfi_restore (ebx)
 	ret
 END (__libc_do_syscall)
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/lockf64.c b/sysdeps/unix/sysv/linux/i386/lockf64.c
index 61fcf22..f2cb938 100644
--- a/sysdeps/unix/sysv/linux/i386/lockf64.c
+++ b/sysdeps/unix/sysv/linux/i386/lockf64.c
@@ -29,6 +29,7 @@ lockf64 (int fd, int cmd, off64_t len64)
 {
   struct flock64 fl64;
   int cmd64;
+  int result;
 
   memset ((char *) &fl64, '\0', sizeof (fl64));
   fl64.l_whence = SEEK_CUR;
@@ -41,12 +42,13 @@ lockf64 (int fd, int cmd, off64_t len64)
       /* Test the lock: return 0 if FD is unlocked or locked by this process;
 	 return -1, set errno to EACCES, if another process holds the lock.  */
       fl64.l_type = F_RDLCK;
-      if (INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64) < 0)
-        return -1;
+      INTERNAL_SYSCALL_DECL (err);
+      result = INTERNAL_SYSCALL (fcntl64, err, 3, fd, F_GETLK64, &fl64);
+      if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, )))
+	return INLINE_SYSCALL_ERROR_RETURN (result, int, );
       if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
         return 0;
-      __set_errno (EACCES);
-      return -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-EACCES, int, );
     case F_ULOCK:
       fl64.l_type = F_UNLCK;
       cmd64 = F_SETLK64;
@@ -61,8 +63,7 @@ lockf64 (int fd, int cmd, off64_t len64)
       break;
 
     default:
-      __set_errno (EINVAL);
-      return -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, );
     }
-  return INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
+  return INLINE_SYSCALL_RETURN (fcntl64, 3, int, fd, cmd64, &fl64);
 }
diff --git a/sysdeps/unix/sysv/linux/i386/lxstat.c b/sysdeps/unix/sysv/linux/i386/lxstat.c
index 0891127..3503d23 100644
--- a/sysdeps/unix/sysv/linux/i386/lxstat.c
+++ b/sysdeps/unix/sysv/linux/i386/lxstat.c
@@ -38,15 +38,18 @@ __lxstat (int vers, const char *name, struct stat *buf)
   int result;
 
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (lstat, 2, name, (struct kernel_stat *) buf);
+    return INLINE_SYSCALL_RETURN (lstat, 2, int, name,
+				  (struct kernel_stat *) buf);
 
   {
     struct stat64 buf64;
 
-    result = INLINE_SYSCALL (lstat64, 2, name, &buf64);
-    if (result == 0)
-      result = __xstat32_conv (vers, &buf64, buf);
-    return result;
+    INTERNAL_SYSCALL_DECL (err);
+    result = INTERNAL_SYSCALL (lstat64, err, 2, name, &buf64);
+    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, )))
+      return INLINE_SYSCALL_ERROR_RETURN (result, int, );
+    else
+      return __xstat32_conv (vers, &buf64, buf);
   }
 }
 
diff --git a/sysdeps/unix/sysv/linux/i386/msgctl.c b/sysdeps/unix/sysv/linux/i386/msgctl.c
index e42f71d..c62de7b 100644
--- a/sysdeps/unix/sysv/linux/i386/msgctl.c
+++ b/sysdeps/unix/sysv/linux/i386/msgctl.c
@@ -55,7 +55,8 @@ int
 attribute_compat_text_section
 __old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf)
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_msgctl, msqid, cmd,
+				0, buf);
 }
 compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0);
 #endif
@@ -63,8 +64,8 @@ compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0);
 int
 __new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl,
-			 msqid, cmd | __IPC_64, 0, buf);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_msgctl, msqid,
+				cmd | __IPC_64, 0, buf);
 }
 
 versioned_symbol (libc, __new_msgctl, msgctl, GLIBC_2_2);
diff --git a/sysdeps/unix/sysv/linux/i386/putmsg.c b/sysdeps/unix/sysv/linux/i386/putmsg.c
index ab0112d..851b61a 100644
--- a/sysdeps/unix/sysv/linux/i386/putmsg.c
+++ b/sysdeps/unix/sysv/linux/i386/putmsg.c
@@ -30,7 +30,8 @@ putmsg (fildes, ctlptr, dataptr, flags)
      const struct strbuf *dataptr;
      int flags;
 {
-  return INLINE_SYSCALL (putpmsg, 5, fildes, ctlptr, dataptr, -1, flags);
+  return INLINE_SYSCALL_RETURN (putpmsg, 5, int, fildes, ctlptr,
+				dataptr, -1, flags);
 }
 #else
 # include <streams/putmsg.c>
diff --git a/sysdeps/unix/sysv/linux/i386/semctl.c b/sysdeps/unix/sysv/linux/i386/semctl.c
index 8f13649..fa9c364 100644
--- a/sysdeps/unix/sysv/linux/i386/semctl.c
+++ b/sysdeps/unix/sysv/linux/i386/semctl.c
@@ -71,8 +71,8 @@ __old_semctl (int semid, int semnum, int cmd, ...)
 
   va_end (ap);
 
-  return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd,
-			 &arg);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_semctl, semid,
+				semnum, cmd, &arg);
 }
 compat_symbol (libc, __old_semctl, semctl, GLIBC_2_0);
 #endif
@@ -90,8 +90,8 @@ __new_semctl (int semid, int semnum, int cmd, ...)
 
   va_end (ap);
 
-  return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
-			 &arg);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_semctl, semid,
+				semnum, cmd | __IPC_64, &arg);
 }
 
 versioned_symbol (libc, __new_semctl, semctl, GLIBC_2_2);
diff --git a/sysdeps/unix/sysv/linux/i386/setegid.c b/sysdeps/unix/sysv/linux/i386/setegid.c
index 8c39784..d2c0f47 100644
--- a/sysdeps/unix/sysv/linux/i386/setegid.c
+++ b/sysdeps/unix/sysv/linux/i386/setegid.c
@@ -17,23 +17,13 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <setxid.h>
 
 
 int
-setegid (gid)
-     gid_t gid;
+setegid (gid_t gid)
 {
-  int result;
-
   if (gid == (gid_t) ~0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1);
-
-  return result;
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, );
+  return INLINE_SYSCALL_RETURN (setresgid32, 3, int, -1, gid, -1);
 }
 libc_hidden_def (setegid)
diff --git a/sysdeps/unix/sysv/linux/i386/seteuid.c b/sysdeps/unix/sysv/linux/i386/seteuid.c
index d6a7a27..f77eaef 100644
--- a/sysdeps/unix/sysv/linux/i386/seteuid.c
+++ b/sysdeps/unix/sysv/linux/i386/seteuid.c
@@ -17,22 +17,13 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <setxid.h>
 
 
 int
 seteuid (uid_t uid)
 {
-  int result;
-
   if (uid == (uid_t) ~0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1);
-
-  return result;
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, );
+  return INLINE_SYSCALL_RETURN (setresuid32, 3, int, -1, uid, -1);
 }
 libc_hidden_def (seteuid)
diff --git a/sysdeps/unix/sysv/linux/i386/setgid.c b/sysdeps/unix/sysv/linux/i386/setgid.c
index d60d2bd..1ac608d 100644
--- a/sysdeps/unix/sysv/linux/i386/setgid.c
+++ b/sysdeps/unix/sysv/linux/i386/setgid.c
@@ -17,17 +17,12 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <setxid.h>
 #include <linux/posix_types.h>
 
 int
 __setgid (gid_t gid)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setgid32, 1, gid);
-
-  return result;
+  return INLINE_SYSCALL_RETURN (setgid32, 1, int, gid);
 }
 #ifndef __setgid
 weak_alias (__setgid, setgid)
diff --git a/sysdeps/unix/sysv/linux/i386/setgroups.c b/sysdeps/unix/sysv/linux/i386/setgroups.c
index aabdcf6..e5a99b7 100644
--- a/sysdeps/unix/sysv/linux/i386/setgroups.c
+++ b/sysdeps/unix/sysv/linux/i386/setgroups.c
@@ -23,7 +23,6 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
-#include <setxid.h>
 #include <linux/posix_types.h>
 
 /* Set the group set for the current user to GROUPS (N of them).  For
@@ -32,6 +31,6 @@
 int
 setgroups (size_t n, const gid_t *groups)
 {
-  return INLINE_SETXID_SYSCALL (setgroups32, 2, n, groups);
+  return INLINE_SYSCALL_RETURN (setgroups32, 2, int, n, groups);
 }
 libc_hidden_def (setgroups)
diff --git a/sysdeps/unix/sysv/linux/i386/setregid.c b/sysdeps/unix/sysv/linux/i386/setregid.c
index 865c47b..47efe6c 100644
--- a/sysdeps/unix/sysv/linux/i386/setregid.c
+++ b/sysdeps/unix/sysv/linux/i386/setregid.c
@@ -23,11 +23,7 @@
 int
 __setregid (gid_t rgid, gid_t egid)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setregid32, 2, rgid, egid);
-
-  return result;
+  return INLINE_SYSCALL_RETURN (setregid32, 2, int, rgid, egid);
 }
 #ifndef __setregid
 weak_alias (__setregid, setregid)
diff --git a/sysdeps/unix/sysv/linux/i386/setresgid.c b/sysdeps/unix/sysv/linux/i386/setresgid.c
index 9639c52..f14625a 100644
--- a/sysdeps/unix/sysv/linux/i386/setresgid.c
+++ b/sysdeps/unix/sysv/linux/i386/setresgid.c
@@ -24,11 +24,7 @@
 int
 __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setresgid32, 3, rgid, egid, sgid);
-
-  return result;
+  return INLINE_SYSCALL_RETURN (setresgid32, 3, int, rgid, egid, sgid);
 }
 libc_hidden_def (__setresgid)
 #ifndef __setresgid
diff --git a/sysdeps/unix/sysv/linux/i386/setresuid.c b/sysdeps/unix/sysv/linux/i386/setresuid.c
index f7e4107..b4151f2 100644
--- a/sysdeps/unix/sysv/linux/i386/setresuid.c
+++ b/sysdeps/unix/sysv/linux/i386/setresuid.c
@@ -24,11 +24,7 @@
 int
 __setresuid (uid_t ruid, uid_t euid, uid_t suid)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setresuid32, 3, ruid, euid, suid);
-
-  return result;
+  return INLINE_SYSCALL_RETURN (setresuid32, 3, int, ruid, euid, suid);
 }
 libc_hidden_def (__setresuid)
 #ifndef __setresuid
diff --git a/sysdeps/unix/sysv/linux/i386/setreuid.c b/sysdeps/unix/sysv/linux/i386/setreuid.c
index af3c5b4..73358b3 100644
--- a/sysdeps/unix/sysv/linux/i386/setreuid.c
+++ b/sysdeps/unix/sysv/linux/i386/setreuid.c
@@ -24,11 +24,7 @@
 int
 __setreuid (uid_t ruid, uid_t euid)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid);
-
-  return result;
+  return INLINE_SYSCALL_RETURN (setreuid32, 2, int, ruid, euid);
 }
 #ifndef __setreuid
 weak_alias (__setreuid, setreuid)
diff --git a/sysdeps/unix/sysv/linux/i386/setuid.c b/sysdeps/unix/sysv/linux/i386/setuid.c
index ce6016e..103047c 100644
--- a/sysdeps/unix/sysv/linux/i386/setuid.c
+++ b/sysdeps/unix/sysv/linux/i386/setuid.c
@@ -24,11 +24,7 @@
 int
 __setuid (uid_t uid)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setuid32, 1, uid);
-
-  return result;
+  return INLINE_SYSCALL_RETURN (setuid32, 1, int, uid);
 }
 #ifndef __setuid
 weak_alias (__setuid, setuid)
diff --git a/sysdeps/unix/sysv/linux/i386/shmctl.c b/sysdeps/unix/sysv/linux/i386/shmctl.c
index eeb4453..0fea8ae 100644
--- a/sysdeps/unix/sysv/linux/i386/shmctl.c
+++ b/sysdeps/unix/sysv/linux/i386/shmctl.c
@@ -62,7 +62,8 @@ int
 attribute_compat_text_section
 __old_shmctl (int shmid, int cmd, struct __old_shmid_ds *buf)
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int,  IPCOP_shmctl, shmid,
+				cmd, 0, buf);
 }
 compat_symbol (libc, __old_shmctl, shmctl, GLIBC_2_0);
 #endif
@@ -70,8 +71,8 @@ compat_symbol (libc, __old_shmctl, shmctl, GLIBC_2_0);
 int
 __new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl,
-			 shmid, cmd | __IPC_64, 0, buf);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_shmctl, shmid,
+				cmd | __IPC_64, 0, buf);
 }
 
 versioned_symbol (libc, __new_shmctl, shmctl, GLIBC_2_2);
diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
index b20a9b9..f9bf43b 100644
--- a/sysdeps/unix/sysv/linux/i386/sigaction.c
+++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
@@ -69,11 +69,13 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
 
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-  result = INLINE_SYSCALL (rt_sigaction, 4,
-			   sig, act ? &kact : NULL,
-			   oact ? &koact : NULL, _NSIG / 8);
-
-  if (oact && result >= 0)
+  INTERNAL_SYSCALL_DECL (err);
+  result = INTERNAL_SYSCALL (rt_sigaction, err, 4,
+			     sig, act ? &kact : NULL,
+			     oact ? &koact : NULL, _NSIG / 8);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, )))
+     return INLINE_SYSCALL_ERROR_RETURN (result, int, );
+  else if (oact && result >= 0)
     {
       oact->sa_handler = koact.k_sa_handler;
       memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.S b/sysdeps/unix/sysv/linux/i386/sysdep.S
deleted file mode 100644
index 4e6c262..0000000
--- a/sysdeps/unix/sysv/linux/i386/sysdep.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (C) 1995-2015 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>
-
-/* The following code is only used in the shared library when we
-   compile the reentrant version.  Otherwise each system call defines
-   each own version.  */
-
-#ifndef PIC
-
-/* The syscall stubs jump here when they detect an error.
-   The code for Linux is almost identical to the canonical Unix/i386
-   code, except that the error number in %eax is negated.  */
-
-#undef CALL_MCOUNT
-#define CALL_MCOUNT /* Don't insert the profiling call, it clobbers %eax.  */
-
-	.text
-ENTRY (__syscall_error)
-	negl %eax
-
-#define __syscall_error __syscall_error_1
-#include <sysdeps/unix/i386/sysdep.S>
-
-#endif	/* !PIC */
diff --git a/sysdeps/unix/sysv/linux/i386/setregid.c b/sysdeps/unix/sysv/linux/i386/sysdep.c
similarity index 68%
copy from sysdeps/unix/sysv/linux/i386/setregid.c
copy to sysdeps/unix/sysv/linux/i386/sysdep.c
index 865c47b..2fcc6f8 100644
--- a/sysdeps/unix/sysv/linux/i386/setregid.c
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2015 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
@@ -16,19 +16,15 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
-#include <unistd.h>
-#include <setxid.h>
-#include <linux/posix_types.h>
-
+#include <sysdep.h>
+ 
+/* This routine is jumped to by all the syscall handlers, to stash
+   an error number into errno.  ERROR is the negative error number
+   returned from the x86 kernel.  */
 int
-__setregid (gid_t rgid, gid_t egid)
+__attribute__ ((__regparm__ (1)))
+__syscall_error (int error)
 {
-  int result;
-
-  result = INLINE_SETXID_SYSCALL (setregid32, 2, rgid, egid);
-
-  return result;
+  __set_errno (-error);
+  return -1;
 }
-#ifndef __setregid
-weak_alias (__setregid, setregid)
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index d76aca5..9df55c7 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -55,11 +55,7 @@
 
 /* We don't want the label for the error handle to be global when we define
    it here.  */
-#ifdef PIC
-# define SYSCALL_ERROR_LABEL 0f
-#else
-# define SYSCALL_ERROR_LABEL syscall_error
-#endif
+#define SYSCALL_ERROR_LABEL __syscall_error
 
 #undef	PSEUDO
 #define	PSEUDO(name, syscall_name, args)				      \
@@ -100,55 +96,7 @@
 
 #define ret_ERRVAL ret
 
-#ifndef PIC
-# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
-#else
-
-# if RTLD_PRIVATE_ERRNO
-#  define SYSCALL_ERROR_HANDLER						      \
-0:SETUP_PIC_REG(cx);							      \
-  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
-  negl %eax;								      \
-  movl %eax, rtld_errno@GOTOFF(%ecx);					      \
-  orl $-1, %eax;							      \
-  ret;
-
-# elif defined _LIBC_REENTRANT
-
-#  if IS_IN (libc)
-#   define SYSCALL_ERROR_ERRNO __libc_errno
-#  else
-#   define SYSCALL_ERROR_ERRNO errno
-#  endif
-#  define SYSCALL_ERROR_HANDLER					      \
-0:SETUP_PIC_REG (cx);							      \
-  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
-  movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;			      \
-  negl %eax;								      \
-  SYSCALL_ERROR_HANDLER_TLS_STORE (%eax, %ecx);				      \
-  orl $-1, %eax;							      \
-  ret;
-#  ifndef NO_TLS_DIRECT_SEG_REFS
-#   define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)		      \
-  movl src, %gs:(destoff)
-#  else
-#   define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)		      \
-  addl %gs:0, destoff;							      \
-  movl src, (destoff)
-#  endif
-# else
-/* Store (- %eax) into errno through the GOT.  */
-#  define SYSCALL_ERROR_HANDLER						      \
-0:SETUP_PIC_REG(cx);							      \
-  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
-  negl %eax;								      \
-  movl errno@GOT(%ecx), %ecx;						      \
-  movl %eax, (%ecx);							      \
-  orl $-1, %eax;							      \
-  ret;
-# endif	/* _LIBC_REENTRANT */
-#endif	/* PIC */
-
+#define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.c is used.  */
 
 /* The original calling convention for system calls on Linux/i386 is
    to use int $0x80.  */
@@ -275,6 +223,10 @@
 
 #else	/* !__ASSEMBLER__ */
 
+extern int __syscall_error (int)
+  attribute_hidden __attribute__ ((__regparm__ (1)));
+
+#if !__GNUC_PREREQ (5,0)
 /* We need some help from the assembler to generate optimal code.  We
    define some macros here which later will be used.  */
 asm (".L__X'%ebx = 1\n\t"
@@ -314,6 +266,7 @@ struct libc_do_syscall_args
 {
   int ebx, edi, ebp;
 };
+#endif
 
 /* Define a macro which expands inline into the wrapper code for a system
    call.  */
@@ -328,6 +281,27 @@ struct libc_do_syscall_args
       }									      \
     (int) resultvar; })
 
+/* Similar to INLINE_SYSCALL, but with return type.  It should only be
+   used with functin return.  */
+#undef INLINE_SYSCALL_RETURN
+#define INLINE_SYSCALL_RETURN(name, nr, type, args...) \
+  ({									\
+    unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);	\
+    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, )))	\
+      return INLINE_SYSCALL_ERROR_RETURN (resultvar, type, );		\
+    (type) resultvar;							\
+  })									\
+
+/* Set error number and return value.  It should only be used with
+   functin return.  We just branch to the internal __syscall_error
+   and ignore return value.  */
+#undef INLINE_SYSCALL_ERROR_RETURN
+#define INLINE_SYSCALL_ERROR_RETURN(resultvar, type, value) \
+  ({									\
+      return (type) __syscall_error (resultvar);			\
+    (type) -1;								\
+  })									\
+
 /* List of system calls which are supported as vsyscalls.  */
 # define HAVE_CLOCK_GETTIME_VSYSCALL    1
 # define HAVE_GETTIMEOFDAY_VSYSCALL     1
@@ -354,8 +328,12 @@ struct libc_do_syscall_args
     INTERNAL_SYSCALL_MAIN_INLINE(name, err, 5, args)
 /* Each object using 6-argument inline syscalls must include a
    definition of __libc_do_syscall.  */
-#define INTERNAL_SYSCALL_MAIN_6(name, err, arg1, arg2, arg3,		\
-				arg4, arg5, arg6)			\
+#if __GNUC_PREREQ (5,0)
+# define INTERNAL_SYSCALL_MAIN_6(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 6, args)
+#else /* GCC 5  */
+# define INTERNAL_SYSCALL_MAIN_6(name, err, arg1, arg2, arg3,		\
+				 arg4, arg5, arg6)			\
   struct libc_do_syscall_args _xv =					\
     {									\
       (int) (arg1),							\
@@ -368,14 +346,52 @@ struct libc_do_syscall_args
     : "=a" (resultvar)							\
     : "i" (__NR_##name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \
     : "memory", "cc")
+#endif /* GCC 5  */
 #define INTERNAL_SYSCALL(name, err, nr, args...) \
   ({									      \
     register unsigned int resultvar;					      \
     INTERNAL_SYSCALL_MAIN_##nr (name, err, args);			      \
     (int) resultvar; })
 #ifdef I386_USE_SYSENTER
-# ifdef SHARED
-#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
+# if __GNUC_PREREQ (5,0)
+#  ifdef SHARED
+#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
+    LOADREGS_##nr(args)							\
+    asm volatile (							\
+    "call *%%gs:%P2"							\
+    : "=a" (resultvar)							\
+    : "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		\
+      ASMARGS_##nr(args) : "memory", "cc")
+#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									\
+    register unsigned int resultvar;					\
+    LOADREGS_##nr(args)							\
+    asm volatile (							\
+    "call *%%gs:%P2"							\
+    : "=a" (resultvar)							\
+    : "a" (name), "i" (offsetof (tcbhead_t, sysinfo))			\
+      ASMARGS_##nr(args) : "memory", "cc");				\
+    (int) resultvar; })
+#  else
+#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
+    LOADREGS_##nr(args)							\
+    asm volatile (							\
+    "call *_dl_sysinfo"							\
+    : "=a" (resultvar)							\
+    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
+#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									\
+    register unsigned int resultvar;					\
+    LOADREGS_##nr(args)							\
+    asm volatile (							\
+    "call *_dl_sysinfo"							\
+    : "=a" (resultvar)							\
+    : "a" (name) ASMARGS_##nr(args) : "memory", "cc");			\
+    (int) resultvar; })
+#  endif
+# else /* GCC 5  */
+#  ifdef SHARED
+#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
     asm volatile (							      \
     LOADARGS_##nr							      \
@@ -385,7 +401,7 @@ struct libc_do_syscall_args
     : "=a" (resultvar)							      \
     : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		      \
       ASMFMT_##nr(args) : "memory", "cc")
-#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
   ({									      \
     register unsigned int resultvar;					      \
     EXTRAVAR_##nr							      \
@@ -397,8 +413,8 @@ struct libc_do_syscall_args
     : "0" (name), "i" (offsetof (tcbhead_t, sysinfo))			      \
       ASMFMT_##nr(args) : "memory", "cc");				      \
     (int) resultvar; })
-# else
-#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
+#  else
+#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
     asm volatile (							      \
     LOADARGS_##nr							      \
@@ -407,7 +423,7 @@ struct libc_do_syscall_args
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
-#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
   ({									      \
     register unsigned int resultvar;					      \
     EXTRAVAR_##nr							      \
@@ -418,9 +434,27 @@ struct libc_do_syscall_args
     : "=a" (resultvar)							      \
     : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
     (int) resultvar; })
-# endif
+#  endif
+# endif /* GCC 5  */
 #else
-# define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
+# if __GNUC_PREREQ (5,0)
+#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
+    LOADREGS_##nr(args)							\
+    asm volatile (							\
+    "int $0x80"								\
+    : "=a" (resultvar)							\
+    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
+#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									\
+    register unsigned int resultvar;					\
+    LOADREGS_##nr(args)							\
+    asm volatile (							\
+    "int $0x80"								\
+    : "=a" (resultvar)							\
+    : "a" (name) ASMARGS_##nr(args) : "memory", "cc");			\
+    (int) resultvar; })
+# else /* GCC 5  */
+#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
     asm volatile (							      \
     LOADARGS_##nr							      \
@@ -429,7 +463,7 @@ struct libc_do_syscall_args
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
-# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
   ({									      \
     register unsigned int resultvar;					      \
     EXTRAVAR_##nr							      \
@@ -440,6 +474,7 @@ struct libc_do_syscall_args
     : "=a" (resultvar)							      \
     : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
     (int) resultvar; })
+# endif /* GCC 5  */
 #endif
 
 #undef INTERNAL_SYSCALL_DECL
@@ -504,6 +539,36 @@ struct libc_do_syscall_args
 # define RESTOREARGS_5
 #endif
 
+#if __GNUC_PREREQ (5,0)
+# define LOADREGS_0()
+# define ASMARGS_0()
+# define LOADREGS_1(arg1) \
+	LOADREGS_0 ()
+# define ASMARGS_1(arg1) \
+	ASMARGS_0 (), "b" ((unsigned int) (arg1))
+# define LOADREGS_2(arg1, arg2) \
+	LOADREGS_1 (arg1)
+# define ASMARGS_2(arg1, arg2) \
+	ASMARGS_1 (arg1), "c" ((unsigned int) (arg2))
+# define LOADREGS_3(arg1, arg2, arg3) \
+	LOADREGS_2 (arg1, arg2)
+# define ASMARGS_3(arg1, arg2, arg3) \
+	ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3))
+# define LOADREGS_4(arg1, arg2, arg3, arg4) \
+	LOADREGS_3 (arg1, arg2, arg3)
+# define ASMARGS_4(arg1, arg2, arg3, arg4) \
+	ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4))
+# define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
+	LOADREGS_4 (arg1, arg2, arg3, arg4)
+# define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
+	ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5))
+# define LOADREGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
+	register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6); \
+	LOADREGS_5 (arg1, arg2, arg3, arg4, arg5)
+# define ASMARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
+	ASMARGS_5 (arg1, arg2, arg3, arg4, arg5), "r" (_a6)
+#endif /* GCC 5  */
+
 #define ASMFMT_0()
 #ifdef __PIC__
 # define ASMFMT_1(arg1) \
diff --git a/sysdeps/unix/sysv/linux/i386/xstat.c b/sysdeps/unix/sysv/linux/i386/xstat.c
index 2424434..290feb4 100644
--- a/sysdeps/unix/sysv/linux/i386/xstat.c
+++ b/sysdeps/unix/sysv/linux/i386/xstat.c
@@ -38,15 +38,18 @@ __xstat (int vers, const char *name, struct stat *buf)
   int result;
 
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (stat, 2, name, (struct kernel_stat *) buf);
+    return INLINE_SYSCALL_RETURN (stat, 2, int, name,
+				  (struct kernel_stat *) buf);
 
   {
     struct stat64 buf64;
 
-    result = INLINE_SYSCALL (stat64, 2, name, &buf64);
-    if (result == 0)
-      result = __xstat32_conv (vers, &buf64, buf);
-    return result;
+    INTERNAL_SYSCALL_DECL (err);
+    result = INTERNAL_SYSCALL (stat64, err, 2, name, &buf64);
+    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, )))
+      return INLINE_SYSCALL_ERROR_RETURN (result, int, );
+    else
+      return __xstat32_conv (vers, &buf64, buf);
   }
 }
 hidden_def (__xstat)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=037d6432a49be52ba482f41f65523ef31a9609d1

commit 037d6432a49be52ba482f41f65523ef31a9609d1
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Aug 13 15:40:05 2015 -0700

    Add INLINE_SYSCALL_RETURN/INLINE_SYSCALL_ERROR_RETURN
    
    For ia32 PIC, the first thing of many syscalls does is to call
    __x86.get_pc_thunk.reg to load PC into reg in case there is an error,
    which is required for setting errno.  In most cases, there are no
    errors.  But we still call __x86.get_pc_thunk.reg.  This patch adds
    INLINE_SYSCALL_RETURN and INLINE_SYSCALL_ERROR_RETURN so that i386
    can optimize setting errno by branching to the internal __syscall_error
    without PLT.
    
    INLINE_SYSCALL_ERROR_RETURN is designed to take the negative error
    number returned from the majority of Linux kernels for which negating
    is a no-op with INTERNAL_SYSCALL_ERRNO.
    
    With i386 INLINE_SYSCALL_RETURN, INLINE_SYSCALL_ERROR_RETURN and
    i386 syscall inlining optimization for GCC 5, for
    sysdeps/unix/sysv/linux/fchmodat.c with -O2 -march=i686
    -mtune=generic, GCC 5.2 now generates:
    
    <fchmodat>:
       0:	push   %ebx
       1:	mov    0x14(%esp),%eax
       5:	mov    0x8(%esp),%ebx
       9:	mov    0xc(%esp),%ecx
       d:	mov    0x10(%esp),%edx
      11:	test   $0xfffffeff,%eax
      16:	jne    38 <fchmodat+0x38>
      18:	test   $0x1,%ah
      1b:	jne    48 <fchmodat+0x48>
      1d:	mov    $0x132,%eax
      22:	call   *%gs:0x10
      29:	cmp    $0xfffff000,%eax
      2e:	ja     58 <fchmodat+0x58>
      30:	pop    %ebx
      31:	ret
      32:	lea    0x0(%esi),%esi
      38:	pop    %ebx
      39:	mov    $0xffffffea,%eax
      3e:	jmp    3f <fchmodat+0x3f>	3f: R_386_PC32	__syscall_error
      43:	nop
      44:	lea    0x0(%esi,%eiz,1),%esi
      48:	pop    %ebx
      49:	mov    $0xffffffa1,%eax
      4e:	jmp    4f <fchmodat+0x4f>	4f: R_386_PC32	__syscall_error
      53:	nop
      54:	lea    0x0(%esi,%eiz,1),%esi
      58:	pop    %ebx
      59:	jmp    5a <fchmodat+0x5a>	5a: R_386_PC32	__syscall_error
    
    instead of
    
    <fchmodat>:
       0:	sub    $0x8,%esp
       3:	mov    0x18(%esp),%eax
       7:	mov    %ebx,(%esp)
       a:	call   b <fchmodat+0xb>	b: R_386_PC32	__x86.get_pc_thunk.bx
       f:	add    $0x2,%ebx	11: R_386_GOTPC	_GLOBAL_OFFSET_TABLE_
      15:	mov    %edi,0x4(%esp)
      19:	test   $0xfffffeff,%eax
      1e:	jne    70 <fchmodat+0x70>
      20:	test   $0x1,%ah
      23:	jne    88 <fchmodat+0x88>
      25:	mov    0x14(%esp),%edx
      29:	mov    0x10(%esp),%ecx
      2d:	mov    0xc(%esp),%edi
      31:	xchg   %ebx,%edi
      33:	mov    $0x132,%eax
      38:	call   *%gs:0x10
      3f:	xchg   %edi,%ebx
      41:	cmp    $0xfffff000,%eax
      46:	ja     58 <fchmodat+0x58>
      48:	mov    (%esp),%ebx
      4b:	mov    0x4(%esp),%edi
      4f:	add    $0x8,%esp
      52:	ret
      53:	nop
      54:	lea    0x0(%esi,%eiz,1),%esi
      58:	mov    0x0(%ebx),%edx	5a: R_386_TLS_GOTIE	__libc_errno
      5e:	neg    %eax
      60:	mov    %eax,%gs:(%edx)
      63:	mov    $0xffffffff,%eax
      68:	jmp    48 <fchmodat+0x48>
      6a:	lea    0x0(%esi),%esi
      70:	mov    0x0(%ebx),%eax	72: R_386_TLS_GOTIE	__libc_errno
      76:	movl   $0x16,%gs:(%eax)
      7d:	mov    $0xffffffff,%eax
      82:	jmp    48 <fchmodat+0x48>
      84:	lea    0x0(%esi,%eiz,1),%esi
      88:	mov    0x0(%ebx),%eax	8a: R_386_TLS_GOTIE	__libc_errno
      8e:	movl   $0x5f,%gs:(%eax)
      95:	mov    $0xffffffff,%eax
      9a:	jmp    48 <fchmodat+0x48>
    
    	* sysdeps/unix/sysdep.h (INLINE_SYSCALL_RETURN): New.
    	(INLINE_SYSCALL_ERROR_RETURN): Likewise.
    	* sysdeps/unix/sysv/linux/adjtime.c (ADJTIME): Use
    	INLINE_SYSCALL_RETURN and INLINE_SYSCALL_ERROR_RETURN.
    	* sysdeps/unix/sysv/linux/aio_sigqueue.c (__aio_sigqueue):
    	Likewise.
    	* sysdeps/unix/sysv/linux/dl-openat64.c (openat64): Likewise.
    	* sysdeps/unix/sysv/linux/eventfd.c (eventfd): Likewise.
    	* sysdeps/unix/sysv/linux/faccessat.c (faccessat): Likewise.
    	* sysdeps/unix/sysv/linux/fchmodat.c (fchmodat): Likewise.
    	* sysdeps/unix/sysv/linux/fcntl.c (do_fcntl): Likewise.
    	* sysdeps/unix/sysv/linux/fstatfs64.c (__fstatfs64): Likewise.
    	* sysdeps/unix/sysv/linux/ftruncate64.c (__ftruncate64): Likewise.
    	* sysdeps/unix/sysv/linux/futimens.c (futimens): Likewise.
    	* sysdeps/unix/sysv/linux/futimes.c (__futimes): Likewise.
    	* sysdeps/unix/sysv/linux/futimesat.c (futimesat): Likewise.
    	* sysdeps/unix/sysv/linux/fxstat.c (__fxstat): Likewise.
    	* sysdeps/unix/sysv/linux/fxstat64.c (___fxstat64): Likewise.
    	* sysdeps/unix/sysv/linux/fxstatat.c (__fxstatat): Likewise.
    	* sysdeps/unix/sysv/linux/fxstatat64.c (__fxstatat64): Likewise.
    	* sysdeps/unix/sysv/linux/gai_sigqueue.c (__gai_sigqueue):
    	Likewise.
    	* sysdeps/unix/sysv/linux/getpriority.c (__getpriority): Likewise.
    	* sysdeps/unix/sysv/linux/getrlimit64.c (__getrlimit64): Likewise.
    	* sysdeps/unix/sysv/linux/llseek.c (__llseek): Likewise.
    	* sysdeps/unix/sysv/linux/lutimes.c (lutimes): Likewise.
    	* sysdeps/unix/sysv/linux/lxstat.c (__lxstat): Likewise.
    	* sysdeps/unix/sysv/linux/lxstat64.c (___lxstat64): Likewise.
    	* sysdeps/unix/sysv/linux/mmap64.c (__mmap64): Likewise.
    	* sysdeps/unix/sysv/linux/mq_close.c (mq_close): Likewise.
    	* sysdeps/unix/sysv/linux/mq_open.c (__mq_open): Likewise.
    	* sysdeps/unix/sysv/linux/mq_unlink.c (mq_unlink): Likewise.
    	* sysdeps/unix/sysv/linux/msgget.c (msgget): Likewise.
    	* sysdeps/unix/sysv/linux/prlimit.c (prlimit): Likewise.
    	* sysdeps/unix/sysv/linux/pt-raise.c (raise): Likewise.
    	* sysdeps/unix/sysv/linux/raise.c (raise): Likewise.
    	* sysdeps/unix/sysv/linux/readahead.c (__readahead): Likewise.
    	* sysdeps/unix/sysv/linux/reboot.c (reboot): Likewise.
    	* sysdeps/unix/sysv/linux/semget.c (semget): Likewise.
    	* sysdeps/unix/sysv/linux/semop.c (semop): Likewise.
    	* sysdeps/unix/sysv/linux/semtimedop.c (semtimedop): Likewise.
    	* sysdeps/unix/sysv/linux/setrlimit64.c (setrlimit64): Likewise.
    	* sysdeps/unix/sysv/linux/shmat.c (shmat): Likewise.
    	* sysdeps/unix/sysv/linux/shmdt.c (shmdt): Likewise.
    	* sysdeps/unix/sysv/linux/shmget.c (shmget): Likewise.
    	* sysdeps/unix/sysv/linux/signalfd.c (signalfd): Likewise.
    	* sysdeps/unix/sysv/linux/sigpending.c (sigpending): Likewise.
    	* sysdeps/unix/sysv/linux/sigprocmask.c ( __sigprocmask): Likewise.
    	* sysdeps/unix/sysv/linux/sigqueue.c (__sigqueue): Likewise.
    	* sysdeps/unix/sysv/linux/speed.c (cfsetospeed): Likewise.
    	* sysdeps/unix/sysv/linux/statfs64.c (__statfs64): Likewise.
    	* sysdeps/unix/sysv/linux/sysctl.c (__sysctl): Likewise.
    	* sysdeps/unix/sysv/linux/tcsendbrk.c (tcsendbreak): Likewise.
    	* sysdeps/unix/sysv/linux/tcsetattr.c (tcsetattr): Likewise.
    	* sysdeps/unix/sysv/linux/timer_getoverr.c (timer_getoverrun):
    	Likewise.
    	* sysdeps/unix/sysv/linux/timer_gettime.c (timer_gettime):
    	Likewise.
    	* sysdeps/unix/sysv/linux/timer_settime.c (timer_settime):
    	Likewise.
    	* sysdeps/unix/sysv/linux/truncate64.c (truncate64): Likewise.
    	* sysdeps/unix/sysv/linux/ustat.c (ustat): Likewise.
    	* sysdeps/unix/sysv/linux/utimensat.c (utimensat): Likewise.
    	* sysdeps/unix/sysv/linux/utimes.c (__utimes): Likewise.
    	* sysdeps/unix/sysv/linux/xmknod.c (__xmknod): Likewise.
    	* sysdeps/unix/sysv/linux/xmknodat.c (__xmknodat): Likewise.
    	* sysdeps/unix/sysv/linux/xstat.c (__xstat): Likewise.
    	* sysdeps/unix/sysv/linux/xstat64.c (___xstat64): Likewise.
    	* sysdeps/unix/sysv/linux/xstatconv.c (__xstat_conv): Likewise.
    	(__xstat64_conv): Likewise.
    	(__xstat32_conv): Likewise.
    	* sysdeps/unix/sysv/linux/sched_getaffinity.c
    	(__sched_getaffinity_new): Add libc_hidden_proto and
    	libc_hidden_def.  Use INLINE_SYSCALL_ERROR_RETURN.

diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
index 52dad58..ca3151e 100644
--- a/sysdeps/unix/sysdep.h
+++ b/sysdeps/unix/sysdep.h
@@ -73,3 +73,22 @@
 #ifndef INLINE_SYSCALL
 #define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args)
 #endif
+
+/* Similar to INLINE_SYSCALL, but with return type.  It should only be
+   used with functin return.  */
+#ifndef INLINE_SYSCALL_RETURN
+#define INLINE_SYSCALL_RETURN(name, nr, type, args...) \
+  INLINE_SYSCALL (name, nr, args)
+#endif
+
+/* Set error number and return value.  It should only be used with
+   functin return.  ERR is the negative error number returned from
+   the majority of Linux kernels for which -ERR is no-op
+   with INTERNAL_SYSCALL_ERRNO.   */
+#ifndef INLINE_SYSCALL_ERROR_RETURN
+#define INLINE_SYSCALL_ERROR_RETURN(err, type, value) \
+  ({								\
+    __set_errno (-err);						\
+    (type) (value);						\
+  })
+#endif
diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index b6fb7cf..ad54cf8 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -61,10 +61,7 @@ ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv)
       tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
       tmp.tv_usec = itv->tv_usec % 1000000L;
       if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
-	{
-	  __set_errno (EINVAL);
-	  return -1;
-	}
+	return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
       tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
       tntx.modes = ADJ_OFFSET_SINGLESHOT;
     }
diff --git a/sysdeps/unix/sysv/linux/aio_sigqueue.c b/sysdeps/unix/sysv/linux/aio_sigqueue.c
index 6a48e62..c56b94f 100644
--- a/sysdeps/unix/sysv/linux/aio_sigqueue.c
+++ b/sysdeps/unix/sysv/linux/aio_sigqueue.c
@@ -47,7 +47,8 @@ __aio_sigqueue (sig, val, caller_pid)
   info.si_uid = getuid ();
   info.si_value = val;
 
-  return INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, sig, &info);
+  return INLINE_SYSCALL_RETURN (rt_sigqueueinfo, 3, int, info.si_pid,
+				sig, &info);
 }
 #else
 # include <rt/aio_sigqueue.c>
diff --git a/sysdeps/unix/sysv/linux/dl-openat64.c b/sysdeps/unix/sysv/linux/dl-openat64.c
index 732097d..ffb13f3 100644
--- a/sysdeps/unix/sysv/linux/dl-openat64.c
+++ b/sysdeps/unix/sysv/linux/dl-openat64.c
@@ -31,9 +31,9 @@ openat64 (dfd, file, oflag)
   assert (!__OPEN_NEEDS_MODE (oflag));
 
 #ifdef __NR_openat
-  return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE);
+  return INLINE_SYSCALL_RETURN (openat, 3, int, dfd, file,
+				oflag | O_LARGEFILE);
 #else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 #endif
 }
diff --git a/sysdeps/unix/sysv/linux/eventfd.c b/sysdeps/unix/sysv/linux/eventfd.c
index d4ffb3c..1496a0e 100644
--- a/sysdeps/unix/sysv/linux/eventfd.c
+++ b/sysdeps/unix/sysv/linux/eventfd.c
@@ -25,11 +25,14 @@ int
 eventfd (unsigned int count, int flags)
 {
 #ifdef __NR_eventfd2
-  int res = INLINE_SYSCALL (eventfd2, 2, count, flags);
 # ifndef __ASSUME_EVENTFD2
-  if (res != -1 || errno != ENOSYS)
-# endif
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (eventfd2, err, 2, count, flags);
+  if (!__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err))
+      || INTERNAL_SYSCALL_ERRNO (res, err) != ENOSYS)
     return res;
+# endif
+  return INLINE_SYSCALL_RETURN (eventfd2, 2, int, count, flags);
 #endif
 
 #ifndef __ASSUME_EVENTFD2
@@ -38,16 +41,12 @@ eventfd (unsigned int count, int flags)
      kernel (sys_indirect) before implementing setting flags like
      O_NONBLOCK etc.  */
   if (flags != 0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1)
 
 # ifdef __NR_eventfd
-  return INLINE_SYSCALL (eventfd, 1, count);
+  return INLINE_SYSCALL_RETURN (eventfd, 1, int, count)
 # else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1)
 # endif
 #elif !defined __NR_eventfd2
 # error "__ASSUME_EVENTFD2 defined but not __NR_eventfd2"
diff --git a/sysdeps/unix/sysv/linux/faccessat.c b/sysdeps/unix/sysv/linux/faccessat.c
index 1bb544f..6a0b1b7 100644
--- a/sysdeps/unix/sysv/linux/faccessat.c
+++ b/sysdeps/unix/sysv/linux/faccessat.c
@@ -35,13 +35,10 @@ faccessat (fd, file, mode, flag)
      int flag;
 {
   if (flag & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS))
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
   if ((flag == 0 || ((flag & ~AT_EACCESS) == 0 && ! __libc_enable_secure)))
-    return INLINE_SYSCALL (faccessat, 3, fd, file, mode);
+    return INLINE_SYSCALL_RETURN (faccessat, 3, int, fd, file, mode);
 
   struct stat64 stats;
   if (__fxstatat64 (_STAT_VER, fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW))
@@ -74,6 +71,5 @@ faccessat (fd, file, mode, flag)
   if (granted == mode)
     return 0;
 
-  __set_errno (EACCES);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-EACCES, int, -1);
 }
diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c
index e278426..025634b 100644
--- a/sysdeps/unix/sysv/linux/fchmodat.c
+++ b/sysdeps/unix/sysv/linux/fchmodat.c
@@ -34,17 +34,11 @@ fchmodat (fd, file, mode, flag)
      int flag;
 {
   if (flag & ~AT_SYMLINK_NOFOLLOW)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 #ifndef __NR_lchmod		/* Linux so far has no lchmod syscall.  */
   if (flag & AT_SYMLINK_NOFOLLOW)
-    {
-      __set_errno (ENOTSUP);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-ENOTSUP, int, -1);
 #endif
 
-  return INLINE_SYSCALL (fchmodat, 3, fd, file, mode);
+  return INLINE_SYSCALL_RETURN (fchmodat, 3, int, fd, file, mode);
 }
diff --git a/sysdeps/unix/sysv/linux/fcntl.c b/sysdeps/unix/sysv/linux/fcntl.c
index fa184db..a9a6b65 100644
--- a/sysdeps/unix/sysv/linux/fcntl.c
+++ b/sysdeps/unix/sysv/linux/fcntl.c
@@ -28,7 +28,7 @@ static int
 do_fcntl (int fd, int cmd, void *arg)
 {
   if (cmd != F_GETOWN)
-    return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg);
+    return INLINE_SYSCALL_RETURN (fcntl, 3, int, fd, cmd, arg);
 
   INTERNAL_SYSCALL_DECL (err);
   struct f_owner_ex fex;
@@ -36,8 +36,8 @@ do_fcntl (int fd, int cmd, void *arg)
   if (!INTERNAL_SYSCALL_ERROR_P (res, err))
     return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
 
-  __set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (res, err),
+				      int, -1);
 }
 
 
diff --git a/sysdeps/unix/sysv/linux/fstatfs64.c b/sysdeps/unix/sysv/linux/fstatfs64.c
index af83830..bba9918 100644
--- a/sysdeps/unix/sysv/linux/fstatfs64.c
+++ b/sysdeps/unix/sysv/linux/fstatfs64.c
@@ -35,12 +35,17 @@ __fstatfs64 (int fd, struct statfs64 *buf)
   if (! __no_statfs64)
 # endif
     {
-      int result = INLINE_SYSCALL (fstatfs64, 3, fd, sizeof (*buf), buf);
-
 # if __ASSUME_STATFS64 == 0
-      if (result == 0 || errno != ENOSYS)
-# endif
+      INTERNAL_SYSCALL_DECL (err);
+      int result = INTERNAL_SYSCALL (fstatfs64, err, 3, fd,
+				     sizeof (*buf), buf);
+      if (!__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))
+	  || INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
 	return result;
+# else
+      return INLINE_SYSCALL_RETURN (fstatfs64, 3, int, fd,
+				    sizeof (*buf), buf);
+# endif
 
 # if __ASSUME_STATFS64 == 0
       __no_statfs64 = 1;
diff --git a/sysdeps/unix/sysv/linux/ftruncate64.c b/sysdeps/unix/sysv/linux/ftruncate64.c
index cc3c43c..b466229 100644
--- a/sysdeps/unix/sysv/linux/ftruncate64.c
+++ b/sysdeps/unix/sysv/linux/ftruncate64.c
@@ -29,8 +29,7 @@ __ftruncate64 (int fd, off64_t length)
 {
   unsigned int low = length & 0xffffffff;
   unsigned int high = length >> 32;
-  int result = INLINE_SYSCALL (ftruncate64, 3, fd,
-			       __LONG_LONG_PAIR (high, low));
-  return result;
+  return INLINE_SYSCALL_RETURN (ftruncate64, 3, int, fd,
+				__LONG_LONG_PAIR (high, low));
 }
 weak_alias (__ftruncate64, ftruncate64)
diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c
index 5f2b8a5..dfc21c0 100644
--- a/sysdeps/unix/sysv/linux/futimens.c
+++ b/sysdeps/unix/sysv/linux/futimens.c
@@ -33,15 +33,11 @@ futimens (int fd, const struct timespec tsp[2])
 {
 #ifdef __NR_utimensat
   if (fd < 0)
-    {
-      __set_errno (EBADF);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EBADF, int, -1);
   /* Avoid implicit array coercion in syscall macros.  */
-  return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0);
+  return INLINE_SYSCALL_RETURN (utimensat, 4, int, fd, NULL, &tsp[0], 0);
 #else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 #endif
 }
 #ifndef __NR_utimensat
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index 69ddfe1..72094b6 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -40,15 +40,13 @@ __futimes (int fd, const struct timeval tvp[2])
     {
       if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
           || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
-	{
-	  __set_errno (EINVAL);
-	  return -1;
-	}
+	return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
       TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]);
       TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]);
     }
 
-  return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0);
+  return INLINE_SYSCALL_RETURN (utimensat, 4, int, fd, NULL,
+				tvp ? &ts : NULL, 0);
 }
 weak_alias (__futimes, futimes)
diff --git a/sysdeps/unix/sysv/linux/futimesat.c b/sysdeps/unix/sysv/linux/futimesat.c
index 27d6870..76ccec7 100644
--- a/sysdeps/unix/sysv/linux/futimesat.c
+++ b/sysdeps/unix/sysv/linux/futimesat.c
@@ -34,5 +34,5 @@ futimesat (int fd, const char *file, const struct timeval tvp[2])
     return __futimes (fd, tvp);
 
   /* Avoid implicit array coercion in syscall macros.  */
-  return INLINE_SYSCALL (futimesat, 3, fd, file, &tvp[0]);
+  return INLINE_SYSCALL_RETURN (futimesat, 3, int, fd, file, &tvp[0]);
 }
diff --git a/sysdeps/unix/sysv/linux/fxstat.c b/sysdeps/unix/sysv/linux/fxstat.c
index 8d8c4e1..e81dc3f 100644
--- a/sysdeps/unix/sysv/linux/fxstat.c
+++ b/sysdeps/unix/sysv/linux/fxstat.c
@@ -36,20 +36,21 @@ int
 __fxstat (int vers, int fd, struct stat *buf)
 {
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (fstat, 2, fd, (struct kernel_stat *) buf);
+    return INLINE_SYSCALL_RETURN (fstat, 2, fd,
+				  (struct kernel_stat *) buf);
 
 #ifdef STAT_IS_KERNEL_STAT
-  errno = EINVAL;
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 #else
   struct kernel_stat kbuf;
-  int result;
-
-  result = INLINE_SYSCALL (fstat, 2, fd, &kbuf);
-  if (result == 0)
-    result = __xstat_conv (vers, &kbuf, buf);
-
-  return result;
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (fstat, err, 2, fd, &kbuf);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
+  else
+    return __xstat_conv (vers, &kbuf, buf);
 #endif
 }
 
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 7a0168d..97b06a8 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -31,8 +31,12 @@
 int
 ___fxstat64 (int vers, int fd, struct stat64 *buf)
 {
-  int result;
-  result = INLINE_SYSCALL (fstat64, 2, fd, buf);
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (fstat64, err, 2, fd, buf);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
 #if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0
   if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino)
     buf->st_ino = buf->__st_ino;
diff --git a/sysdeps/unix/sysv/linux/fxstatat.c b/sysdeps/unix/sysv/linux/fxstatat.c
index c88bcec..5259931 100644
--- a/sysdeps/unix/sysv/linux/fxstatat.c
+++ b/sysdeps/unix/sysv/linux/fxstatat.c
@@ -45,7 +45,11 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
 #endif
 
   result = INTERNAL_SYSCALL (newfstatat, err, 4, fd, file, &kst, flag);
-  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
+  else
     {
 #ifdef STAT_IS_KERNEL_STAT
       return 0;
@@ -53,11 +57,6 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
       return __xstat_conv (vers, &kst, st);
 #endif
     }
-  else
-    {
-      __set_errno (INTERNAL_SYSCALL_ERRNO (result, err));
-      return -1;
-    }
 }
 libc_hidden_def (__fxstatat)
 #ifdef XSTAT_IS_XSTAT64
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index a55cf1d..f4cd094 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -32,21 +32,17 @@ int
 __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
 {
   if (__glibc_unlikely (vers != _STAT_VER_LINUX))
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
   int result;
   INTERNAL_SYSCALL_DECL (err);
 
   result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag);
-  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
-    return 0;
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
   else
-    {
-      __set_errno (INTERNAL_SYSCALL_ERRNO (result, err));
-      return -1;
-    }
+    return 0;
 }
 libc_hidden_def (__fxstatat64)
diff --git a/sysdeps/unix/sysv/linux/gai_sigqueue.c b/sysdeps/unix/sysv/linux/gai_sigqueue.c
index 404dd68..fe4f36f 100644
--- a/sysdeps/unix/sysv/linux/gai_sigqueue.c
+++ b/sysdeps/unix/sysv/linux/gai_sigqueue.c
@@ -47,7 +47,8 @@ __gai_sigqueue (sig, val, caller_pid)
   info.si_uid = __getuid ();
   info.si_value = val;
 
-  return INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, sig, &info);
+  return INLINE_SYSCALL_RETURN (rt_sigqueueinfo, 3, int, info.si_pid,
+				sig, &info);
 }
 #else
 # include <resolv/gai_sigqueue.c>
diff --git a/sysdeps/unix/sysv/linux/getpriority.c b/sysdeps/unix/sysv/linux/getpriority.c
index 9c691bb..444995e 100644
--- a/sysdeps/unix/sysv/linux/getpriority.c
+++ b/sysdeps/unix/sysv/linux/getpriority.c
@@ -34,12 +34,14 @@
 int
 __getpriority (enum __priority_which which, id_t who)
 {
-  int res;
-
-  res = INLINE_SYSCALL (getpriority, 2, (int) which, who);
-  if (res >= 0)
-    res = PZERO - res;
-  return res;
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (getpriority, err, 2, (int) which, who);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (res,
+								 err),
+					int, -1);
+  else
+    return PZERO - res;
 }
 libc_hidden_def (__getpriority)
 weak_alias (__getpriority, getpriority)
diff --git a/sysdeps/unix/sysv/linux/getrlimit64.c b/sysdeps/unix/sysv/linux/getrlimit64.c
index 100ba62..b0c8533 100644
--- a/sysdeps/unix/sysv/linux/getrlimit64.c
+++ b/sysdeps/unix/sysv/linux/getrlimit64.c
@@ -27,11 +27,15 @@ int
 __getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
 {
 #ifdef __ASSUME_PRLIMIT64
-  return INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, rlimits);
+  return INLINE_SYSCALL_RETURN (prlimit64, 4, int, 0, resource,
+				NULL, rlimits);
 #else
 # ifdef __NR_prlimit64
-  int res = INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, rlimits);
-  if (res == 0 || errno != ENOSYS)
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (prlimit64, err, 4, 0, resource, NULL,
+			      rlimits);
+  if (!__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err))
+      || INTERNAL_SYSCALL_ERRNO (res, err) != ENOSYS)
     return res;
 # endif
   struct rlimit rlimits32;
diff --git a/sysdeps/unix/sysv/linux/llseek.c b/sysdeps/unix/sysv/linux/llseek.c
index 80ac5e6..116e55b 100644
--- a/sysdeps/unix/sysv/linux/llseek.c
+++ b/sysdeps/unix/sysv/linux/llseek.c
@@ -29,10 +29,17 @@ loff_t
 __llseek (int fd, loff_t offset, int whence)
 {
   loff_t retval;
-
-  return (loff_t) (INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32),
-				   (off_t) (offset & 0xffffffff),
-				   &retval, whence) ?: retval);
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (_llseek, err, 5, fd,
+				 (off_t) (offset >> 32),
+				 (off_t) (offset & 0xffffffff),
+				 &retval, whence);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					loff_t, -1);
+  else
+    return retval;
 }
 weak_alias (__llseek, llseek)
 strong_alias (__llseek, __libc_lseek64)
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 9e51305..3597c18 100644
--- a/sysdeps/unix/sysv/linux/lutimes.c
+++ b/sysdeps/unix/sysv/linux/lutimes.c
@@ -34,20 +34,16 @@ lutimes (const char *file, const struct timeval tvp[2])
     {
       if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
           || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
-	{
-	  __set_errno (EINVAL);
-	  return -1;
-	}
+	return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
       TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]);
       TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]);
     }
 
-  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL,
-			 AT_SYMLINK_NOFOLLOW);
+  return INLINE_SYSCALL_RETURN (utimensat, 4, int, AT_FDCWD, file,
+				tvp ? ts : NULL, AT_SYMLINK_NOFOLLOW);
 #else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 #endif
 }
 
diff --git a/sysdeps/unix/sysv/linux/lxstat.c b/sysdeps/unix/sysv/linux/lxstat.c
index 948665c..ae3f33c 100644
--- a/sysdeps/unix/sysv/linux/lxstat.c
+++ b/sysdeps/unix/sysv/linux/lxstat.c
@@ -35,20 +35,21 @@ int
 __lxstat (int vers, const char *name, struct stat *buf)
 {
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (lstat, 2, name, (struct kernel_stat *) buf);
+    return INLINE_SYSCALL_ERROR_RETURN (lstat, 2, int, name,
+					(struct kernel_stat *) buf);
 
 #ifdef STAT_IS_KERNEL_STAT
-  errno = EINVAL;
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1)
 #else
   struct kernel_stat kbuf;
-  int result;
-
-  result = INLINE_SYSCALL (lstat, 2, name, &kbuf);
-  if (result == 0)
-    result = __xstat_conv (vers, &kbuf, buf);
-
-  return result;
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (lstat, err, 2, name, &kbuf);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1)
+  else
+    return __xstat_conv (vers, &kbuf, buf);
 #endif
 }
 
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 5d0c051..5b4d806 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -30,8 +30,12 @@
 int
 ___lxstat64 (int vers, const char *name, struct stat64 *buf)
 {
-  int result;
-  result = INLINE_SYSCALL (lstat64, 2, name, buf);
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (lstat64, err, 2, name, buf);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
 #if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0
   if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino)
     buf->st_ino = buf->__st_ino;
diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c
index 0b160b6..4dbe28b 100644
--- a/sysdeps/unix/sysv/linux/mmap64.c
+++ b/sysdeps/unix/sysv/linux/mmap64.c
@@ -46,15 +46,9 @@ __mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
     }
 #endif
   if (offset & ((1 << page_shift) - 1))
-    {
-      __set_errno (EINVAL);
-      return MAP_FAILED;
-    }
-  void *result;
-  result = (void *)
-    INLINE_SYSCALL (mmap2, 6, addr,
-		    len, prot, flags, fd,
-		    (off_t) (offset >> page_shift));
-  return result;
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, void *, MAP_FAILED);
+  return INLINE_SYSCALL_RETURN (mmap2, 6, void *, addr,
+				len, prot, flags, fd,
+				(off_t) (offset >> page_shift));
 }
 weak_alias (__mmap64, mmap64)
diff --git a/sysdeps/unix/sysv/linux/mq_close.c b/sysdeps/unix/sysv/linux/mq_close.c
index 58d5aea..1d5b664 100644
--- a/sysdeps/unix/sysv/linux/mq_close.c
+++ b/sysdeps/unix/sysv/linux/mq_close.c
@@ -26,7 +26,7 @@
 int
 mq_close (mqd_t mqdes)
 {
-  return INLINE_SYSCALL (close, 1, mqdes);
+  return INLINE_SYSCALL_RETURN (close, 1, int, mqdes);
 }
 
 #else
diff --git a/sysdeps/unix/sysv/linux/mq_open.c b/sysdeps/unix/sysv/linux/mq_open.c
index 46c0cc8..ecadd08 100644
--- a/sysdeps/unix/sysv/linux/mq_open.c
+++ b/sysdeps/unix/sysv/linux/mq_open.c
@@ -35,10 +35,7 @@ mqd_t
 __mq_open (const char *name, int oflag, ...)
 {
   if (name[0] != '/')
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
   mode_t mode = 0;
   struct mq_attr *attr = NULL;
@@ -52,7 +49,8 @@ __mq_open (const char *name, int oflag, ...)
       va_end (ap);
     }
 
-  return INLINE_SYSCALL (mq_open, 4, name + 1, oflag, mode, attr);
+  return INLINE_SYSCALL_RETURN (mq_open, 4, int, name + 1, oflag, mode,
+				attr);
 }
 strong_alias (__mq_open, mq_open);
 
diff --git a/sysdeps/unix/sysv/linux/mq_unlink.c b/sysdeps/unix/sysv/linux/mq_unlink.c
index a876c3c..0b133d1 100644
--- a/sysdeps/unix/sysv/linux/mq_unlink.c
+++ b/sysdeps/unix/sysv/linux/mq_unlink.c
@@ -26,10 +26,7 @@ int
 mq_unlink (const char *name)
 {
   if (name[0] != '/')
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
   INTERNAL_SYSCALL_DECL (err);
   int ret = INTERNAL_SYSCALL (mq_unlink, err, 1, name + 1);
@@ -41,8 +38,7 @@ mq_unlink (const char *name)
       ret = INTERNAL_SYSCALL_ERRNO (ret, err);
       if (ret == EPERM)
 	ret = EACCES;
-      __set_errno (ret);
-      ret = -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-ret, int, -1);
     }
 
   return ret;
diff --git a/sysdeps/unix/sysv/linux/msgget.c b/sysdeps/unix/sysv/linux/msgget.c
index ca8932c..fdc4796 100644
--- a/sysdeps/unix/sysv/linux/msgget.c
+++ b/sysdeps/unix/sysv/linux/msgget.c
@@ -32,5 +32,6 @@ msgget (key, msgflg)
      key_t key;
      int msgflg;
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_msgget, key, msgflg, 0, NULL);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_msgget, key, msgflg,
+				0, NULL);
 }
diff --git a/sysdeps/unix/sysv/linux/prlimit.c b/sysdeps/unix/sysv/linux/prlimit.c
index db88ba8..ad164c4 100644
--- a/sysdeps/unix/sysv/linux/prlimit.c
+++ b/sysdeps/unix/sysv/linux/prlimit.c
@@ -44,10 +44,15 @@ prlimit (__pid_t pid, enum __rlimit_resource resource,
       new_rlimit64 = &new_rlimit64_mem;
     }
 
-  int res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64,
-			    old_rlimit64);
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (prlimit64, err, 4, pid, resource,
+			      new_rlimit64, old_rlimit64);
 
-  if (res == 0 && old_rlimit != NULL)
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (res,
+								 err),
+					int, -1);
+  else if (old_rlimit != NULL)
     {
       /* The prlimit64 syscall is ill-designed for 32-bit machines.
 	 We have to provide a 32-bit variant since otherwise the LFS
@@ -59,20 +64,14 @@ prlimit (__pid_t pid, enum __rlimit_resource resource,
       if (old_rlimit->rlim_cur != old_rlimit64_mem.rlim_cur)
 	{
 	  if (new_rlimit == NULL)
-	    {
-	      __set_errno (EOVERFLOW);
-	      return -1;
-	    }
+	    return INLINE_SYSCALL_ERROR_RETURN (-EOVERFLOW, int, -1);
 	  old_rlimit->rlim_cur = RLIM_INFINITY;
 	}
       old_rlimit->rlim_max = old_rlimit64_mem.rlim_max;
       if (old_rlimit->rlim_max != old_rlimit64_mem.rlim_max)
 	{
 	  if (new_rlimit == NULL)
-	    {
-	      __set_errno (EOVERFLOW);
-	      return -1;
-	    }
+	    return INLINE_SYSCALL_ERROR_RETURN (-EOVERFLOW, int, -1);
 	  old_rlimit->rlim_max = RLIM_INFINITY;
 	}
     }
@@ -84,8 +83,7 @@ int
 prlimit (__pid_t pid, enum __rlimit_resource resource,
 	 const struct rlimit *new_rlimit, struct rlimit *old_rlimit)
 {
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 }
 stub_warning (prlimit)
 #endif
diff --git a/sysdeps/unix/sysv/linux/pt-raise.c b/sysdeps/unix/sysv/linux/pt-raise.c
index 307b9dc..1e14439 100644
--- a/sysdeps/unix/sysv/linux/pt-raise.c
+++ b/sysdeps/unix/sysv/linux/pt-raise.c
@@ -33,6 +33,6 @@ raise (sig)
   if (__glibc_unlikely (pid < 0))
     pid = -pid;
 
-  return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid),
-			 sig);
+  return INLINE_SYSCALL_RETURN (tgkill, 3, int, pid,
+				THREAD_GETMEM (THREAD_SELF, tid), sig);
 }
diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c
index e281063..2e6bb6b 100644
--- a/sysdeps/unix/sysv/linux/raise.c
+++ b/sysdeps/unix/sysv/linux/raise.c
@@ -52,7 +52,7 @@ raise (sig)
     if (__glibc_unlikely (pid <= 0))
       pid = (pid & INT_MAX) == 0 ? selftid : -pid;
 
-  return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
+  return INLINE_SYSCALL_RETURN (tgkill, 3, int, pid, selftid, sig);
 }
 libc_hidden_def (raise)
 weak_alias (raise, gsignal)
diff --git a/sysdeps/unix/sysv/linux/readahead.c b/sysdeps/unix/sysv/linux/readahead.c
index c47df0d..0c3e585 100644
--- a/sysdeps/unix/sysv/linux/readahead.c
+++ b/sysdeps/unix/sysv/linux/readahead.c
@@ -29,17 +29,16 @@
 ssize_t
 __readahead (int fd, off64_t offset, size_t count)
 {
-  return INLINE_SYSCALL (readahead, 4, fd,
-			 __LONG_LONG_PAIR ((off_t) (offset >> 32),
-					   (off_t) (offset & 0xffffffff)),
-			 count);
+  return INLINE_SYSCALL_RETURN (readahead, 4, int, fd,
+				__LONG_LONG_PAIR ((off_t) (offset >> 32),
+						  (off_t) (offset & 0xffffffff)),
+			      count);
 }
 #else
 ssize_t
 __readahead (int fd, off64_t offset, size_t count)
 {
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 }
 stub_warning (readahead)
 #endif
diff --git a/sysdeps/unix/sysv/linux/reboot.c b/sysdeps/unix/sysv/linux/reboot.c
index a016321..e525245 100644
--- a/sysdeps/unix/sysv/linux/reboot.c
+++ b/sysdeps/unix/sysv/linux/reboot.c
@@ -25,5 +25,6 @@
 int
 reboot (int howto)
 {
-  return INLINE_SYSCALL (reboot, 3, (int) 0xfee1dead, 672274793, howto);
+  return INLINE_SYSCALL_RETURN (reboot, 3, int, (int) 0xfee1dead,
+				672274793, howto);
 }
diff --git a/sysdeps/unix/sysv/linux/sched_getaffinity.c b/sysdeps/unix/sysv/linux/sched_getaffinity.c
index 9850806..d66b6fa 100644
--- a/sysdeps/unix/sysv/linux/sched_getaffinity.c
+++ b/sysdeps/unix/sysv/linux/sched_getaffinity.c
@@ -25,12 +25,22 @@
 
 
 #ifdef __NR_sched_getaffinity
+# if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
+extern int __sched_getaffinity_new (pid_t, size_t, cpu_set_t *);
+libc_hidden_proto (__sched_getaffinity_new)
+# endif
+
 int
 __sched_getaffinity_new (pid_t pid, size_t cpusetsize, cpu_set_t *cpuset)
 {
-  int res = INLINE_SYSCALL (sched_getaffinity, 3, pid,
-			    MIN (INT_MAX, cpusetsize), cpuset);
-  if (res != -1)
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, pid,
+			      MIN (INT_MAX, cpusetsize), cpuset);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (res,
+								 err),
+					int, -1);
+  else
     {
       /* Clean the rest of the memory the kernel didn't do.  */
       memset ((char *) cpuset + res, '\0', cpusetsize - res);
@@ -44,6 +54,8 @@ versioned_symbol (libc, __sched_getaffinity_new, sched_getaffinity,
 
 
 # if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
+libc_hidden_def (__sched_getaffinity_new)
+
 int
 attribute_compat_text_section
 __sched_getaffinity_old (pid_t pid, cpu_set_t *cpuset)
diff --git a/sysdeps/unix/sysv/linux/semget.c b/sysdeps/unix/sysv/linux/semget.c
index 7221ff2..c75835d 100644
--- a/sysdeps/unix/sysv/linux/semget.c
+++ b/sysdeps/unix/sysv/linux/semget.c
@@ -33,5 +33,6 @@ semget (key, nsems, semflg)
      int nsems;
      int semflg;
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_semget, key, nsems, semflg, NULL);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_semget, key, nsems,
+				semflg, NULL);
 }
diff --git a/sysdeps/unix/sysv/linux/semop.c b/sysdeps/unix/sysv/linux/semop.c
index dc936be..b40014c 100644
--- a/sysdeps/unix/sysv/linux/semop.c
+++ b/sysdeps/unix/sysv/linux/semop.c
@@ -31,5 +31,6 @@ semop (semid, sops, nsops)
      struct sembuf *sops;
      size_t nsops;
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_semop, semid, (int) nsops, 0, sops);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_semop, semid,
+				(int) nsops, 0, sops);
 }
diff --git a/sysdeps/unix/sysv/linux/semtimedop.c b/sysdeps/unix/sysv/linux/semtimedop.c
index 02df07e..57e7485 100644
--- a/sysdeps/unix/sysv/linux/semtimedop.c
+++ b/sysdeps/unix/sysv/linux/semtimedop.c
@@ -32,7 +32,6 @@ semtimedop (semid, sops, nsops, timeout)
      size_t nsops;
      const struct timespec *timeout;
 {
-  return INLINE_SYSCALL (ipc, 6, IPCOP_semtimedop,
-			 semid, (int) nsops, 0, sops,
-			 timeout);
+  return INLINE_SYSCALL_RETURN (ipc, 6, int, IPCOP_semtimedop, semid,
+				(int) nsops, 0, sops, timeout);
 }
diff --git a/sysdeps/unix/sysv/linux/setrlimit64.c b/sysdeps/unix/sysv/linux/setrlimit64.c
index 17f95cb..1989af6 100644
--- a/sysdeps/unix/sysv/linux/setrlimit64.c
+++ b/sysdeps/unix/sysv/linux/setrlimit64.c
@@ -30,11 +30,15 @@ setrlimit64 (resource, rlimits)
      const struct rlimit64 *rlimits;
 {
 #ifdef __ASSUME_PRLIMIT64
-  return INLINE_SYSCALL (prlimit64, 4, 0, resource, rlimits, NULL);
+  return INLINE_SYSCALL_RETURN (prlimit64, 4, int, 0, resource,
+				rlimits, NULL);
 #else
 # ifdef __NR_prlimit64
-  int res = INLINE_SYSCALL (prlimit64, 4, 0, resource, rlimits, NULL);
-  if (res == 0 || errno != ENOSYS)
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (prlimit64, err, 4, 0, resource, rlimits,
+			      NULL);
+  if (!__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err))
+      || INTERNAL_SYSCALL_ERRNO (res, err) != ENOSYS)
     return res;
 # endif
   struct rlimit rlimits32;
diff --git a/sysdeps/unix/sysv/linux/shmat.c b/sysdeps/unix/sysv/linux/shmat.c
index 94d18d3..45ebd11 100644
--- a/sysdeps/unix/sysv/linux/shmat.c
+++ b/sysdeps/unix/sysv/linux/shmat.c
@@ -42,11 +42,10 @@ shmat (shmid, shmaddr, shmflg)
 				shmid, shmflg,
 				(long int) &raddr,
 				(void *) shmaddr);
-  if (INTERNAL_SYSCALL_ERROR_P (resultvar, err))
-    {
-      __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, err));
-      return (void *) -1l;
-    }
-
-  return raddr;
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (resultvar,
+								 err),
+					void *, -1l);
+  else
+    return raddr;
 }
diff --git a/sysdeps/unix/sysv/linux/shmdt.c b/sysdeps/unix/sysv/linux/shmdt.c
index 51bad71..0bb6370 100644
--- a/sysdeps/unix/sysv/linux/shmdt.c
+++ b/sysdeps/unix/sysv/linux/shmdt.c
@@ -30,5 +30,6 @@ int
 shmdt (shmaddr)
      const void *shmaddr;
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_shmdt, 0, 0, 0, (void *) shmaddr);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_shmdt, 0, 0, 0,
+				(void *) shmaddr);
 }
diff --git a/sysdeps/unix/sysv/linux/shmget.c b/sysdeps/unix/sysv/linux/shmget.c
index b3d74e6..c9720f4 100644
--- a/sysdeps/unix/sysv/linux/shmget.c
+++ b/sysdeps/unix/sysv/linux/shmget.c
@@ -33,5 +33,6 @@ shmget (key, size, shmflg)
      size_t size;
      int shmflg;
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_shmget, key, size, shmflg, NULL);
+  return INLINE_SYSCALL_RETURN (ipc, 5, int, IPCOP_shmget, key, size,
+				shmflg, NULL);
 }
diff --git a/sysdeps/unix/sysv/linux/signalfd.c b/sysdeps/unix/sysv/linux/signalfd.c
index f3ae8c1..e07b56c 100644
--- a/sysdeps/unix/sysv/linux/signalfd.c
+++ b/sysdeps/unix/sysv/linux/signalfd.c
@@ -26,11 +26,17 @@ int
 signalfd (int fd, const sigset_t *mask, int flags)
 {
 #ifdef __NR_signalfd4
-  int res = INLINE_SYSCALL (signalfd4, 4, fd, mask, _NSIG / 8, flags);
 # ifndef __ASSUME_SIGNALFD4
-  if (res != -1 || errno != ENOSYS)
-# endif
+  INTERNAL_SYSCALL_DECL (err);
+  int res = INTERNAL_SYSCALL (signalfd4, err, 4, fd, mask, _NSIG / 8,
+			      flags);
+  if (!__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err))
+      || INTERNAL_SYSCALL_ERRNO (res, err) != ENOSYS)
     return res;
+# else
+  return INLINE_SYSCALL_RETURN (signalfd4, 4, int, fd, mask, _NSIG / 8,
+				flags);
+# endif
 #endif
 
 #ifndef __ASSUME_SIGNALFD4
@@ -39,16 +45,12 @@ signalfd (int fd, const sigset_t *mask, int flags)
      kernel (sys_indirect) before implementing setting flags like
      O_NONBLOCK etc.  */
   if (flags != 0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
 # ifdef __NR_signalfd
-  return INLINE_SYSCALL (signalfd, 3, fd, mask, _NSIG / 8);
+  return INLINE_SYSCALL_RETURN (signalfd, 3, int, fd, mask, _NSIG / 8);
 # else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 # endif
 #elif !defined __NR_signalfd4
 # error "__ASSUME_SIGNALFD4 defined but not __NR_signalfd4"
diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c
index c8f3a8e..4ad0982 100644
--- a/sysdeps/unix/sysv/linux/sigpending.c
+++ b/sysdeps/unix/sysv/linux/sigpending.c
@@ -29,5 +29,5 @@ int
 sigpending (set)
      sigset_t *set;
 {
-  return INLINE_SYSCALL (rt_sigpending, 2, set, _NSIG / 8);
+  return INLINE_SYSCALL_RETURN (rt_sigpending, 2, int, set, _NSIG / 8);
 }
diff --git a/sysdeps/unix/sysv/linux/sigprocmask.c b/sysdeps/unix/sysv/linux/sigprocmask.c
index 574f0d2..452f8a1 100644
--- a/sysdeps/unix/sysv/linux/sigprocmask.c
+++ b/sysdeps/unix/sysv/linux/sigprocmask.c
@@ -54,6 +54,7 @@ __sigprocmask (how, set, oset)
     }
 #endif
 
-  return INLINE_SYSCALL (rt_sigprocmask, 4, how, set, oset, _NSIG / 8);
+  return INLINE_SYSCALL_RETURN (rt_sigprocmask, 4, int, how, set, oset,
+				_NSIG / 8);
 }
 weak_alias (__sigprocmask, sigprocmask)
diff --git a/sysdeps/unix/sysv/linux/sigqueue.c b/sysdeps/unix/sysv/linux/sigqueue.c
index 7970a7c..9009174 100644
--- a/sysdeps/unix/sysv/linux/sigqueue.c
+++ b/sysdeps/unix/sysv/linux/sigqueue.c
@@ -43,7 +43,7 @@ __sigqueue (pid, sig, val)
   info.si_uid = __getuid ();
   info.si_value = val;
 
-  return INLINE_SYSCALL (rt_sigqueueinfo, 3, pid, sig, &info);
+  return INLINE_SYSCALL_RETURN (rt_sigqueueinfo, 3, int, pid, sig, &info);
 }
 weak_alias (__sigqueue, sigqueue)
 #else
diff --git a/sysdeps/unix/sysv/linux/speed.c b/sysdeps/unix/sysv/linux/speed.c
index 3ac0640..2ed9f15 100644
--- a/sysdeps/unix/sysv/linux/speed.c
+++ b/sysdeps/unix/sysv/linux/speed.c
@@ -60,10 +60,7 @@ cfsetospeed  (termios_p, speed)
 {
   if ((speed & ~CBAUD) != 0
       && (speed < B57600 || speed > __MAX_BAUD))
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
 #ifdef _HAVE_STRUCT_TERMIOS_C_OSPEED
   termios_p->c_ospeed = speed;
@@ -87,10 +84,7 @@ cfsetispeed (termios_p, speed)
 {
   if ((speed & ~CBAUD) != 0
       && (speed < B57600 || speed > __MAX_BAUD))
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
 #ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED
   termios_p->c_ispeed = speed;
diff --git a/sysdeps/unix/sysv/linux/statfs64.c b/sysdeps/unix/sysv/linux/statfs64.c
index ac5c33f..0d9e16c 100644
--- a/sysdeps/unix/sysv/linux/statfs64.c
+++ b/sysdeps/unix/sysv/linux/statfs64.c
@@ -37,12 +37,18 @@ __statfs64 (const char *file, struct statfs64 *buf)
   if (! __no_statfs64)
 # endif
     {
-      int result = INLINE_SYSCALL (statfs64, 3, file, sizeof (*buf), buf);
-
 # if __ASSUME_STATFS64 == 0
-      if (result == 0 || errno != ENOSYS)
-# endif
+      INTERNAL_SYSCALL_DECL (err);
+      int result = INTERNAL_SYSCALL (statfs64, err, 3, file,
+				     sizeof (*buf), buf);
+
+      if (!__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))
+	  || INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
 	return result;
+# else
+      return INLINE_SYSCALL_RETURN (statfs64, 3, int, file,
+				    sizeof (*buf), buf);
+# endif
 
 # if __ASSUME_STATFS64 == 0
       __no_statfs64 = 1;
diff --git a/sysdeps/unix/sysv/linux/sysctl.c b/sysdeps/unix/sysv/linux/sysctl.c
index 2d4eb1d..d0fe55c 100644
--- a/sysdeps/unix/sysv/linux/sysctl.c
+++ b/sysdeps/unix/sysv/linux/sysctl.c
@@ -37,7 +37,7 @@ __sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
     .newlen = newlen
   };
 
-  return INLINE_SYSCALL (_sysctl, 1, &args);
+  return INLINE_SYSCALL_RETURN (_sysctl, 1, int, &args);
 }
 libc_hidden_def (__sysctl)
 weak_alias (__sysctl, sysctl)
diff --git a/sysdeps/unix/sysv/linux/tcsendbrk.c b/sysdeps/unix/sysv/linux/tcsendbrk.c
index 4a43209..508efbb 100644
--- a/sysdeps/unix/sysv/linux/tcsendbrk.c
+++ b/sysdeps/unix/sysv/linux/tcsendbrk.c
@@ -39,7 +39,6 @@ tcsendbreak (int fd, int duration)
   /* ioctl can't send a break of any other duration for us.
      This could be changed to use trickery (e.g. lower speed and
      send a '\0') to send the break, but for now just return an error.  */
-  __set_errno (EINVAL);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 #endif
 }
diff --git a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c
index d7afc63..96f7287 100644
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
@@ -61,8 +61,7 @@ tcsetattr (fd, optional_actions, termios_p)
       cmd = TCSETSF;
       break;
     default:
-      __set_errno (EINVAL);
-      return -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
     }
 
   k_termios.c_iflag = termios_p->c_iflag & ~IBAUD0;
@@ -79,6 +78,6 @@ tcsetattr (fd, optional_actions, termios_p)
   memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
 	  __KERNEL_NCCS * sizeof (cc_t));
 
-  return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
+  return INLINE_SYSCALL_RETURN (ioctl, 3, int, fd, cmd, &k_termios);
 }
 libc_hidden_def (tcsetattr)
diff --git a/sysdeps/unix/sysv/linux/timer_getoverr.c b/sysdeps/unix/sysv/linux/timer_getoverr.c
index 8f00192..2bcac79 100644
--- a/sysdeps/unix/sysv/linux/timer_getoverr.c
+++ b/sysdeps/unix/sysv/linux/timer_getoverr.c
@@ -35,7 +35,5 @@ timer_getoverrun (timerid)
   struct timer *kt = (struct timer *) timerid;
 
   /* Get the information from the kernel.  */
-  int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid);
-
-  return res;
+  return INLINE_SYSCALL_RETURN (timer_getoverrun, 1, int, kt->ktimerid);
 }
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 79705cf..e9ca59a 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -37,7 +37,6 @@ timer_gettime (timerid, value)
   struct timer *kt = (struct timer *) timerid;
 
   /* Delete the kernel timer object.  */
-  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
-
-  return res;
+  return INLINE_SYSCALL_RETURN (timer_gettime, 2, int, kt->ktimerid,
+				value);
 }
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index 87c6519..d8687fd 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -39,8 +39,6 @@ timer_settime (timerid, flags, value, ovalue)
   struct timer *kt = (struct timer *) timerid;
 
   /* Delete the kernel timer object.  */
-  int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
-			    value, ovalue);
-
-  return res;
+  return INLINE_SYSCALL_RETURN (timer_settime, 4, int, kt->ktimerid,
+				flags, value, ovalue);
 }
diff --git a/sysdeps/unix/sysv/linux/truncate64.c b/sysdeps/unix/sysv/linux/truncate64.c
index 0002247..d4500b1 100644
--- a/sysdeps/unix/sysv/linux/truncate64.c
+++ b/sysdeps/unix/sysv/linux/truncate64.c
@@ -29,7 +29,6 @@ truncate64 (const char *path, off64_t length)
 {
   unsigned int low = length & 0xffffffff;
   unsigned int high = length >> 32;
-  int result = INLINE_SYSCALL (truncate64, 3, path,
-			       __LONG_LONG_PAIR (high, low));
-  return result;
+  return INLINE_SYSCALL_RETURN (truncate64, 3, int, path,
+				__LONG_LONG_PAIR (high, low));
 }
diff --git a/sysdeps/unix/sysv/linux/ustat.c b/sysdeps/unix/sysv/linux/ustat.c
index 8d495ca..1d78c20 100644
--- a/sysdeps/unix/sysv/linux/ustat.c
+++ b/sysdeps/unix/sysv/linux/ustat.c
@@ -31,10 +31,8 @@ ustat (dev_t dev, struct ustat *ubuf)
   /* We must convert the value to dev_t type used by the kernel.  */
   k_dev =  dev & ((1ULL << 32) - 1);
   if (k_dev != dev)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
-  return INLINE_SYSCALL (ustat, 2, (unsigned int) k_dev, ubuf);
+  return INLINE_SYSCALL_RETURN (ustat, 2, int, (unsigned int) k_dev,
+				ubuf);
 }
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 81b565f..9b645a1 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -30,16 +30,13 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
 	   int flags)
 {
   if (file == NULL)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 #ifdef __NR_utimensat
   /* Avoid implicit array coercion in syscall macros.  */
-  return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags);
+  return INLINE_SYSCALL_RETURN (utimensat, 4, int, fd, file, &tsp[0],
+				flags);
 #else
-  __set_errno (ENOSYS);
-  return -1;
+  return INLINE_SYSCALL_ERROR_RETURN (-ENOSYS, int, -1);
 #endif
 }
 #ifndef __NR_utimensat
diff --git a/sysdeps/unix/sysv/linux/utimes.c b/sysdeps/unix/sysv/linux/utimes.c
index 2a1f2f9..10b5593 100644
--- a/sysdeps/unix/sysv/linux/utimes.c
+++ b/sysdeps/unix/sysv/linux/utimes.c
@@ -30,7 +30,7 @@ int
 __utimes (const char *file, const struct timeval tvp[2])
 {
   /* Avoid implicit array coercion in syscall macros.  */
-  return INLINE_SYSCALL (utimes, 2, file, &tvp[0]);
+  return INLINE_SYSCALL_RETURN (utimes, 2, int, file, &tvp[0]);
 }
 
 weak_alias (__utimes, utimes)
diff --git a/sysdeps/unix/sysv/linux/xmknod.c b/sysdeps/unix/sysv/linux/xmknod.c
index b940273..92f714d 100644
--- a/sysdeps/unix/sysv/linux/xmknod.c
+++ b/sysdeps/unix/sysv/linux/xmknod.c
@@ -33,20 +33,15 @@ __xmknod (int vers, const char *path, mode_t mode, dev_t *dev)
   unsigned long long int k_dev;
 
   if (vers != _MKNOD_VER)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
   /* We must convert the value to dev_t type used by the kernel.  */
   k_dev =  (*dev) & ((1ULL << 32) - 1);
   if (k_dev != *dev)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
-  return INLINE_SYSCALL (mknod, 3, path, mode, (unsigned int) k_dev);
+  return INLINE_SYSCALL_RETURN (mknod, 3, int, path, mode,
+				(unsigned int) k_dev);
 }
 
 weak_alias (__xmknod, _xmknod)
diff --git a/sysdeps/unix/sysv/linux/xmknodat.c b/sysdeps/unix/sysv/linux/xmknodat.c
index f30b9b3..04ad458 100644
--- a/sysdeps/unix/sysv/linux/xmknodat.c
+++ b/sysdeps/unix/sysv/linux/xmknodat.c
@@ -34,20 +34,15 @@ int
 __xmknodat (int vers, int fd, const char *file, mode_t mode, dev_t *dev)
 {
   if (vers != _MKNOD_VER)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
   /* We must convert the value to dev_t type used by the kernel.  */
   unsigned long long int k_dev =  (*dev) & ((1ULL << 32) - 1);
   if (k_dev != *dev)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
+    return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
 
-  return INLINE_SYSCALL (mknodat, 4, fd, file, mode, (unsigned int) k_dev);
+  return INLINE_SYSCALL_RETURN (mknodat, 4, int, fd, file, mode,
+				(unsigned int) k_dev);
 }
 
 libc_hidden_def (__xmknodat)
diff --git a/sysdeps/unix/sysv/linux/xstat.c b/sysdeps/unix/sysv/linux/xstat.c
index 6218963..8734e0b 100644
--- a/sysdeps/unix/sysv/linux/xstat.c
+++ b/sysdeps/unix/sysv/linux/xstat.c
@@ -35,20 +35,22 @@ int
 __xstat (int vers, const char *name, struct stat *buf)
 {
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (stat, 2, name, (struct kernel_stat *) buf);
+    return INLINE_SYSCALL_RETURN (stat, 2, int, name,
+				  (struct kernel_stat *) buf);
 
 #ifdef STAT_IS_KERNEL_STAT
   errno = EINVAL;
   return -1;
 #else
   struct kernel_stat kbuf;
-  int result;
-
-  result = INLINE_SYSCALL (stat, 2, name, &kbuf);
-  if (result == 0)
-    result = __xstat_conv (vers, &kbuf, buf);
-
-  return result;
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (stat, err, 2, name, &kbuf);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
+  else
+    return __xstat_conv (vers, &kbuf, buf);
 #endif
 }
 hidden_def (__xstat)
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index c909b56..55ff8a1 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -31,8 +31,12 @@
 int
 ___xstat64 (int vers, const char *name, struct stat64 *buf)
 {
-  int result;
-  result = INLINE_SYSCALL (stat64, 2, name, buf);
+  INTERNAL_SYSCALL_DECL (err);
+  int result = INTERNAL_SYSCALL (stat64, err, 2, name, buf);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
+    return INLINE_SYSCALL_ERROR_RETURN (-INTERNAL_SYSCALL_ERRNO (result,
+								 err),
+					int, -1);
 #if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0
   if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino)
     buf->st_ino = buf->__st_ino;
diff --git a/sysdeps/unix/sysv/linux/xstatconv.c b/sysdeps/unix/sysv/linux/xstatconv.c
index 6504414..5aae78e 100644
--- a/sysdeps/unix/sysv/linux/xstatconv.c
+++ b/sysdeps/unix/sysv/linux/xstatconv.c
@@ -96,8 +96,7 @@ __xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
       break;
 
     default:
-      __set_errno (EINVAL);
-      return -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
     }
 
   return 0;
@@ -170,8 +169,7 @@ __xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
 	 _STAT_VER_KERNEL does not make sense.  */
     case _STAT_VER_KERNEL:
     default:
-      __set_errno (EINVAL);
-      return -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
     }
 
   return 0;
@@ -201,19 +199,13 @@ __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
 	    buf->st_ino = kbuf->st_ino;
 	    if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino)
 		&& buf->st_ino != kbuf->st_ino)
-	      {
-		__set_errno (EOVERFLOW);
-		return -1;
-	      }
+	      return INLINE_SYSCALL_ERROR_RETURN (-EOVERFLOW, int, -1);
 	  }
 #else
 	buf->st_ino = kbuf->st_ino;
 	if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino)
 	    && buf->st_ino != kbuf->st_ino)
-	  {
-	    __set_errno (EOVERFLOW);
-	    return -1;
-	  }
+	  return INLINE_SYSCALL_ERROR_RETURN (-EOVERFLOW, int, -1);
 #endif
 	buf->st_mode = kbuf->st_mode;
 	buf->st_nlink = kbuf->st_nlink;
@@ -227,19 +219,13 @@ __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
 	/* Check for overflow.  */
 	if (sizeof (buf->st_size) != sizeof (kbuf->st_size)
 	    && buf->st_size != kbuf->st_size)
-	  {
-	    __set_errno (EOVERFLOW);
-	    return -1;
-	  }
+	  return INLINE_SYSCALL_ERROR_RETURN (-EOVERFLOW, int, -1);
 	buf->st_blksize = kbuf->st_blksize;
 	buf->st_blocks = kbuf->st_blocks;
 	/* Check for overflow.  */
 	if (sizeof (buf->st_blocks) != sizeof (kbuf->st_blocks)
 	    && buf->st_blocks != kbuf->st_blocks)
-	  {
-	    __set_errno (EOVERFLOW);
-	    return -1;
-	  }
+	  return INLINE_SYSCALL_ERROR_RETURN (-EOVERFLOW, int, -1);
 #ifdef _HAVE_STAT_NSEC
 	buf->st_atim.tv_sec = kbuf->st_atim.tv_sec;
 	buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec;
@@ -275,8 +261,7 @@ __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
 	 _STAT_VER_KERNEL does not make sense.  */
     case _STAT_VER_KERNEL:
     default:
-      __set_errno (EINVAL);
-      return -1;
+      return INLINE_SYSCALL_ERROR_RETURN (-EINVAL, int, -1);
     }
 
   return 0;

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]