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/master created. glibc-2.22-377-gaa65e03


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/master has been created
        at  aa65e03df89596fef1d249573779692681f638a6 (commit)

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

commit aa65e03df89596fef1d249573779692681f638a6
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:	shr    $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>
    
    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 & (MMAP_PAGE_UNIT - 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..6be8692
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/mmap.c
@@ -0,0 +1,36 @@
+/* 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_UNIT
+# define MMAP_PAGE_UNIT 4096UL
+#endif
+
+__ptr_t
+__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+  if (offset & (MMAP_PAGE_UNIT - 1))
+    return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+  return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
+                                   offset / MMAP_PAGE_UNIT);
+}
+
+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=6e19182262fd3f658fd3ae72346e040565a7abd8

commit 6e19182262fd3f658fd3ae72346e040565a7abd8
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Sep 14 07:13:04 2015 -0700

    Optimize i386 syscall inlining
    
    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/libc-do-syscall.S
    	(__libc_do_syscall): Defined only if !__GNUC_PREREQ (5,0).
    	* sysdeps/unix/sysv/linux/i386/sysdep.h: Define assembler macros
    	only if !__GNUC_PREREQ (5,0).
    	(INTERNAL_SYSCALL_MAIN_6): Optimize for GCC 5.
    	(INTERNAL_SYSCALL_MAIN_INLINE): Likewise.
    	(INTERNAL_SYSCALL_NCS): Likewise.
    	(LOADREGS_0): New macro for GCC 5.
    	(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.

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/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index 3cf927a..5324da6 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -227,6 +227,7 @@
 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"
@@ -266,6 +267,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.  */
@@ -322,8 +324,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),							\
@@ -336,14 +342,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							      \
@@ -353,7 +397,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							      \
@@ -365,8 +409,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							      \
@@ -375,7 +419,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							      \
@@ -386,9 +430,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							      \
@@ -397,7 +459,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							      \
@@ -408,6 +470,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
@@ -472,6 +535,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) \

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

commit 071910adb29c9c7fb76261b163d2679f1591b0fe
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Aug 21 14:46:05 2015 -0700

    Avoid reading errno in syscall implementations
    
    Reading errno is expensive for x86 PIC.  With INTERNAL_SYSCALL,
    INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO and
    INLINE_SYSCALL_ERROR_RETURN_VALUE, we can avoid reading errno.
    
    	* sysdeps/unix/sysv/linux/eventfd.c (eventfd): Use
    	INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P and
    	INTERNAL_SYSCALL_ERRNO to avoid reading errno.
    	* sysdeps/unix/sysv/linux/fstatfs64.c (__fstatfs64): Likewise.
    	* sysdeps/unix/sysv/linux/getrlimit64.c (__getrlimit64):
    	Likewise.
    	* sysdeps/unix/sysv/linux/setrlimit64.c (setrlimit64):
    	Likewise.
    	* sysdeps/unix/sysv/linux/signalfd.c (signalfd): Likewise.
    	* sysdeps/unix/sysv/linux/statfs64.c (__statfs64): Likewise.

diff --git a/sysdeps/unix/sysv/linux/eventfd.c b/sysdeps/unix/sysv/linux/eventfd.c
index efce282..a13be32 100644
--- a/sysdeps/unix/sysv/linux/eventfd.c
+++ b/sysdeps/unix/sysv/linux/eventfd.c
@@ -25,11 +25,15 @@ 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;
+# else
+  return INLINE_SYSCALL (eventfd2, 2, count, flags);
+# endif
 #endif
 
 #ifndef __ASSUME_EVENTFD2
diff --git a/sysdeps/unix/sysv/linux/fstatfs64.c b/sysdeps/unix/sysv/linux/fstatfs64.c
index af83830..eb21d42 100644
--- a/sysdeps/unix/sysv/linux/fstatfs64.c
+++ b/sysdeps/unix/sysv/linux/fstatfs64.c
@@ -35,12 +35,16 @@ __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 (fstatfs64, 3, fd, sizeof (*buf), buf);
+# endif
 
 # if __ASSUME_STATFS64 == 0
       __no_statfs64 = 1;
diff --git a/sysdeps/unix/sysv/linux/getrlimit64.c b/sysdeps/unix/sysv/linux/getrlimit64.c
index 100ba62..cca1265 100644
--- a/sysdeps/unix/sysv/linux/getrlimit64.c
+++ b/sysdeps/unix/sysv/linux/getrlimit64.c
@@ -30,8 +30,11 @@ __getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
   return INLINE_SYSCALL (prlimit64, 4, 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/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 5d0c051..63959cf 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -30,8 +30,11 @@
 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_VALUE (INTERNAL_SYSCALL_ERRNO (result,
+								      err));
 #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/setrlimit64.c b/sysdeps/unix/sysv/linux/setrlimit64.c
index 17f95cb..33e1500 100644
--- a/sysdeps/unix/sysv/linux/setrlimit64.c
+++ b/sysdeps/unix/sysv/linux/setrlimit64.c
@@ -33,8 +33,11 @@ setrlimit64 (resource, rlimits)
   return INLINE_SYSCALL (prlimit64, 4, 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/signalfd.c b/sysdeps/unix/sysv/linux/signalfd.c
index 8573450..d58edc7 100644
--- a/sysdeps/unix/sysv/linux/signalfd.c
+++ b/sysdeps/unix/sysv/linux/signalfd.c
@@ -26,11 +26,16 @@ 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 (signalfd4, 4, fd, mask, _NSIG / 8, flags);
+# endif
 #endif
 
 #ifndef __ASSUME_SIGNALFD4
diff --git a/sysdeps/unix/sysv/linux/statfs64.c b/sysdeps/unix/sysv/linux/statfs64.c
index ac5c33f..fdd1667 100644
--- a/sysdeps/unix/sysv/linux/statfs64.c
+++ b/sysdeps/unix/sysv/linux/statfs64.c
@@ -37,12 +37,17 @@ __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 (statfs64, 3, file, sizeof (*buf), buf);
+# endif
 
 # if __ASSUME_STATFS64 == 0
       __no_statfs64 = 1;

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


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]