From patchwork Wed Oct 7 16:23:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 54606 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f200.google.com (mail-wi0-f200.google.com [209.85.212.200]) by patches.linaro.org (Postfix) with ESMTPS id 7DEB822FF8 for ; Wed, 7 Oct 2015 16:26:03 +0000 (UTC) Received: by wicuu12 with SMTP id uu12sf11573169wic.2 for ; Wed, 07 Oct 2015 09:26:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:mailing-list :precedence:list-id:list-unsubscribe:list-subscribe:list-archive :list-post:list-help:sender:delivered-to:from:to:cc:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results; bh=NmtjuMDZdP3K1utN47h5ZQiD/BKmlwTJsfILIhoYSQw=; b=R/wK9vXxCE2FH6VQVJifPWquXs2EdtZkGxe+RF+tUonzKrPTxkMhJ3McIaw4Xpbs1h 4K5DyI+4psuFQQuV05xe/5DEKql5EFg+1PAaww4bVpeFHiwKJdxJOss0mz45VAZnH6G6 s9I3PSbvtqnUoo3vnwQk1OEvtC23sqArkyahnomobmjfLBPguPnpRGmTAysi23/uqRGB ptSrRxp9X3+LLgdQ+e6dqEdHJtuBEVsL0wa/hb59nRabcJTrb+rfIseHwNZxxjO5g8pj VKBpZlL3LIEX/Rw2HNcJX1KQ0mZ4k9M1BGxfafpXzIxq/kgX4UwLt+8Lddh4/sLTJyQR Er/g== X-Gm-Message-State: ALoCoQn0qXMpWz2tqN3qgavzezYrrtQXIrlgNC8hZpOLWZSDoJZPNjwDCEgTKsbFAGhBwyOHbsUU X-Received: by 10.194.109.233 with SMTP id hv9mr432064wjb.1.1444235162437; Wed, 07 Oct 2015 09:26:02 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.168.83 with SMTP id r80ls83295lfe.75.gmail; Wed, 07 Oct 2015 09:26:02 -0700 (PDT) X-Received: by 10.112.209.4 with SMTP id mi4mr1110945lbc.7.1444235162281; Wed, 07 Oct 2015 09:26:02 -0700 (PDT) Received: from mail-lb0-x236.google.com (mail-lb0-x236.google.com. [2a00:1450:4010:c04::236]) by mx.google.com with ESMTPS id o65si25838547lfi.124.2015.10.07.09.26.02 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Oct 2015 09:26:02 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c04::236 as permitted sender) client-ip=2a00:1450:4010:c04::236; Received: by lbcao8 with SMTP id ao8so17949795lbc.3 for ; Wed, 07 Oct 2015 09:26:02 -0700 (PDT) X-Received: by 10.25.210.206 with SMTP id j197mr727198lfg.86.1444235162152; Wed, 07 Oct 2015 09:26:02 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp79665lbq; Wed, 7 Oct 2015 09:26:01 -0700 (PDT) X-Received: by 10.107.152.75 with SMTP id a72mr3421369ioe.129.1444235160916; Wed, 07 Oct 2015 09:26:00 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id a19si3165493igr.24.2015.10.07.09.26.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Oct 2015 09:26:00 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-63761-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 107220 invoked by alias); 7 Oct 2015 16:23:53 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list 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 107158 invoked by uid 89); 7 Oct 2015 16:23:52 -0000 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-f171.google.com X-Received: by 10.129.56.68 with SMTP id f65mr1573394ywa.201.1444235009898; Wed, 07 Oct 2015 09:23:29 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Adhemerval Zanella Subject: [PATCH 05/13] nptl: powerpc64: Fix Race conditions in pthread cancellation (BZ#12683) Date: Wed, 7 Oct 2015 13:23:07 -0300 Message-Id: <1444234995-9542-6-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> X-Original-Sender: adhemerval.zanella@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c04::236 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org X-Google-Group-Id: 836684582541 From: Adhemerval Zanella This patches adds the powerpc64 modification required for the BZ#12683 fix. It basically removes the enable_asynccancel/disable_asynccancel function usage on code used on powerpc64, and provide a arch-specific symbol that contains global markers to be used in SIGCANCEL handler. Checked on powerpc64 and powerpc64le. * sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c (__libc_fnctl): Remove CANCEL_ASYNC/CANCEL_RESET usage. * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): Likewise. (PSEUDO_RET): Likewise. (__pthread_get_ip): Add implementation. * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h (SYSCALL_CANCEL_ERROR): New define. (SYSCALL_CANCEL_ERRNO): New define. * sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file: cancellable syscall. * sysdeps/unix/sysv/linux/powerpc/sysdep.c (__syscall_cancel_error): New symbol: cancellable syscall error handler. --- ChangeLog | 14 +++ sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c | 4 +- .../sysv/linux/powerpc/powerpc64/sysdep-cancel.h | 137 +++++++-------------- sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h | 9 ++ sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S | 63 ++++++++++ sysdeps/unix/sysv/linux/powerpc/sysdep.c | 11 ++ 6 files changed, 141 insertions(+), 97 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S diff --git a/ChangeLog b/ChangeLog index 303de33..059e20f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2015-10-07 Adhemerval Zanella + * sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c (__libc_fnctl): + Remove CANCEL_ASYNC/CANCEL_RESET usage. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): + Likewise. + (PSEUDO_RET): Likewise. + (__pthread_get_ip): Add implementation. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h + (SYSCALL_CANCEL_ERROR): New define. + (SYSCALL_CANCEL_ERRNO): New define. + * sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file: + cancellable syscall. + * sysdeps/unix/sysv/linux/powerpc/sysdep.c (__syscall_cancel_error): + New symbol: cancellable syscall error handler. + * nptl/Makefile [routines]: Add syscall_cancel object. [libpthread-routines]: Remove cancellation object. (CFLAGS-cancellation.c): Remove -fasynchronous-unwind-tables. diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c index 69031ba..3a10d16 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c @@ -23,8 +23,7 @@ #include - -#ifndef NO_CANCELLATION +#if !IS_IN (rtld) int __fcntl_nocancel (int fd, int cmd, ...) { @@ -39,7 +38,6 @@ __fcntl_nocancel (int fd, int cmd, ...) } #endif - int __libc_fcntl (int fd, int cmd, ...) { diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h index 5cd7ddb..9381bfc 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -27,121 +27,70 @@ # define DASHDASHPFX(str) __##str -#if _CALL_ELF == 2 -#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16+48) -#define CANCEL_PARM_SAVE (FRAME_MIN_SIZE+16) -#else -#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16) -#define CANCEL_PARM_SAVE (CANCEL_FRAMESIZE+FRAME_PARM_SAVE) -#endif +# if !IS_IN (libc) +# undef HIDDEN_JUMPTARGET +# define HIDDEN_JUMPTARGET(__symbol) __symbol +# endif + +#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE) # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .section ".text"; \ ENTRY (name) \ SINGLE_THREAD_P; \ - bne- .Lpseudo_cancel; \ - .type DASHDASHPFX(syscall_name##_nocancel),@function; \ - .globl DASHDASHPFX(syscall_name##_nocancel); \ - DASHDASHPFX(syscall_name##_nocancel): \ + bne- L(pseudo_cancel); \ DO_CALL (SYS_ify (syscall_name)); \ - PSEUDO_RET; \ - .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel); \ - .Lpseudo_cancel: \ - stdu 1,-CANCEL_FRAMESIZE(1); \ - cfi_adjust_cfa_offset (CANCEL_FRAMESIZE); \ - mflr 9; \ - std 9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1); \ + bnslr+; \ + TAIL_CALL_SYSCALL_ERROR; \ + L(pseudo_cancel): \ + mflr r0; \ + std r0,FRAME_LR_SAVE(r1); \ cfi_offset (lr, FRAME_LR_SAVE); \ - DOCARGS_##args; /* save syscall args around CENABLE. */ \ - CENABLE; \ - std 3,FRAME_MIN_SIZE(1); /* store CENABLE return value (MASK). */ \ - UNDOCARGS_##args; /* restore syscall args. */ \ - DO_CALL (SYS_ify (syscall_name)); \ - mfcr 0; /* save CR/R3 around CDISABLE. */ \ - std 3,FRAME_MIN_SIZE+8(1); \ - std 0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1); \ - cfi_offset (cr, FRAME_CR_SAVE); \ - ld 3,FRAME_MIN_SIZE(1); /* pass MASK to CDISABLE. */ \ - CDISABLE; \ - ld 9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1); \ - ld 0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1); /* restore CR/R3. */ \ - ld 3,FRAME_MIN_SIZE+8(1); \ - mtlr 9; \ - mtcr 0; \ - addi 1,1,CANCEL_FRAMESIZE; \ + stdu r1,-CANCEL_FRAMESIZE(r1); \ + cfi_adjust_cfa_offset (CANCEL_FRAMESIZE); \ + mr r9,r8; \ + mr r8,r7; \ + mr r7,r6; \ + mr r6,r5; \ + mr r5,r4; \ + mr r4,r3; \ + li r3,SYS_ify (syscall_name); \ + bl HIDDEN_JUMPTARGET(__syscall_cancel); \ + nop; \ + bl JUMPTARGET(__syscall_cancel_error); \ + nop; \ + addi r1,r1,CANCEL_FRAMESIZE; \ cfi_adjust_cfa_offset (-CANCEL_FRAMESIZE); \ + ld r0,FRAME_LR_SAVE(r1); \ + mtlr r0; \ cfi_restore (lr); \ - cfi_restore (cr) - -# define DOCARGS_0 -# define UNDOCARGS_0 - -# define DOCARGS_1 std 3,CANCEL_PARM_SAVE(1); DOCARGS_0 -# define UNDOCARGS_1 ld 3,CANCEL_PARM_SAVE(1); UNDOCARGS_0 - -# define DOCARGS_2 std 4,CANCEL_PARM_SAVE+8(1); DOCARGS_1 -# define UNDOCARGS_2 ld 4,CANCEL_PARM_SAVE+8(1); UNDOCARGS_1 - -# define DOCARGS_3 std 5,CANCEL_PARM_SAVE+16(1); DOCARGS_2 -# define UNDOCARGS_3 ld 5,CANCEL_PARM_SAVE+16(1); UNDOCARGS_2 + blr -# define DOCARGS_4 std 6,CANCEL_PARM_SAVE+24(1); DOCARGS_3 -# define UNDOCARGS_4 ld 6,CANCEL_PARM_SAVE+24(1); UNDOCARGS_3 - -# define DOCARGS_5 std 7,CANCEL_PARM_SAVE+32(1); DOCARGS_4 -# define UNDOCARGS_5 ld 7,CANCEL_PARM_SAVE+32(1); UNDOCARGS_4 - -# define DOCARGS_6 std 8,CANCEL_PARM_SAVE+40(1); DOCARGS_5 -# define UNDOCARGS_6 ld 8,CANCEL_PARM_SAVE+40(1); UNDOCARGS_5 - -# if IS_IN (libpthread) -# ifdef SHARED -# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) -# else -# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel); nop -# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel); nop -# endif -# elif IS_IN (libc) -# ifdef SHARED -# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) -# else -# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel); nop -# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel); nop -# endif -# elif IS_IN (librt) -# ifdef SHARED -# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) -# else -# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel); nop -# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel); nop -# endif -# else -# error Unsupported library -# endif +# undef PSEUDO_RET +# define PSEUDO_RET # ifndef __ASSEMBLER__ -# define SINGLE_THREAD_P \ - __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ - header.multiple_threads) == 0, 1) +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) # else -# define SINGLE_THREAD_P \ - lwz 10,MULTIPLE_THREADS_OFFSET(13); \ +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(13); \ cmpwi 10,0 # endif -#elif !defined __ASSEMBLER__ - -# define SINGLE_THREAD_P (1) -# define NO_CANCELLATION 1 - #endif #ifndef __ASSEMBLER__ # define RTLD_SINGLE_THREAD_P \ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ header.multiple_threads) == 0, 1) + +static inline +const char * __pthread_get_ip (const ucontext_t *uc) +{ + return (char *)uc->uc_mcontext.gp_regs[PT_NIP]; +} + #endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h index e2014cc..8a941f81 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h @@ -131,6 +131,15 @@ sc_ret; \ }) +#undef SYSCALL_CANCEL_ERROR +#define SYSCALL_CANCEL_ERROR(err) \ + (err > 0xfffffffffffff000UL) + +#undef SYSCALL_CANCEL_ERRNO +#define SYSCALL_CANCEL_ERRNO(err) \ + (-err) + + /* Define a macro which expands inline into the wrapper code for a system call. This use is for internal calls that do not need to handle errors normally. It will never touch errno. This returns just what the kernel diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S new file mode 100644 index 0000000..c7068d3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S @@ -0,0 +1,63 @@ +/* Cancellable syscall wrapper - powerpc version. + Copyright (C) 2014 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 [r3] __syscall_cancel_arch (int *cancelhandling [r3], + long int nr [r4], + long int arg1 [r5], + long int arg2 [r6], + long int arg3 [r7], + long int arg4 [r8], + long int arg5 [r9], + long int arg6 [r10]) */ + +ENTRY (__syscall_cancel_arch) + + .globl __syscall_cancel_arch_start + .type __syscall_cancel_arch_start,@function +__syscall_cancel_arch_start: + + /* if (*cancelhandling & CANCELED_BITMASK) + __syscall_do_cancel() */ + lwz r0,0(r3) + rldicl. r0,r0,62,63 + beq 1f + b __syscall_do_cancel + nop +1: + /* Issue a 6 argument syscall, the nr [r4] being the syscall + number. */ + mr r0,r4 + mr r3,r5 + mr r4,r6 + mr r5,r7 + mr r6,r8 + mr r7,r9 + mr r8,r10 + sc + + .globl __syscall_cancel_arch_end + .type __syscall_cancel_arch_end,@function +__syscall_cancel_arch_end: + + bnslr+ + neg r3,r3 + blr +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.c b/sysdeps/unix/sysv/linux/powerpc/sysdep.c index 6dc6737..8d58fd0 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sysdep.c +++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.c @@ -26,3 +26,14 @@ __syscall_error (int err_no) __set_errno (err_no); return -1; } + +long int +__syscall_cancel_error (unsigned long err) +{ + if (__glibc_unlikely ((err) & (1 << 28))) + { + __set_errno (-err); + return -1; + } + return err; +}