aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-10-13 11:58:53 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-10-13 11:59:15 -0700
commitfb1cf108115f7e2e4510859693431b3473657d77 (patch)
tree5c1579a854a37ac677b5647273ce5fccba600e4a /sysdeps/unix
parent0a5768fe9c2e2870269c3a0920f88d9c22d73e33 (diff)
downloadglibc-fb1cf108115f7e2e4510859693431b3473657d77.tar
glibc-fb1cf108115f7e2e4510859693431b3473657d77.tar.gz
glibc-fb1cf108115f7e2e4510859693431b3473657d77.tar.bz2
glibc-fb1cf108115f7e2e4510859693431b3473657d77.zip
Add INLINE_SYSCALL_ERROR_RETURN_VALUE
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_ERROR_RETURN_VALUE so that i386 can optimize setting errno by branching to the internal __syscall_error without PLT. With i386 INLINE_SYSCALL_ERROR_RETURN_VALUE 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/sysv/linux/sysdep.h: New file. * sysdeps/unix/sysv/linux/i386/sysdep.c: Likewise. * sysdeps/unix/sysv/linux/alpha/sysdep.h: Include <sysdeps/unix/sysv/linux/sysdep.h>. * sysdeps/unix/sysv/linux/arm/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/generic/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/hppa/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/ia64/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/m68k/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/microblaze/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/sh/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/sparc/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise. * 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/clone.S (__clone): Don't check PIC when branching to SYSCALL_ERROR_LABEL. * sysdeps/unix/sysv/linux/i386/sysdep.S: Removed. * sysdeps/unix/sysv/linux/i386/sysdep.h: Include <sysdeps/unix/sysv/linux/sysdep.h>. (SYSCALL_ERROR_LABEL): Changed to __syscall_error. (SYSCALL_ERROR_ERRNO): Removed. (SYSCALL_ERROR_HANDLER): Changed to empty. (SYSCALL_ERROR_HANDLER_TLS_STORE): Likewise. (__syscall_error): New prototype. [IS_IN (libc)] (INLINE_SYSCALL): New macro. (INLINE_SYSCALL_ERROR_RETURN_VALUE): Likewise.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/alpha/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/arm/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/generic/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/hppa/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/i386/Makefile14
-rw-r--r--sysdeps/unix/sysv/linux/i386/clone.S8
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.c (renamed from sysdeps/unix/sysv/linux/i386/sysdep.S)34
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h78
-rw-r--r--sysdeps/unix/sysv/linux/ia64/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/m68k/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/sh/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sysdep.h1
-rw-r--r--sysdeps/unix/sysv/linux/sysdep.h25
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/sysdep.h1
22 files changed, 91 insertions, 85 deletions
diff --git a/sysdeps/unix/sysv/linux/alpha/sysdep.h b/sysdeps/unix/sysv/linux/alpha/sysdep.h
index a95b1139d2..aea77b472b 100644
--- a/sysdeps/unix/sysv/linux/alpha/sysdep.h
+++ b/sysdeps/unix/sysv/linux/alpha/sysdep.h
@@ -25,6 +25,7 @@
#endif
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/alpha/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/arm/sysdep.h b/sysdeps/unix/sysv/linux/arm/sysdep.h
index 200f77a62e..c8715f7f4b 100644
--- a/sysdeps/unix/sysv/linux/arm/sysdep.h
+++ b/sysdeps/unix/sysv/linux/arm/sysdep.h
@@ -21,6 +21,7 @@
#define _LINUX_ARM_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/arm/sysdep.h>
/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
diff --git a/sysdeps/unix/sysv/linux/generic/sysdep.h b/sysdeps/unix/sysv/linux/generic/sysdep.h
index 11da9d21df..70e7158508 100644
--- a/sysdeps/unix/sysv/linux/generic/sysdep.h
+++ b/sysdeps/unix/sysv/linux/generic/sysdep.h
@@ -19,6 +19,7 @@
#include <bits/wordsize.h>
#include <kernel-features.h>
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
/* Provide the common name to allow more code reuse. */
#define __NR__llseek __NR_llseek
diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep.h b/sysdeps/unix/sysv/linux/hppa/sysdep.h
index cb1f163b4b..2cae70fd3c 100644
--- a/sysdeps/unix/sysv/linux/hppa/sysdep.h
+++ b/sysdeps/unix/sysv/linux/hppa/sysdep.h
@@ -22,6 +22,7 @@
#define _LINUX_HPPA_SYSDEP_H 1
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/hppa/sysdep.h>
/* Defines RTLD_PRIVATE_ERRNO. */
diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 80da5935cf..e10d133db4 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/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S
index 243dbfecc9..2aafb3a4a6 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/sysdep.S b/sysdeps/unix/sysv/linux/i386/sysdep.c
index 4e6c262f8e..141105eeff 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.S
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-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
@@ -15,26 +15,16 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <errno.h>
#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 */
+/* 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
+__attribute__ ((__regparm__ (1)))
+__syscall_error (int error)
+{
+ __set_errno (-error);
+ return -1;
+}
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index d76aca50d6..3cf927a24b 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -20,6 +20,7 @@
#define _LINUX_I386_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/i386/sysdep.h>
/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
#include <dl-sysdep.h>
@@ -55,11 +56,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 +97,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 +224,9 @@
#else /* !__ASSEMBLER__ */
+extern int __syscall_error (int)
+ attribute_hidden __attribute__ ((__regparm__ (1)));
+
/* 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"
@@ -318,7 +270,15 @@ struct libc_do_syscall_args
/* Define a macro which expands inline into the wrapper code for a system
call. */
#undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...) \
+#if IS_IN (libc)
+# define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
+ __glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, )) \
+ ? __syscall_error (-INTERNAL_SYSCALL_ERRNO (resultvar, )) \
+ : (int) resultvar; })
+#else
+# define INLINE_SYSCALL(name, nr, args...) \
({ \
unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \
@@ -327,6 +287,14 @@ struct libc_do_syscall_args
resultvar = 0xffffffff; \
} \
(int) resultvar; })
+#endif
+
+/* Set error number and return -1. Return the internal function,
+ __syscall_error, which sets errno from the negative error number
+ and returns -1, to avoid PIC. */
+#undef INLINE_SYSCALL_ERROR_RETURN_VALUE
+#define INLINE_SYSCALL_ERROR_RETURN_VALUE(resultvar) \
+ __syscall_error (-(resultvar))
/* List of system calls which are supported as vsyscalls. */
# define HAVE_CLOCK_GETTIME_VSYSCALL 1
diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h
index 03efae9024..eafcc7acfb 100644
--- a/sysdeps/unix/sysv/linux/ia64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h
@@ -21,6 +21,7 @@
#define _LINUX_IA64_SYSDEP_H 1
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/ia64/sysdep.h>
#include <dl-sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/m68k/sysdep.h b/sysdeps/unix/sysv/linux/m68k/sysdep.h
index 2b88add4c8..e55446cb44 100644
--- a/sysdeps/unix/sysv/linux/m68k/sysdep.h
+++ b/sysdeps/unix/sysv/linux/m68k/sysdep.h
@@ -17,6 +17,7 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <tls.h>
/* Defines RTLD_PRIVATE_ERRNO. */
diff --git a/sysdeps/unix/sysv/linux/microblaze/sysdep.h b/sysdeps/unix/sysv/linux/microblaze/sysdep.h
index 9d5c542633..75dd11f741 100644
--- a/sysdeps/unix/sysv/linux/microblaze/sysdep.h
+++ b/sysdeps/unix/sysv/linux/microblaze/sysdep.h
@@ -20,6 +20,7 @@
#define _LINUX_MICROBLAZE_SYSDEP_H 1
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/microblaze/sysdep.h>
/* Defines RTLD_PRIVATE_ERRNO. */
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
index a2aa38ddd7..cb8f4a8d94 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
@@ -19,6 +19,7 @@
#define _LINUX_MIPS_MIPS32_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/mips/mips32/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
index 4c28af6c3e..b97bf0b63b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
@@ -19,6 +19,7 @@
#define _LINUX_MIPS_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/mips/mips64/n32/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
index 1fc038c27f..6bbeeb0ee3 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
@@ -19,6 +19,7 @@
#define _LINUX_MIPS_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/mips/mips64/n64/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
index dc56bea49a..7f389e478b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
@@ -18,6 +18,7 @@
#ifndef _LINUX_POWERPC_SYSDEP_H
#define _LINUX_POWERPC_SYSDEP_H 1
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/powerpc/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index e2014cca39..6803cce70f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -20,6 +20,7 @@
#ifndef _LINUX_POWERPC_SYSDEP_H
#define _LINUX_POWERPC_SYSDEP_H 1
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/powerpc/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
index c768df1743..d29b68593d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
@@ -21,6 +21,7 @@
#include <sysdeps/s390/s390-32/sysdep.h>
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
index c041153b3a..a373207dff 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
@@ -22,6 +22,7 @@
#include <sysdeps/s390/s390-64/sysdep.h>
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.h b/sysdeps/unix/sysv/linux/sh/sysdep.h
index 5226ff611c..ab5b2c3d70 100644
--- a/sysdeps/unix/sysv/linux/sh/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sh/sysdep.h
@@ -21,6 +21,7 @@
#define _LINUX_SH_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/sh/sysdep.h>
#include <tls.h>
diff --git a/sysdeps/unix/sysv/linux/sparc/sysdep.h b/sysdeps/unix/sysv/linux/sparc/sysdep.h
index e215dbb3be..c9843de5b3 100644
--- a/sysdeps/unix/sysv/linux/sparc/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sparc/sysdep.h
@@ -20,6 +20,7 @@
#define _LINUX_SPARC_SYSDEP_H 1
#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/sparc/sysdep.h>
#ifdef __ASSEMBLER__
diff --git a/sysdeps/unix/sysv/linux/sysdep.h b/sysdeps/unix/sysv/linux/sysdep.h
new file mode 100644
index 0000000000..a7dd887394
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sysdep.h
@@ -0,0 +1,25 @@
+/* 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/>. */
+
+/* Set error number and return -1. A target may choose to return the
+ internal function, __syscall_error, which sets errno and returns -1.
+ We use -1l, instead of -1, so that it can be casted to (void *). */
+#define INLINE_SYSCALL_ERROR_RETURN_VALUE(err) \
+ ({ \
+ __set_errno (err); \
+ -1l; \
+ })
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 5a62cce467..fc132f6791 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -19,6 +19,7 @@
#define _LINUX_X86_64_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/x86_64/sysdep.h>
#include <tls.h>