From patchwork Fri Aug 21 22:38:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Lu, Hongjiu" X-Patchwork-Id: 8383 Received: (qmail 123073 invoked by alias); 21 Aug 2015 22:39:11 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 123063 invoked by uid 89); 21 Aug 2015 22:39:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, NO_DNS_FOR_FROM, RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mga11.intel.com X-ExtLoop1: 1 Date: Fri, 21 Aug 2015 15:38:58 -0700 From: "H.J. Lu" To: GNU C Library Subject: RFC: [PATCH] Add INLINE_SYSCALL_ERROR_RETURN Message-ID: <20150821223858.GA3889@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) If it is OK, I can add #include to other sysdep.h files. Thanks. H.J. --- 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 so that i386 can optimize setting errno by branching to the internal __syscall_error without PLT. With i386 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: : 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 18: test $0x1,%ah 1b: jne 48 1d: mov $0x132,%eax 22: call *%gs:0x10 29: cmp $0xfffff000,%eax 2e: ja 58 30: pop %ebx 31: ret 32: lea 0x0(%esi),%esi 38: pop %ebx 39: mov $0xffffffea,%eax 3e: jmp 3f 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 4f: R_386_PC32 __syscall_error 53: nop 54: lea 0x0(%esi,%eiz,1),%esi 58: pop %ebx 59: jmp 5a 5a: R_386_PC32 __syscall_error instead of : 0: sub $0x8,%esp 3: mov 0x18(%esp),%eax 7: mov %ebx,(%esp) a: call b 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 20: test $0x1,%ah 23: jne 88 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 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 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 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 * sysdeps/unix/sysv/linux/adjtime.c (ADJTIME): Use INLINE_SYSCALL_ERROR_RETURN. * 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/futimens.c (futimens): Likewise. * sysdeps/unix/sysv/linux/futimes.c (__futimes): Likewise. * sysdeps/unix/sysv/linux/fxstat.c (__fxstat): Likewise. * sysdeps/unix/sysv/linux/fxstatat.c (__fxstatat): Likewise. * sysdeps/unix/sysv/linux/fxstatat64.c (__fxstatat64): 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_open.c (__mq_open): Likewise. * sysdeps/unix/sysv/linux/mq_unlink.c (mq_unlink): Likewise. * sysdeps/unix/sysv/linux/prlimit.c (prlimit): Likewise. * sysdeps/unix/sysv/linux/readahead.c (__readahead): Likewise. * sysdeps/unix/sysv/linux/shmat.c (shmat): Likewise. * sysdeps/unix/sysv/linux/signalfd.c (signalfd): Likewise. * sysdeps/unix/sysv/linux/speed.c (cfsetospeed): Likewise. * sysdeps/unix/sysv/linux/tcsetattr.c (tcsetattr): Likewise. * sysdeps/unix/sysv/linux/ustat.c (ustat): Likewise. * sysdeps/unix/sysv/linux/utimensat.c (utimensat): 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/xstatconv.c (__xstat_conv): Likewise. (__xstat64_conv): Likewise. (__xstat32_conv): Likewise. * sysdeps/unix/sysv/linux/sysdep.h: New file. * sysdeps/unix/sysv/linux/i386/sysdep.h: Include . * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise. --- sysdeps/unix/sysv/linux/adjtime.c | 5 +---- sysdeps/unix/sysv/linux/dl-openat64.c | 3 +-- sysdeps/unix/sysv/linux/eventfd.c | 8 ++------ sysdeps/unix/sysv/linux/faccessat.c | 8 ++------ sysdeps/unix/sysv/linux/fchmodat.c | 10 ++-------- sysdeps/unix/sysv/linux/fcntl.c | 3 +-- sysdeps/unix/sysv/linux/futimens.c | 8 ++------ sysdeps/unix/sysv/linux/futimes.c | 5 +---- sysdeps/unix/sysv/linux/fxstat.c | 3 +-- sysdeps/unix/sysv/linux/fxstatat.c | 5 +---- sysdeps/unix/sysv/linux/fxstatat64.c | 10 ++-------- sysdeps/unix/sysv/linux/i386/sysdep.h | 1 + sysdeps/unix/sysv/linux/lutimes.c | 8 ++------ sysdeps/unix/sysv/linux/lxstat.c | 3 +-- sysdeps/unix/sysv/linux/mmap64.c | 5 +---- sysdeps/unix/sysv/linux/mq_open.c | 5 +---- sysdeps/unix/sysv/linux/mq_unlink.c | 8 ++------ sysdeps/unix/sysv/linux/prlimit.c | 13 +++---------- sysdeps/unix/sysv/linux/readahead.c | 3 +-- sysdeps/unix/sysv/linux/shmat.c | 6 ++---- sysdeps/unix/sysv/linux/signalfd.c | 8 ++------ sysdeps/unix/sysv/linux/speed.c | 10 ++-------- sysdeps/unix/sysv/linux/sysdep.h | 24 ++++++++++++++++++++++++ sysdeps/unix/sysv/linux/tcsendbrk.c | 3 +-- sysdeps/unix/sysv/linux/tcsetattr.c | 3 +-- sysdeps/unix/sysv/linux/ustat.c | 5 +---- sysdeps/unix/sysv/linux/utimensat.c | 8 ++------ sysdeps/unix/sysv/linux/x86_64/sysdep.h | 1 + sysdeps/unix/sysv/linux/xmknod.c | 10 ++-------- sysdeps/unix/sysv/linux/xmknodat.c | 10 ++-------- sysdeps/unix/sysv/linux/xstat.c | 3 +-- sysdeps/unix/sysv/linux/xstatconv.c | 29 +++++++---------------------- 32 files changed, 76 insertions(+), 158 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/sysdep.h diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c index b6fb7cf..ded0d02 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); tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L; tntx.modes = ADJ_OFFSET_SINGLESHOT; } diff --git a/sysdeps/unix/sysv/linux/dl-openat64.c b/sysdeps/unix/sysv/linux/dl-openat64.c index 732097d..b2dbd5c 100644 --- a/sysdeps/unix/sysv/linux/dl-openat64.c +++ b/sysdeps/unix/sysv/linux/dl-openat64.c @@ -33,7 +33,6 @@ openat64 (dfd, file, oflag) #ifdef __NR_openat return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE); #else - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); #endif } diff --git a/sysdeps/unix/sysv/linux/eventfd.c b/sysdeps/unix/sysv/linux/eventfd.c index d4ffb3c..55406bb 100644 --- a/sysdeps/unix/sysv/linux/eventfd.c +++ b/sysdeps/unix/sysv/linux/eventfd.c @@ -38,16 +38,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); # ifdef __NR_eventfd return INLINE_SYSCALL (eventfd, 1, count); # else - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); # 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..eaca319 100644 --- a/sysdeps/unix/sysv/linux/faccessat.c +++ b/sysdeps/unix/sysv/linux/faccessat.c @@ -35,10 +35,7 @@ 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); if ((flag == 0 || ((flag & ~AT_EACCESS) == 0 && ! __libc_enable_secure))) return INLINE_SYSCALL (faccessat, 3, fd, file, mode); @@ -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); } diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c index e278426..720b26b 100644 --- a/sysdeps/unix/sysv/linux/fchmodat.c +++ b/sysdeps/unix/sysv/linux/fchmodat.c @@ -34,16 +34,10 @@ fchmodat (fd, file, mode, flag) int flag; { if (flag & ~AT_SYMLINK_NOFOLLOW) - { - __set_errno (EINVAL); - return -1; - } + return INLINE_SYSCALL_ERROR_RETURN (EINVAL); #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); #endif return INLINE_SYSCALL (fchmodat, 3, fd, file, mode); diff --git a/sysdeps/unix/sysv/linux/fcntl.c b/sysdeps/unix/sysv/linux/fcntl.c index fa184db..4c891d6 100644 --- a/sysdeps/unix/sysv/linux/fcntl.c +++ b/sysdeps/unix/sysv/linux/fcntl.c @@ -36,8 +36,7 @@ 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)); } diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c index 5f2b8a5..6f9181d 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); /* Avoid implicit array coercion in syscall macros. */ return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0); #else - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); #endif } #ifndef __NR_utimensat diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c index 69ddfe1..afc8d2c 100644 --- a/sysdeps/unix/sysv/linux/futimes.c +++ b/sysdeps/unix/sysv/linux/futimes.c @@ -40,10 +40,7 @@ __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); TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]); TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]); diff --git a/sysdeps/unix/sysv/linux/fxstat.c b/sysdeps/unix/sysv/linux/fxstat.c index 8d8c4e1..72f4517 100644 --- a/sysdeps/unix/sysv/linux/fxstat.c +++ b/sysdeps/unix/sysv/linux/fxstat.c @@ -39,8 +39,7 @@ __fxstat (int vers, int fd, struct stat *buf) return INLINE_SYSCALL (fstat, 2, fd, (struct kernel_stat *) buf); #ifdef STAT_IS_KERNEL_STAT - errno = EINVAL; - return -1; + return INLINE_SYSCALL_ERROR_RETURN (EINVAL); #else struct kernel_stat kbuf; int result; diff --git a/sysdeps/unix/sysv/linux/fxstatat.c b/sysdeps/unix/sysv/linux/fxstatat.c index c88bcec..298493b 100644 --- a/sysdeps/unix/sysv/linux/fxstatat.c +++ b/sysdeps/unix/sysv/linux/fxstatat.c @@ -54,10 +54,7 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) #endif } else - { - __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); - return -1; - } + return INLINE_SYSCALL_ERROR_RETURN (INTERNAL_SYSCALL_ERRNO (result, err)); } 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..be97ccd 100644 --- a/sysdeps/unix/sysv/linux/fxstatat64.c +++ b/sysdeps/unix/sysv/linux/fxstatat64.c @@ -32,10 +32,7 @@ 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 result; INTERNAL_SYSCALL_DECL (err); @@ -44,9 +41,6 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag) if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return 0; else - { - __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); - return -1; - } + return INLINE_SYSCALL_ERROR_RETURN (INTERNAL_SYSCALL_ERRNO (result, err)); } libc_hidden_def (__fxstatat64) diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index d76aca5..aac3e7b 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 #include /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ #include diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c index 9e51305..b1cc54a 100644 --- a/sysdeps/unix/sysv/linux/lutimes.c +++ b/sysdeps/unix/sysv/linux/lutimes.c @@ -34,10 +34,7 @@ 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); TIMEVAL_TO_TIMESPEC (&tvp[0], &ts[0]); TIMEVAL_TO_TIMESPEC (&tvp[1], &ts[1]); @@ -46,8 +43,7 @@ lutimes (const char *file, const struct timeval tvp[2]) return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL, AT_SYMLINK_NOFOLLOW); #else - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); #endif } diff --git a/sysdeps/unix/sysv/linux/lxstat.c b/sysdeps/unix/sysv/linux/lxstat.c index 948665c..b859f93 100644 --- a/sysdeps/unix/sysv/linux/lxstat.c +++ b/sysdeps/unix/sysv/linux/lxstat.c @@ -38,8 +38,7 @@ __lxstat (int vers, const char *name, struct stat *buf) return INLINE_SYSCALL (lstat, 2, name, (struct kernel_stat *) buf); #ifdef STAT_IS_KERNEL_STAT - errno = EINVAL; - return -1; + return INLINE_SYSCALL_ERROR_RETURN (EINVAL); #else struct kernel_stat kbuf; int result; diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c index 0b160b6..1c9d3c1 100644 --- a/sysdeps/unix/sysv/linux/mmap64.c +++ b/sysdeps/unix/sysv/linux/mmap64.c @@ -46,10 +46,7 @@ __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; - } + return (void *) INLINE_SYSCALL_ERROR_RETURN (EINVAL); void *result; result = (void *) INLINE_SYSCALL (mmap2, 6, addr, diff --git a/sysdeps/unix/sysv/linux/mq_open.c b/sysdeps/unix/sysv/linux/mq_open.c index 46c0cc8..6ca78cd 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); mode_t mode = 0; struct mq_attr *attr = NULL; diff --git a/sysdeps/unix/sysv/linux/mq_unlink.c b/sysdeps/unix/sysv/linux/mq_unlink.c index a876c3c..51eb481 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); 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); } return ret; diff --git a/sysdeps/unix/sysv/linux/prlimit.c b/sysdeps/unix/sysv/linux/prlimit.c index db88ba8..0337940 100644 --- a/sysdeps/unix/sysv/linux/prlimit.c +++ b/sysdeps/unix/sysv/linux/prlimit.c @@ -59,20 +59,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); 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); old_rlimit->rlim_max = RLIM_INFINITY; } } @@ -84,8 +78,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); } stub_warning (prlimit) #endif diff --git a/sysdeps/unix/sysv/linux/readahead.c b/sysdeps/unix/sysv/linux/readahead.c index c47df0d..0cae417 100644 --- a/sysdeps/unix/sysv/linux/readahead.c +++ b/sysdeps/unix/sysv/linux/readahead.c @@ -38,8 +38,7 @@ __readahead (int fd, off64_t offset, size_t count) ssize_t __readahead (int fd, off64_t offset, size_t count) { - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); } stub_warning (readahead) #endif diff --git a/sysdeps/unix/sysv/linux/shmat.c b/sysdeps/unix/sysv/linux/shmat.c index 94d18d3..3f6388b 100644 --- a/sysdeps/unix/sysv/linux/shmat.c +++ b/sysdeps/unix/sysv/linux/shmat.c @@ -43,10 +43,8 @@ shmat (shmid, shmaddr, shmflg) (long int) &raddr, (void *) shmaddr); if (INTERNAL_SYSCALL_ERROR_P (resultvar, err)) - { - __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, err)); - return (void *) -1l; - } + return (void *) INLINE_SYSCALL_ERROR_RETURN (INTERNAL_SYSCALL_ERRNO (resultvar, + err)); return raddr; } diff --git a/sysdeps/unix/sysv/linux/signalfd.c b/sysdeps/unix/sysv/linux/signalfd.c index f3ae8c1..1e242a4 100644 --- a/sysdeps/unix/sysv/linux/signalfd.c +++ b/sysdeps/unix/sysv/linux/signalfd.c @@ -39,16 +39,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); # ifdef __NR_signalfd return INLINE_SYSCALL (signalfd, 3, fd, mask, _NSIG / 8); # else - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); # endif #elif !defined __NR_signalfd4 # error "__ASSUME_SIGNALFD4 defined but not __NR_signalfd4" diff --git a/sysdeps/unix/sysv/linux/speed.c b/sysdeps/unix/sysv/linux/speed.c index 3ac0640..8b5b7ac 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); #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); #ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED termios_p->c_ispeed = speed; diff --git a/sysdeps/unix/sysv/linux/sysdep.h b/sysdeps/unix/sysv/linux/sysdep.h new file mode 100644 index 0000000..fe2ce54 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sysdep.h @@ -0,0 +1,24 @@ +/* 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 + . */ + +/* Set error number and return -1. A target may choose to return the + internal function, __syscall_error, which sets errno and returns -1. */ +#define INLINE_SYSCALL_ERROR_RETURN(err) \ + ({ \ + __set_errno (err); \ + -1; \ + }) diff --git a/sysdeps/unix/sysv/linux/tcsendbrk.c b/sysdeps/unix/sysv/linux/tcsendbrk.c index 4a43209..c6599c5 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); #endif } diff --git a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c index d7afc63..7dd1368 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); } k_termios.c_iflag = termios_p->c_iflag & ~IBAUD0; diff --git a/sysdeps/unix/sysv/linux/ustat.c b/sysdeps/unix/sysv/linux/ustat.c index 8d495ca..b18d131 100644 --- a/sysdeps/unix/sysv/linux/ustat.c +++ b/sysdeps/unix/sysv/linux/ustat.c @@ -31,10 +31,7 @@ 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); return INLINE_SYSCALL (ustat, 2, (unsigned int) k_dev, ubuf); } diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c index 81b565f..df7c2a2 100644 --- a/sysdeps/unix/sysv/linux/utimensat.c +++ b/sysdeps/unix/sysv/linux/utimensat.c @@ -30,16 +30,12 @@ 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); #ifdef __NR_utimensat /* Avoid implicit array coercion in syscall macros. */ return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags); #else - __set_errno (ENOSYS); - return -1; + return INLINE_SYSCALL_ERROR_RETURN (ENOSYS); #endif } #ifndef __NR_utimensat diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 5a62cce..fc132f6 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 #include #include diff --git a/sysdeps/unix/sysv/linux/xmknod.c b/sysdeps/unix/sysv/linux/xmknod.c index b940273..daf71f8 100644 --- a/sysdeps/unix/sysv/linux/xmknod.c +++ b/sysdeps/unix/sysv/linux/xmknod.c @@ -33,18 +33,12 @@ __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); /* 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); return INLINE_SYSCALL (mknod, 3, path, mode, (unsigned int) k_dev); } diff --git a/sysdeps/unix/sysv/linux/xmknodat.c b/sysdeps/unix/sysv/linux/xmknodat.c index f30b9b3..66c8652 100644 --- a/sysdeps/unix/sysv/linux/xmknodat.c +++ b/sysdeps/unix/sysv/linux/xmknodat.c @@ -34,18 +34,12 @@ 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); /* 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); return INLINE_SYSCALL (mknodat, 4, fd, file, mode, (unsigned int) k_dev); } diff --git a/sysdeps/unix/sysv/linux/xstat.c b/sysdeps/unix/sysv/linux/xstat.c index 6218963..d45e37a 100644 --- a/sysdeps/unix/sysv/linux/xstat.c +++ b/sysdeps/unix/sysv/linux/xstat.c @@ -38,8 +38,7 @@ __xstat (int vers, const char *name, struct stat *buf) return INLINE_SYSCALL (stat, 2, name, (struct kernel_stat *) buf); #ifdef STAT_IS_KERNEL_STAT - errno = EINVAL; - return -1; + return INLINE_SYSCALL_ERROR_RETURN (EINVAL); #else struct kernel_stat kbuf; int result; diff --git a/sysdeps/unix/sysv/linux/xstatconv.c b/sysdeps/unix/sysv/linux/xstatconv.c index 6504414..1c448fc 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); } 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); } 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); } #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); #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); 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); #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); } return 0;