From patchwork Wed Oct 7 16:23:14 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 54607 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f197.google.com (mail-wi0-f197.google.com [209.85.212.197]) by patches.linaro.org (Postfix) with ESMTPS id 9ED8222FF8 for ; Wed, 7 Oct 2015 16:26:17 +0000 (UTC) Received: by wicuu12 with SMTP id uu12sf11576487wic.2 for ; Wed, 07 Oct 2015 09:26:16 -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:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results; bh=bfU0R/EkLdZQLKjT0TVWJzLHcNGtQPTK+he8LwEsSdI=; b=Y2lq3myeGmV6FAKEeEKS+W1FLy+cN7BTeo1MwiE0EWe6h6IHmQD+MT/Z6y4fIWli1J 7eHimU4JqZyancKAg8V9pnz/2jU5SCDSTrMTRqvRJdeC2rjED7BFpr+axdSHPFbRysZB wbx58UdbmrgqXr7qGBPo4hhCdZg6pxZ3MSPut0t23rgYraVZaKRQ/NaArLkn8UVolERl Tfz9TCHg5dyuUdf3EsyC71eEG69rDDRBctHwmNy0pOicQLycrU7dHFHEHVM3BrX5FxBr tYS7l+iuVNpLTWYUXTeCn5HGNerKgXnuxGv6GGt9nwTf1PoBa0uEubTB6Eo0HauPi9jC ZAOw== X-Gm-Message-State: ALoCoQmQF3BKX4No9ihZQg9Ep7FhQVY9RhaofpQrYUqmQqnYCbjNTXlZwaEZaQEWkIuCg/Uv36pC X-Received: by 10.112.132.6 with SMTP id oq6mr428937lbb.1.1444235176950; Wed, 07 Oct 2015 09:26:16 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.164.135 with SMTP id n129ls102560lfe.7.gmail; Wed, 07 Oct 2015 09:26:16 -0700 (PDT) X-Received: by 10.25.85.202 with SMTP id j193mr713822lfb.2.1444235176820; Wed, 07 Oct 2015 09:26:16 -0700 (PDT) Received: from mail-lb0-x234.google.com (mail-lb0-x234.google.com. [2a00:1450:4010:c04::234]) by mx.google.com with ESMTPS id 42si25839731lfr.77.2015.10.07.09.26.16 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Oct 2015 09:26:16 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c04::234 as permitted sender) client-ip=2a00:1450:4010:c04::234; Received: by lbwr8 with SMTP id r8so17382409lbw.2 for ; Wed, 07 Oct 2015 09:26:16 -0700 (PDT) X-Received: by 10.25.86.213 with SMTP id k204mr732332lfb.36.1444235176528; Wed, 07 Oct 2015 09:26:16 -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 w3csp79787lbq; Wed, 7 Oct 2015 09:26:15 -0700 (PDT) X-Received: by 10.50.83.104 with SMTP id p8mr3090433igy.90.1444235174989; Wed, 07 Oct 2015 09:26:14 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id o3si3164687iga.25.2015.10.07.09.26.14 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Oct 2015 09:26:14 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-63762-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 107401 invoked by alias); 7 Oct 2015 16:23:55 -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 107341 invoked by uid 89); 7 Oct 2015 16:23:54 -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-f172.google.com X-Received: by 10.13.253.3 with SMTP id n3mr1559944ywf.292.1444235018913; Wed, 07 Oct 2015 09:23:38 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 12/13] nptl: s390: Fix Race conditions in pthread cancellation (BZ#12683) Date: Wed, 7 Oct 2015 13:23:14 -0300 Message-Id: <1444234995-9542-13-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::234 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org X-Google-Group-Id: 836684582541 This patch adds the s390 modifications required for the BZ#12683 fix. It basically removes the enable_asynccancel/disable_asynccancel function usage on code, provide a arch-specific symbol that contains global markers to be used in SIGCANCEL handler. Checked on s390 (thanks to Stefan Liebler ). * sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S: New file. * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Redefine to call __syscall_cancel function for cancellable syscalls. (__pthread_get_ip): Add implementation. * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (SYSCALL_CANCEL_ERROR): Add definition. (SYSCALL_CANCEL_ERRNO): Likewise. --- ChangeLog | 11 ++ .../unix/sysv/linux/s390/s390-32/syscall_cancel.S | 85 ++++++++++++++ .../unix/sysv/linux/s390/s390-32/sysdep-cancel.h | 128 ++++++++++----------- sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h | 8 ++ 4 files changed, 168 insertions(+), 64 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S diff --git a/ChangeLog b/ChangeLog index f922fa0..cdb4190 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,15 @@ 2015-10-07 Adhemerval Zanella + Stefan Liebler + + * sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Redefine + to call __syscall_cancel function for cancellable syscalls. + (__pthread_get_ip): Add implementation. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (SYSCALL_CANCEL_ERROR): Add + definition. + (SYSCALL_CANCEL_ERRNO): Likewise. + +2015-10-07 Adhemerval Zanella * sysdeps/unix/sysv/linux/arm/syscall_cancel.S: New file. * sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Redefine diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S b/sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S new file mode 100644 index 0000000..bf90acd --- /dev/null +++ b/sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S @@ -0,0 +1,85 @@ +/* Cancellable syscall wrapper - s390 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 [r2] __syscall_cancel_arch (int *cancelhandling [r2], + long int nr [r3], + long int arg1 [r4], + long int arg2 [r5], + long int arg3 [r6], + long int arg4 [SP+96], + long int arg5 [SP+100], + long int arg6 [SP+104]) */ + +ENTRY (__syscall_cancel_arch) + /* Save registers and setup stack. */ + stm %r6,%r15,24(%r15) /* Save registers */ + cfi_offset (%r15, -36) + cfi_offset (%r14, -40) + cfi_offset (%r13, -44) + cfi_offset (%r12, -48) + cfi_offset (%r11, -52) + cfi_offset (%r10, -56) + cfi_offset (%r9, -60) + cfi_offset (%r8, -64) + cfi_offset (%r7, -68) + cfi_offset (%r6, -72) + lr %r1,%r15 + l %r0,4(0,%r15) /* Load eos */ + ahi %r15,-96 /* Buy stack space */ + cfi_adjust_cfa_offset (96) + st %r1,0(0,%r15) /* Store back chain */ + st %r0,4(0,%r15) /* Store eos */ + + .globl __syscall_cancel_arch_start + .type __syscall_cancel_arch_start,@function +__syscall_cancel_arch_start: + + /* if (*cancelhandling & CANCELED_BITMASK) + __syscall_do_cancel() */ + tm 3(%r2),4 + jne 1f + + /* Issue a 6 argument syscall */ + lr %r1,%r3 /* Move syscall number. */ + lr %r2,%r4 /* First parameter. */ + lr %r3,%r5 /* Second parameter. */ + lr %r4,%r6 /* Third parameter. */ + l %r5,192(%r15) /* Fourth parameter. */ + l %r6,196(%r15) /* Fifth parameter. */ + l %r7,200(%r15) /* Sixth parameter. */ + + svc 0 /* svc number is always in r1. */ + .globl __syscall_cancel_arch_end + .type __syscall_cancel_arch_end,@function +__syscall_cancel_arch_end: + l %r15,0(%r15) /* Load back chain. */ + cfi_adjust_cfa_offset (-96) + lm %r6,15,24(%r15) /* Load registers. */ + + br %r14 + + /* Branch to __syscall_do_cancel */ +1: + l %r15,0(%r15) /* Load back chain. */ + cfi_adjust_cfa_offset (-96) + lm %r6,%r15,24(%r15) /* Load registers. */ + jg __syscall_do_cancel +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h index 17b7aaa..1ed57f0 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h @@ -24,97 +24,90 @@ #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) +# if IS_IN (libc) +# define PREPARE_CALL +# define PREPARE_GOT +# define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel) +# else +# define PREPARE_CALL l %r12,2f-0b(%r13); \ + la %r12,0(%r12,%r13); +# define PREPARE_GOT 2: .long _GLOBAL_OFFSET_TABLE_-0b; +# define JMP_SYSCALL_CANCEL __syscall_cancel@plt +# endif + +# define STORE_0 /* Nothing */ +# define STORE_1 /* Nothing */ +# define STORE_2 /* Nothing */ +# define STORE_3 /* Nothing */ +# define STORE_4 st %r6,24(%r15); \ + cfi_offset (%r6,-72); +# define STORE_5 STORE_4 +# define STORE_6 STORE_4 + +# define LOAD_0 /* Nothing */ +# define LOAD_1 /* Nothing */ +# define LOAD_2 /* Nothing */ +# define LOAD_3 /* Nothing */ +# define LOAD_4 l %r6,24(%r15); +# define LOAD_5 LOAD_4 +# define LOAD_6 LOAD_4 + +# define MOVE_ARGS_0 +# define MOVE_ARGS_1 lr %r3,%r2; \ + MOVE_ARGS_0 +# define MOVE_ARGS_2 lr %r4,%r3; \ + MOVE_ARGS_1 +# define MOVE_ARGS_3 lr %r5,%r4; \ + MOVE_ARGS_2 +# define MOVE_ARGS_4 lr %r6,%r5; \ + MOVE_ARGS_3 +# define MOVE_ARGS_5 st %r6,96(%r15); \ + MOVE_ARGS_4 +# define MOVE_ARGS_6 l %r14,96(%r14); \ + st %r14,100(%r15); \ + MOVE_ARGS_5 + # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .text; \ L(pseudo_cancel): \ cfi_startproc; \ - STM_##args \ stm %r12,%r15,48(%r15); \ cfi_offset (%r15, -36); \ cfi_offset (%r14, -40); \ cfi_offset (%r13, -44); \ cfi_offset (%r12, -48); \ + STORE_##args \ lr %r14,%r15; \ - ahi %r15,-96; \ - cfi_adjust_cfa_offset (96); \ + ahi %r15,-104; \ + cfi_adjust_cfa_offset (104); \ st %r14,0(%r15); \ + MOVE_ARGS_##args \ + lhi %r2,SYS_ify (syscall_name); \ basr %r13,0; \ 0: l %r1,1f-0b(%r13); \ + PREPARE_CALL \ bas %r14,0(%r1,%r13); \ - lr %r0,%r2; \ - LM_##args \ - .if SYS_ify (syscall_name) < 256; \ - svc SYS_ify (syscall_name); \ - .else; \ - lhi %r1,SYS_ify (syscall_name); \ - svc 0; \ - .endif; \ - LR7_##args \ - l %r1,2f-0b(%r13); \ - lr %r12,%r2; \ - lr %r2,%r0; \ - bas %r14,0(%r1,%r13); \ - lr %r2,%r12; \ - lm %r12,%r15,48+96(%r15); \ + lm %r12,%r15,48+104(%r15); \ + cfi_restore (%r12); \ + cfi_restore (%r13); \ + cfi_restore (%r14); \ + cfi_restore (%r15); \ + LOAD_##args \ cfi_endproc; \ j L(pseudo_check); \ -1: .long CENABLE-0b; \ -2: .long CDISABLE-0b; \ +1: .long JMP_SYSCALL_CANCEL-0b; \ + PREPARE_GOT \ ENTRY(name) \ SINGLE_THREAD_P(%r1) \ jne L(pseudo_cancel); \ -.type __##syscall_name##_nocancel,@function; \ -.globl __##syscall_name##_nocancel; \ -__##syscall_name##_nocancel: \ DO_CALL(syscall_name, args); \ L(pseudo_check): \ lhi %r4,-4095; \ clr %r2,%r4; \ jnl SYSCALL_ERROR_LABEL; \ -.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ L(pseudo_end): -# if IS_IN (libpthread) -# define CENABLE __pthread_enable_asynccancel -# define CDISABLE __pthread_disable_asynccancel -# elif IS_IN (libc) -# define CENABLE __libc_enable_asynccancel -# define CDISABLE __libc_disable_asynccancel -# elif IS_IN (librt) -# define CENABLE __librt_enable_asynccancel -# define CDISABLE __librt_disable_asynccancel -# else -# error Unsupported library -# endif - -#define STM_0 /* Nothing */ -#define STM_1 st %r2,8(%r15); -#define STM_2 stm %r2,%r3,8(%r15); -#define STM_3 stm %r2,%r4,8(%r15); -#define STM_4 stm %r2,%r5,8(%r15); -#define STM_5 stm %r2,%r5,8(%r15); -#define STM_6 stm %r2,%r7,8(%r15); - -#define LM_0 /* Nothing */ -#define LM_1 l %r2,8+96(%r15); -#define LM_2 lm %r2,%r3,8+96(%r15); -#define LM_3 lm %r2,%r4,8+96(%r15); -#define LM_4 lm %r2,%r5,8+96(%r15); -#define LM_5 lm %r2,%r5,8+96(%r15); -#define LM_6 lm %r2,%r5,8+96(%r15); \ - cfi_offset (%r7, -68); \ - l %r7,96+96(%r15); - -#define LR7_0 /* Nothing */ -#define LR7_1 /* Nothing */ -#define LR7_2 /* Nothing */ -#define LR7_3 /* Nothing */ -#define LR7_4 /* Nothing */ -#define LR7_5 /* Nothing */ -#define LR7_6 l %r7,28+96(%r15); \ - cfi_restore (%r7); - # ifndef __ASSEMBLER__ # define SINGLE_THREAD_P \ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ @@ -136,4 +129,11 @@ L(pseudo_end): # define RTLD_SINGLE_THREAD_P \ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ header.multiple_threads) == 0, 1) + +static inline +long int __pthread_get_ip (const struct ucontext *uc) +{ + /* We have 31bit addresses, remove bit 0. */ + return uc->uc_mcontext.psw.addr & 0x7FFFFFFF; +} #endif diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h index c768df1..08e2be4 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h +++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h @@ -243,6 +243,14 @@ #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 DECLARGS_0() #define DECLARGS_1(arg1) \ register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);