From patchwork Wed Oct 7 16:23:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 8984 Received: (qmail 108561 invoked by alias); 7 Oct 2015 16:24:07 -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 108465 invoked by uid 89); 7 Oct 2015 16:24:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-yk0-f181.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ghG6MUngEHQxf9srgGxTije4SH94e6Xqvy1i84Nz688=; b=W+Zfqeg6iQJ9Rw+4Y/PwaJTOeiPy9oHSCNBZm99d8z08qe3pwoZ+v9ssytLPmSdd8s nYMYDBw7aiK+fdJ9tZZPA0MAsj4WejxqBa2uv1HZE+uY/UkXqZ2xU3QhqcRdDew2mqqb 3DQ5xe6Z0fYTF5li9OkTPkRsy5L7vkz9uGWQe6aEIgWmkwR4KruGufhFETiX4FE+gmp5 ffN4rx5vj6NXlOFZ4VJi7xrpIzJ9DjY/EujjDS+3QNPCmfEQs3GOR9/BiKZyXu8Qmnxr 43yfauPlbh94kMhGwa0D2aIjLG7XQF48REW54I/1ZnB3isuWP6DlI5BLmAm8HYeL3kRo mbQw== X-Gm-Message-State: ALoCoQk4u2Sy1Dfhkf+dDndqSF3+UDAU6XDLLTWVu2aw9DwaVav79qFvMieznzLn7dkSOpNwxvj0 X-Received: by 10.13.210.5 with SMTP id u5mr1585785ywd.154.1444235013943; Wed, 07 Oct 2015 09:23:33 -0700 (PDT) From: Adhemerval Zanella X-Google-Original-From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Adhemerval Zanella Subject: [PATCH 08/13] nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683) Date: Wed, 7 Oct 2015 13:23:10 -0300 Message-Id: <1444234995-9542-9-git-send-email-adhemerval.zanella@linaro.com> In-Reply-To: <1444234995-9542-1-git-send-email-adhemerval.zanella@linaro.com> References: <1444234995-9542-1-git-send-email-adhemerval.zanella@linaro.com> From: Adhemerval Zanella This patch adds the i386 modifications required for the BZ#12683 fix. It basically removes the enable_asynccancel/disable_asynccancel function usage on code used on x86_64, provide a arch-specific symbol that contains global markers to be used in SIGCANCEL handler, and add cancellation entrypoints in the socketcall default header. Checked on i686. * sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove macro. * sysdeps/unix/sysv/linux/i386/Makefile [$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object. * sysdeps/unix/sysv/linux/i386/fcntl.c (NO_CANCELLATION): Replace by IS_IN (rtld). * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_wait_tid): Use cancellable futex syscall macro. * sysdeps/unix/sysv/linux/i386/syscall_cancel.S: New file. * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Redefine to call __syscall_cancel function for cancellable syscalls. * sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_CANCEL_ERROR): New define. (SYSCALL_CANCEL_ERRNO): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_0): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_1): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_2): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_3): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_4): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_5): Likewise. (INTERNAL_SYSCALL_MAIN_NCS_6): Likewise. (INTERNAL_SYSCALL_NCS): Redefine to call it with 6-arguments. --- ChangeLog | 22 ++++ sysdeps/i386/nptl/tls.h | 11 -- sysdeps/unix/sysv/linux/i386/Makefile | 1 + sysdeps/unix/sysv/linux/i386/fcntl.c | 4 +- sysdeps/unix/sysv/linux/i386/lowlevellock.h | 2 +- sysdeps/unix/sysv/linux/i386/syscall_cancel.S | 105 +++++++++++++++++++ sysdeps/unix/sysv/linux/i386/sysdep-cancel.h | 144 ++++++++++---------------- sysdeps/unix/sysv/linux/i386/sysdep.h | 65 +++++++++--- sysdeps/unix/sysv/linux/socketcall.h | 34 ++++-- 9 files changed, 261 insertions(+), 127 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/i386/syscall_cancel.S diff --git a/ChangeLog b/ChangeLog index b71c168..feaf023 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,27 @@ 2015-10-07 Adhemerval Zanella + * sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove macro. + * sysdeps/unix/sysv/linux/i386/Makefile + [$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object. + * sysdeps/unix/sysv/linux/i386/fcntl.c (NO_CANCELLATION): Replace + by IS_IN (rtld). + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_wait_tid): Use + cancellable futex syscall macro. + * sysdeps/unix/sysv/linux/i386/syscall_cancel.S: New file. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Redefine to + call __syscall_cancel function for cancellable syscalls. + * sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_CANCEL_ERROR): New + define. + (SYSCALL_CANCEL_ERRNO): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_0): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_1): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_2): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_3): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_4): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_5): Likewise. + (INTERNAL_SYSCALL_MAIN_NCS_6): Likewise. + (INTERNAL_SYSCALL_NCS): Redefine to call it with 6-arguments. + * sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h (__syscall_arg_t): Define type for x32. (__SSC): Add platform specific macro. diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h index 829cd3a..ffac3a8 100644 --- a/sysdeps/i386/nptl/tls.h +++ b/sysdeps/i386/nptl/tls.h @@ -395,17 +395,6 @@ tls_fill_user_desc (union user_desc_init *desc, abort (); }) -/* Atomic set bit. */ -#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ - (void) ({ if (sizeof ((descr)->member) == 4) \ - asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0" \ - :: "i" (offsetof (struct pthread, member)), \ - "ir" (1 << (bit))); \ - else \ - /* Not necessary for other sizes in the moment. */ \ - abort (); }) - - /* Call the user-provided thread function. */ #define CALL_THREAD_FCT(descr) \ ({ void *__res; \ diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index 80da593..4f83d08 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -6,6 +6,7 @@ sysdep_routines += ioperm iopl vm86 endif ifeq ($(subdir),elf) +sysdep-rtld_routines += libc-do-syscall sysdep-others += lddlibc4 install-bin += lddlibc4 endif diff --git a/sysdeps/unix/sysv/linux/i386/fcntl.c b/sysdeps/unix/sysv/linux/i386/fcntl.c index 56f4bd1..ac5eed4 100644 --- a/sysdeps/unix/sysv/linux/i386/fcntl.c +++ b/sysdeps/unix/sysv/linux/i386/fcntl.c @@ -23,7 +23,7 @@ #include -#ifndef NO_CANCELLATION +#if !IS_IN (rtld) int __fcntl_nocancel (int fd, int cmd, ...) { @@ -36,7 +36,7 @@ __fcntl_nocancel (int fd, int cmd, ...) return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); } -#endif /* NO_CANCELLATION */ +#endif int diff --git a/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/sysdeps/unix/sysv/linux/i386/lowlevellock.h index 58f5638..02ea0fc 100644 --- a/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -283,7 +283,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count, do { \ __typeof (tid) __tid; \ while ((__tid = (tid)) != 0) \ - lll_futex_wait (&(tid), __tid, LLL_SHARED);\ + lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);\ } while (0) extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) diff --git a/sysdeps/unix/sysv/linux/i386/syscall_cancel.S b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S new file mode 100644 index 0000000..1ff6288 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S @@ -0,0 +1,105 @@ +/* Cancellable syscall wrapper - x86_64 version. + 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 + . */ + +#include + +/* long int [eax] __syscall_cancel_arch (int *cancelhandling [SP], + long int nr [SP+4], + long int arg1 [SP+8], + long int arg2 [SP+12], + long int arg3 [SP+16], + long int arg4 [SP+20], + long int arg5 [SP+24], + long int arg6 [SP+28]) */ + +ENTRY (__syscall_cancel_arch) + pushl %ebp + cfi_def_cfa_offset (8) + cfi_offset (ebp, -8) + pushl %edi + cfi_def_cfa_offset (12) + cfi_offset (edi, -12) + pushl %esi + cfi_def_cfa_offset (16) + cfi_offset (esi, -16) + pushl %ebx + cfi_def_cfa_offset (20) + cfi_offset (ebx, -20) + + .globl __syscall_cancel_arch_start + .type __syscall_cancel_arch_start,@function +__syscall_cancel_arch_start: + + /* if (*cancelhandling & CANCELED_BITMASK) + __syscall_do_cancel() */ + testb $4, (%eax) + jne 1f + + /* Issue a 6 argument syscall, the nr [%eax] being the syscall + number. */ + movl 24(%esp), %eax + movl 28(%esp), %ebx + movl 32(%esp), %ecx + movl 36(%esp), %edx + movl 40(%esp), %esi + movl 44(%esp), %edi + movl 48(%esp), %ebp + + /* It can not use the vDSO __kernel_vsyscall because the cancelable + checks in libc-cancelation.c requires to know if the cancellation + IP value that was trigger between the two + __syscall_cancel_arch_{start,end} marks. */ + int $128 + + .globl __syscall_cancel_arch_end + .type __syscall_cancel_arch_end,@function +__syscall_cancel_arch_end: + + popl %ebx + cfi_restore (ebx) + cfi_def_cfa_offset (16) + popl %esi + cfi_restore (esi) + cfi_def_cfa_offset (12) + popl %edi + cfi_restore (edi) + cfi_def_cfa_offset (8) + popl %ebp + cfi_restore (ebp) + cfi_def_cfa_offset (4) + ret + +1: + /* Although the __syscall_do_cancel do not return, we need to stack + being set correctly so exceptions work correctly. */ + popl %ebx + cfi_restore (ebx) + cfi_def_cfa_offset (16) + popl %esi + cfi_restore (esi) + cfi_def_cfa_offset (12) + popl %edi + cfi_restore (edi) + cfi_def_cfa_offset (8) + popl %ebp + cfi_restore (ebp) + cfi_def_cfa_offset (4) + jmp __syscall_do_cancel + +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h index 1f86dae..d8cdd27 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -24,112 +24,66 @@ #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) +# if IS_IN (libc) +# define JMP_STARTFUNC \ + subl $16, %esp +# define JMP_SYSCALL_CANCEL \ + HIDDEN_JUMPTARGET(__syscall_cancel) +# define JMP_ENDFUNC \ + addl $44, %esp; \ + cfi_def_cfa_offset (4) +# else +# define JMP_STARTFUNC \ + pushl %ebx; \ + cfi_def_cfa_offset (8); \ + cfi_offset (ebx, -8); \ + SETUP_PIC_REG (bx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + subl $12, %esp +# define JMP_SYSCALL_CANCEL \ + __syscall_cancel@plt +# define JMP_ENDFUNC \ + addl $40, %esp; \ + cfi_def_cfa_offset (8); \ + popl %ebx; \ + cfi_restore (ebx); \ + cfi_def_cfa_offset (4) +# endif + # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \ jne L(pseudo_cancel); \ - .type __##syscall_name##_nocancel,@function; \ - .globl __##syscall_name##_nocancel; \ - __##syscall_name##_nocancel: \ DO_CALL (syscall_name, args); \ cmpl $-4095, %eax; \ jae SYSCALL_ERROR_LABEL; \ ret; \ - .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ L(pseudo_cancel): \ - CENABLE \ - SAVE_OLDTYPE_##args \ - PUSHCARGS_##args \ - DOCARGS_##args \ - movl $SYS_ify (syscall_name), %eax; \ - ENTER_KERNEL; \ - POPCARGS_##args; \ - POPSTATE_##args \ + JMP_STARTFUNC; \ + cfi_def_cfa_offset (20); \ + pushl 40(%esp); \ + cfi_def_cfa_offset (24); \ + pushl 40(%esp); \ + cfi_def_cfa_offset (28); \ + pushl 40(%esp); \ + cfi_def_cfa_offset (32); \ + pushl 40(%esp); \ + cfi_def_cfa_offset (36); \ + pushl 40(%esp); \ + cfi_def_cfa_offset (40); \ + pushl 40(%esp); \ + cfi_def_cfa_offset (44); \ + pushl $SYS_ify (syscall_name); \ + cfi_def_cfa_offset (48); \ + call JMP_SYSCALL_CANCEL; \ + JMP_ENDFUNC; \ cmpl $-4095, %eax; \ jae SYSCALL_ERROR_LABEL -# define SAVE_OLDTYPE_0 movl %eax, %ecx; -# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 -# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); -# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 -# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 -# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 -# define SAVE_OLDTYPE_6 SAVE_OLDTYPE_2 - -# define PUSHCARGS_0 /* No arguments to push. */ -# define DOCARGS_0 /* No arguments to frob. */ -# define POPCARGS_0 /* No arguments to pop. */ -# define _PUSHCARGS_0 /* No arguments to push. */ -# define _POPCARGS_0 /* No arguments to pop. */ - -# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 -# define DOCARGS_1 _DOARGS_1 (4) -# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); -# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (ebx, 0); _PUSHCARGS_0 -# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ - cfi_adjust_cfa_offset (-4); cfi_restore (ebx); - -# define PUSHCARGS_2 PUSHCARGS_1 -# define DOCARGS_2 _DOARGS_2 (12) -# define POPCARGS_2 POPCARGS_1 -# define _PUSHCARGS_2 _PUSHCARGS_1 -# define _POPCARGS_2 _POPCARGS_1 - -# define PUSHCARGS_3 _PUSHCARGS_2 -# define DOCARGS_3 _DOARGS_3 (20) -# define POPCARGS_3 _POPCARGS_3 -# define _PUSHCARGS_3 _PUSHCARGS_2 -# define _POPCARGS_3 _POPCARGS_2 - -# define PUSHCARGS_4 _PUSHCARGS_4 -# define DOCARGS_4 _DOARGS_4 (28) -# define POPCARGS_4 _POPCARGS_4 -# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (esi, 0); _PUSHCARGS_3 -# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ - cfi_adjust_cfa_offset (-4); cfi_restore (esi); - -# define PUSHCARGS_5 _PUSHCARGS_5 -# define DOCARGS_5 _DOARGS_5 (36) -# define POPCARGS_5 _POPCARGS_5 -# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (edi, 0); _PUSHCARGS_4 -# define _POPCARGS_5 _POPCARGS_4; popl %edi; \ - cfi_adjust_cfa_offset (-4); cfi_restore (edi); - -# define PUSHCARGS_6 _PUSHCARGS_6 -# define DOCARGS_6 _DOARGS_6 (44) -# define POPCARGS_6 _POPCARGS_6 -# define _PUSHCARGS_6 pushl %ebp; cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (ebp, 0); _PUSHCARGS_5 -# define _POPCARGS_6 _POPCARGS_5; popl %ebp; \ - cfi_adjust_cfa_offset (-4); cfi_restore (ebp); - -# if IS_IN (libpthread) -# define CENABLE call __pthread_enable_asynccancel; -# define CDISABLE call __pthread_disable_asynccancel -# elif IS_IN (libc) -# define CENABLE call __libc_enable_asynccancel; -# define CDISABLE call __libc_disable_asynccancel -# elif IS_IN (librt) -# define CENABLE call __librt_enable_asynccancel; -# define CDISABLE call __librt_disable_asynccancel -# else -# error Unsupported library -# endif -# define POPSTATE_0 \ - pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ - CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); -# define POPSTATE_1 POPSTATE_0 -# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ - cfi_adjust_cfa_offset (-4); -# define POPSTATE_3 POPSTATE_2 -# define POPSTATE_4 POPSTATE_3 -# define POPSTATE_5 POPSTATE_4 -# define POPSTATE_6 POPSTATE_5 +# undef PSEUDO_RET +# define PSEUDO_RET # ifndef __ASSEMBLER__ # define SINGLE_THREAD_P \ @@ -150,4 +104,10 @@ # define RTLD_SINGLE_THREAD_P \ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ header.multiple_threads) == 0, 1) + +static inline +long int __pthread_get_ip (const ucontext_t *uc) +{ + return (long int)uc->uc_mcontext.gregs[REG_EIP]; +} #endif diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index d76aca5..b82e6a2 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep.h @@ -373,6 +373,42 @@ struct libc_do_syscall_args register unsigned int resultvar; \ INTERNAL_SYSCALL_MAIN_##nr (name, err, args); \ (int) resultvar; }) + +/* Same as INTERNAL_SYSCALL, but for non-constant name argument. */ +#define INTERNAL_SYSCALL_MAIN_NCS_0(name, err, args...) \ + INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 0, args) +#define INTERNAL_SYSCALL_MAIN_NCS_1(name, err, args...) \ + INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 1, args) +#define INTERNAL_SYSCALL_MAIN_NCS_2(name, err, args...) \ + INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 2, args) +#define INTERNAL_SYSCALL_MAIN_NCS_3(name, err, args...) \ + INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 3, args) +#define INTERNAL_SYSCALL_MAIN_NCS_4(name, err, args...) \ + INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 4, args) +#define INTERNAL_SYSCALL_MAIN_NCS_5(name, err, args...) \ + INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 5, args) +/* The NCS version is different because it has a non-constant 'name' arg + and then requires a different asm constraint ("0" instead of "i"). */ +#define INTERNAL_SYSCALL_MAIN_NCS_6(name, err, arg1, arg2, arg3, \ + arg4, arg5, arg6) \ + struct libc_do_syscall_args _xv = \ + { \ + (int) (arg1), \ + (int) (arg5), \ + (int) (arg6) \ + }; \ + asm volatile ( \ + "movl %1, %%eax\n\t" \ + "call __libc_do_syscall" \ + : "=a" (resultvar) \ + : "0" (name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \ + : "memory", "cc") +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register unsigned int resultvar; \ + INTERNAL_SYSCALL_MAIN_NCS_##nr (name, err, args); \ + (int) resultvar; }) + #ifdef I386_USE_SYSENTER # ifdef SHARED # define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \ @@ -385,9 +421,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...) \ - ({ \ - register unsigned int resultvar; \ +# define INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, nr, args...) \ EXTRAVAR_##nr \ asm volatile ( \ LOADARGS_##nr \ @@ -395,8 +429,7 @@ struct libc_do_syscall_args RESTOREARGS_##nr \ : "=a" (resultvar) \ : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \ - ASMFMT_##nr(args) : "memory", "cc"); \ - (int) resultvar; }) + ASMFMT_##nr(args) : "memory", "cc") # else # define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \ EXTRAVAR_##nr \ @@ -407,17 +440,14 @@ 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...) \ - ({ \ - register unsigned int resultvar; \ +# define INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, nr, args...) \ EXTRAVAR_##nr \ asm volatile ( \ LOADARGS_##nr \ "call *_dl_sysinfo\n\t" \ RESTOREARGS_##nr \ : "=a" (resultvar) \ - : "0" (name) ASMFMT_##nr(args) : "memory", "cc"); \ - (int) resultvar; }) + : "0" (name) ASMFMT_##nr(args) : "memory", "cc") # endif #else # define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \ @@ -429,17 +459,14 @@ 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...) \ - ({ \ - register unsigned int resultvar; \ +# define INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, nr, args...) \ EXTRAVAR_##nr \ asm volatile ( \ LOADARGS_##nr \ "int $0x80\n\t" \ RESTOREARGS_##nr \ : "=a" (resultvar) \ - : "0" (name) ASMFMT_##nr(args) : "memory", "cc"); \ - (int) resultvar; }) + : "0" (name) ASMFMT_##nr(args) : "memory", "cc") #endif #undef INTERNAL_SYSCALL_DECL @@ -452,6 +479,14 @@ struct libc_do_syscall_args #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) +#undef SYSCALL_CANCEL_ERROR +#define SYSCALL_CANCEL_ERROR(__val) \ + ((unsigned int) (__val) >= 0xfffff001u) + +#undef SYSCALL_CANCEL_ERRNO +#define SYSCALL_CANCEL_ERRNO(__val) \ + (-(__val)) + #define LOADARGS_0 #ifdef __PIC__ # if defined I386_USE_SYSENTER && defined SHARED diff --git a/sysdeps/unix/sysv/linux/socketcall.h b/sysdeps/unix/sysv/linux/socketcall.h index 007acba..1bd29fe 100644 --- a/sysdeps/unix/sysv/linux/socketcall.h +++ b/sysdeps/unix/sysv/linux/socketcall.h @@ -86,13 +86,35 @@ sc_ret; \ }) -#define SOCKETCALL_CANCEL(name, __a1, __a2, __a3, __a4, __a5, __a6) \ + +#define __SOCKETCALL_CANCEL1(__name, __a1) \ + SYSCALL_CANCEL_NCS (socketcall, __name, \ + ((long int [1]) { (long int) __a1 })) +#define __SOCKETCALL_CANCEL2(__name, __a1, __a2) \ + SYSCALL_CANCEL_NCS (socketcall, __name, \ + ((long int [2]) { (long int) __a1, (long int) __a2 })) +#define __SOCKETCALL_CANCEL3(__name, __a1, __a2, __a3) \ + SYSCALL_CANCEL_NCS (socketcall, __name, \ + ((long int [3]) { (long int) __a1, (long int) __a2, (long int) __a3 })) +#define __SOCKETCALL_CANCEL4(__name, __a1, __a2, __a3, __a4) \ + SYSCALL_CANCEL_NCS (socketcall, __name, \ + ((long int [4]) { (long int) __a1, (long int) __a2, (long int) __a3, \ + (long int) __a4 })) +#define __SOCKETCALL_CANCEL5(__name, __a1, __a2, __a3, __a4, __a5) \ + SYSCALL_CANCEL_NCS (socketcall, __name, \ + ((long int [5]) { (long int) __a1, (long int) __a2, (long int) __a3, \ + (long int) __a4, (long int) __a5 })) +#define __SOCKETCALL_CANCEL6(__name, __a1, __a2, __a3, __a4, __a5, __a6) \ + SYSCALL_CANCEL_NCS (socketcall, __name, \ + ((long int [6]) { (long int) __a1, (long int) __a2, (long int) __a3, \ + (long int) __a4, (long int) __a5, (long int) __a6 })) + +#define __SOCKETCALL_CANCEL(...) __SOCKETCALL_DISP (__SOCKETCALL_CANCEL,\ + __VA_ARGS__) + +#define SOCKETCALL_CANCEL(name, args...) \ ({ \ - __syscall_arg_t __args[6] = { __SSC (__a1), __SSC (__a2), \ - __SSC (__a3), __SSC (__a4), \ - __SSC (__a5), __SSC (__a6) }; \ - long int sc_ret = SYSCALL_CANCEL_NCS (socketcall, SOCKOP_##name, \ - __args); \ + long int sc_ret = __SOCKETCALL_CANCEL (SOCKOP_##name, args); \ if (SYSCALL_CANCEL_ERROR (sc_ret)) \ { \ __set_errno (SYSCALL_CANCEL_ERRNO (sc_ret)); \