From patchwork Thu Sep 17 20:04:20 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: 519009 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A6F321402BF for ; Fri, 18 Sep 2015 06:04:51 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=lA/gGgu0; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:subject:to:message-id:date:mime-version :content-type:content-transfer-encoding; q=dns; s=default; b=vdp f4kmQBVI1swzceuwEVAFzB6HvKSl7FFijUlhwqQOLATUlq9D9sBnqTiurlC84sNz LSUdK25JoPhTtl8Y+VboVGuORVOVAmubhiD8fbzhY7y4rDVs73hIhU/4b0+qnyhd GXAb2bI1ziT7EoOR2MO3oyVSCh7LmDYQwttNweAU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:subject:to:message-id:date:mime-version :content-type:content-transfer-encoding; s=default; bh=I2v8npiNJ BGYr9iaBIPoLd1rFfs=; b=lA/gGgu0cSmHhS95xz+ri32eRi4oX+lRrjs5C1i3N 2bt2EOYf4reSoV9x2s+phIX84JLVlwMu/nZfxlRgumsKeXrReFidtrjFS9xCMmu+ zYtO7+JkMExxi9/GdB8vkgAFIcj++/VmfCm7p1HvVq8b3pX2Y3ohvcDrFXmp/Jrl 2Y= Received: (qmail 108315 invoked by alias); 17 Sep 2015 20:04:38 -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 107832 invoked by uid 89); 17 Sep 2015 20:04:34 -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-f177.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:subject:to:message-id:date:user-agent :mime-version:content-type:content-transfer-encoding; bh=tyda5/BMkExsBfnQGosPF7au0YXFTID4oEeeW0nwZWY=; b=C52vz8ag01bGPjj3CJ+R0BKUdLZCLYb+HZeO1fIJhusDy2YqfXisRAiNxtaKa9H67e okyUwoIbzwccslXG7JeT/QMU7Zp712k1/eb+FSEkuwuApEVpTVsc22+zBkDj87U9l5Cz LEv9qHeEmVQ2uZbhUfvfRSIm59SpGAQ2nvjk4Mb7iMHoCOT7oXwkO0AhARNthkotuoue JqqpX70RPWOdmTkjUkm4rkB/nJWmE9xUe0jrOjNFpo9Nq9GXSPmX3hRr2CVaRCfc30EC azuVraJoTF1rW9EbUDVqVmODul5tkXt3EMH2I/YahpG/j2L43yW/Lgmz/oHdhR+p7tiH vt7w== X-Gm-Message-State: ALoCoQkeN3iU7tJbRKnVUp+DIBJ//OCn1IIGHMmhQYdjYJ+dYKM+JGLHGu+4fM7P9+2YLgO9txXj X-Received: by 10.129.116.84 with SMTP id p81mr1140289ywc.1.1442520261090; Thu, 17 Sep 2015 13:04:21 -0700 (PDT) From: Adhemerval Zanella Subject: [PATCH 07/10] nptl: aarch64: Fix Race conditions in pthread cancellation (BZ#12683) To: GNU C Library Message-ID: <55FB1CC4.7090005@linaro.org> Date: Thu, 17 Sep 2015 17:04:20 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 This patch adds the aarch64 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. --- * sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S: New file. * sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h (PSEUDO): Redefine to call __syscall_cancel function for cancellable syscalls. (__pthread_get_ip): Add implementation. * sysdeps/unix/sysv/linux/aarch64/sysdep.h (SYSCALL_CANCEL_ERROR): Add definition. (SYSCALL_CANCEL_ERRNO): Likewise. -- diff --git a/sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S b/sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S new file mode 100644 index 0000000..56ede8e --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S @@ -0,0 +1,61 @@ +/* Cancellable syscall wrapper - aarch64 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 [r0] __syscall_cancel_arch (int *cancelhandling [x0], + long int nr [x1], + long int arg1 [x2], + long int arg2 [x3], + long int arg3 [x4], + long int arg4 [x5], + long int arg5 [x6], + long int arg6 [x7]) */ + +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() */ + ldr w0, [x0] + tbnz w0, 2, 1f + + /* Issue a 6 argument syscall, the nr [x1] being the syscall + number. */ + mov x8, x1 + mov x0, x2 + mov x1, x3 + mov x2, x4 + mov x3, x5 + mov x4, x6 + mov x5, x7 + svc 0x0 + + .globl __syscall_cancel_arch_end + .type __syscall_cancel_arch_end,@function +__syscall_cancel_arch_end: + ret + +1: + b __syscall_do_cancel + +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h index 36e8e39..71207b3 100644 --- a/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h @@ -20,80 +20,57 @@ #include #ifndef __ASSEMBLER__ # include +# include #endif #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) +# if IS_IN (libc) +# define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel) +# else +# define JMP_SYSCALL_CANCEL __syscall_cancel +# endif + # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ - .section ".text"; \ -ENTRY (__##syscall_name##_nocancel); \ -.Lpseudo_nocancel: \ - DO_CALL (syscall_name, args); \ -.Lpseudo_finish: \ - cmn x0, 4095; \ - b.cs .Lsyscall_error; \ - .subsection 2; \ - .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ ENTRY (name); \ SINGLE_THREAD_P(16); \ - cbz w16, .Lpseudo_nocancel; \ - /* Setup common stack frame no matter the number of args. \ - Also save the first arg, since it's basically free. */ \ - stp x30, x0, [sp, -64]!; \ - cfi_adjust_cfa_offset (64); \ - cfi_rel_offset (x30, 0); \ - DOCARGS_##args; /* save syscall args around CENABLE. */ \ - CENABLE; \ - mov x16, x0; /* save mask around syscall. */ \ - UNDOCARGS_##args; /* restore syscall args. */ \ + cbnz w16, L(pseudo_cancel); \ DO_CALL (syscall_name, args); \ - str x0, [sp, 8]; /* save result around CDISABLE. */ \ - mov x0, x16; /* restore mask for CDISABLE. */ \ - CDISABLE; \ - /* Break down the stack frame, restoring result at once. */ \ - ldp x30, x0, [sp], 64; \ - cfi_adjust_cfa_offset (-64); \ - cfi_restore (x30); \ - b .Lpseudo_finish; \ - cfi_endproc; \ - .size name, .-name; \ - .previous + b L(pseudo_finish); \ +L(pseudo_cancel): \ + stp x29, x30, [sp, -16]!; \ + cfi_def_cfa_offset (16); \ + cfi_offset (29, -16); \ + cfi_offset (30, -8); \ + add x29, sp, 0; \ + cfi_def_cfa_register (29); \ + mov x6, x5; \ + mov x5, x4; \ + mov x4, x3; \ + mov x3, x2; \ + mov x2, x1; \ + mov x1, x0; \ + mov x0, SYS_ify (syscall_name); \ + bl JMP_SYSCALL_CANCEL; \ + ldp x29, x30, [sp], 16; \ + cfi_restore (30); \ + cfi_restore (29); \ + cfi_def_cfa (31, 0); \ +L(pseudo_finish): \ + cmn x0, 4095; \ + b.cs L(syscall_error); # undef PSEUDO_END # define PSEUDO_END(name) \ SYSCALL_ERROR_HANDLER; \ - cfi_endproc - -# define DOCARGS_0 -# define DOCARGS_1 -# define DOCARGS_2 str x1, [sp, 16] -# define DOCARGS_3 stp x1, x2, [sp, 16] -# define DOCARGS_4 DOCARGS_3; str x3, [sp, 32] -# define DOCARGS_5 DOCARGS_3; stp x3, x4, [sp, 32] -# define DOCARGS_6 DOCARGS_5; str x5, [sp, 48] - -# define UNDOCARGS_0 -# define UNDOCARGS_1 ldr x0, [sp, 8] -# define UNDOCARGS_2 ldp x0, x1, [sp, 8] -# define UNDOCARGS_3 UNDOCARGS_1; ldp x1, x2, [sp, 16] -# define UNDOCARGS_4 UNDOCARGS_2; ldp x2, x3, [sp, 24] -# define UNDOCARGS_5 UNDOCARGS_3; ldp x3, x4, [sp, 32] -# define UNDOCARGS_6 UNDOCARGS_4; ldp x4, x5, [sp, 40] + cfi_endproc; \ + .size name, .-name; # if IS_IN (libpthread) -# define CENABLE bl __pthread_enable_asynccancel -# define CDISABLE bl __pthread_disable_asynccancel # define __local_multiple_threads __pthread_multiple_threads # elif IS_IN (libc) -# define CENABLE bl __libc_enable_asynccancel -# define CDISABLE bl __libc_disable_asynccancel # define __local_multiple_threads __libc_multiple_threads -# elif IS_IN (librt) -# define CENABLE bl __librt_enable_asynccancel -# define CDISABLE bl __librt_disable_asynccancel -# else -# error Unsupported library # endif # if IS_IN (libpthread) || IS_IN (libc) @@ -131,4 +108,10 @@ extern int __local_multiple_threads attribute_hidden; # 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) +{ + return uc->uc_mcontext.pc; +} #endif diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep.h b/sysdeps/unix/sysv/linux/aarch64/sysdep.h index fe94a50..5f73b9e 100644 --- a/sysdeps/unix/sysv/linux/aarch64/sysdep.h +++ b/sysdeps/unix/sysv/linux/aarch64/sysdep.h @@ -199,6 +199,14 @@ # undef INTERNAL_SYSCALL_ERRNO # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) +#undef SYSCALL_CANCEL_ERROR +#define SYSCALL_CANCEL_ERROR(__val) \ + ((unsigned long) (__val) >= (unsigned long) -4095) + +#undef SYSCALL_CANCEL_ERRNO +#define SYSCALL_CANCEL_ERRNO(__val) \ + (-(__val)) + # define LOAD_ARGS_0() \ register long _x0 asm ("x0"); # define LOAD_ARGS_1(x0) \