From patchwork Wed May 26 16:57:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 1484150 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=libc-alpha-bounces@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=A9z2pWc3; dkim-atps=neutral Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fqxwc1Xg4z9sSn for ; Thu, 27 May 2021 02:58:23 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9B0263947436; Wed, 26 May 2021 16:57:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9B0263947436 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1622048270; bh=AXDBXj2vGE9aiPEfxAByhjhcE+bWnsVcNW9mDvSxc50=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=A9z2pWc3IETYVCUTboo5iaQpc/H9s2V8q6txZasboGVIGbwbpGNkj6IY1wq+o08Lw Y8gzAkxCrK4yL1GSaTalbcTOL9znzql1c4CCUJIcTZzjm/oECseC0MYUgqPO0hmGRo Oc1Fy4OaHW7ykmyPi8sqwEQWxDqDm9RTmqAdCzgc= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x82c.google.com (mail-qt1-x82c.google.com [IPv6:2607:f8b0:4864:20::82c]) by sourceware.org (Postfix) with ESMTPS id CF5CE3947427 for ; Wed, 26 May 2021 16:57:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org CF5CE3947427 Received: by mail-qt1-x82c.google.com with SMTP id m13so1372953qtk.13 for ; Wed, 26 May 2021 09:57:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AXDBXj2vGE9aiPEfxAByhjhcE+bWnsVcNW9mDvSxc50=; b=tXR7aiSTeJYlSleJY2F79EwLfz/YXfoAKVYKPSRZLI9M61yX7FjTklgGGw/zZwVuzV ViDAe/1cDDMDv93CYc/B/JNUsGzmcYLSvGKdKi9IVCHrVbISDYXCOdI3fp+Re81H15Rs NdwvC6zNlqGa0Hp0/uYY80FDAaOsmCR4zvotuS9wbUNVDVSNH8z65NL2Fk11ptW9a87u i5+NMgs3DP+aqXXoZo7WpAjPgiv7z29ciw201GYSCGoBB8fteJ0PYZCbd0lnrlDFg/lK lg9s5mL8UrPKJiqCsVcYrGRDpvN/72XEU3sNflufwj4yu1UCgvzokKN8ng8+i2lDG//v LsJg== X-Gm-Message-State: AOAM530Da4M9/iGHReh4UlmfUZ+dAw6aIEWmWvfbaXcd3DLEtytAk/P5 N/+hUIK3OZQke0n8uAv5CK3YfNNzvEzdfw== X-Google-Smtp-Source: ABdhPJxYVV1egoyPq9F/vdwJMBI89UTV0hRa0lr9Y0QLYWO6ZdXv1wDNIyaODukG1X7rG4a/PMUU6g== X-Received: by 2002:ac8:740a:: with SMTP id p10mr11901798qtq.241.1622048266098; Wed, 26 May 2021 09:57:46 -0700 (PDT) Received: from birita.. ([177.194.37.86]) by smtp.googlemail.com with ESMTPSA id k125sm1859761qkf.53.2021.05.26.09.57.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 May 2021 09:57:45 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 10/11] nptl: Implement raise in terms of pthread_kill Date: Wed, 26 May 2021 13:57:27 -0300 Message-Id: <20210526165728.1772546-11-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210526165728.1772546-1-adhemerval.zanella@linaro.org> References: <20210526165728.1772546-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Now that pthread_kill is provided by libc.so it is possible to implement the generic POSIX implementation as 'pthread_kill(pthread_self(), sig)'. For Linux implementation, pthread_kill read the targeting TID from the TCB. For raise, this it not possible because it would make raise fail when issue after vfork (where creates the resulting process has a different TID from the parent, but its TCB is not updated as for pthread_create). To make raise use pthread_kill, it is make usable from vfork by getting the target thread id through gettid syscall. Checked on x86_64-linux-gnu and aarch64-linux-gnu. --- include/pthread.h | 5 ++++ nptl/pthreadP.h | 4 ++- nptl/pthread_kill.c | 40 ++++++++++++++++--------- nptl/pthread_self.c | 4 ++- sysdeps/htl/pthreadP.h | 2 -- sysdeps/posix/raise.c | 11 +++++-- sysdeps/unix/sysv/linux/raise.c | 52 --------------------------------- 7 files changed, 47 insertions(+), 71 deletions(-) delete mode 100644 sysdeps/unix/sysv/linux/raise.c diff --git a/include/pthread.h b/include/pthread.h index a3e1cf51b0..1158919247 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -16,4 +16,9 @@ extern int __pthread_barrier_wait (pthread_barrier_t *__barrier) /* This function is called to initialize the pthread library. */ extern void __pthread_initialize (void) __attribute__ ((weak)); + +extern int __pthread_kill (pthread_t threadid, int signo); + +extern pthread_t __pthread_self (void); + #endif diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 3e7a4f52ab..618922f47a 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -508,11 +508,13 @@ extern int __pthread_once (pthread_once_t *once_control, libc_hidden_proto (__pthread_once) extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void)); -extern pthread_t __pthread_self (void); +libc_hidden_proto (__pthread_self) extern int __pthread_equal (pthread_t thread1, pthread_t thread2); extern int __pthread_detach (pthread_t th); libc_hidden_proto (__pthread_detach) extern int __pthread_kill (pthread_t threadid, int signo); +libc_hidden_proto (__pthread_kill) +extern int __pthread_cancel (pthread_t th); extern void __pthread_exit (void *value) __attribute__ ((__noreturn__)); libc_hidden_proto (__pthread_exit) extern int __pthread_join (pthread_t threadid, void **thread_return); diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c index ad7e011779..0392c3f9e5 100644 --- a/nptl/pthread_kill.c +++ b/nptl/pthread_kill.c @@ -28,24 +28,38 @@ __pthread_kill (pthread_t threadid, int signo) if (__is_internal_signal (signo)) return EINVAL; - /* Force load of pd->tid into local variable or register. Otherwise - if a thread exits between ESRCH test and tgkill, we might return - EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid; struct pthread *pd = (struct pthread *) threadid; - pid_t tid = atomic_forced_read (pd->tid); - if (__glibc_unlikely (tid <= 0)) - /* Not a valid thread handle. */ - return ESRCH; - /* We have a special syscall to do the work. */ - pid_t pid = __getpid (); + if (pd == THREAD_SELF) + tid = INLINE_SYSCALL_CALL (gettid); + else + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + tid = atomic_forced_read (pd->tid); - int val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); - return (INTERNAL_SYSCALL_ERROR_P (val) - ? INTERNAL_SYSCALL_ERRNO (val) : 0); + int val; + if (__glibc_likely (tid > 0)) + { + pid_t pid = __getpid (); + + val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); + val = (INTERNAL_SYSCALL_ERROR_P (val) + ? INTERNAL_SYSCALL_ERRNO (val) : 0); + } + else + val = ESRCH; + + return val; } +/* Some architectures (for instance arm) might pull raise through libgcc, so + avoid the symbol version if it ends up being used on ld.so. */ +#if !IS_IN(rtld) +libc_hidden_def (__pthread_kill) versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34); -#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) +# if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); +# endif #endif diff --git a/nptl/pthread_self.c b/nptl/pthread_self.c index f877a2e6bd..196d93fb8e 100644 --- a/nptl/pthread_self.c +++ b/nptl/pthread_self.c @@ -20,7 +20,9 @@ #include pthread_t -pthread_self (void) +__pthread_self (void) { return (pthread_t) THREAD_SELF; } +libc_hidden_def (__pthread_self) +weak_alias (__pthread_self, pthread_self) diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h index 8e2cf2ce65..3b357b7bdc 100644 --- a/sysdeps/htl/pthreadP.h +++ b/sysdeps/htl/pthreadP.h @@ -31,8 +31,6 @@ extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; /* These represent the interface used by glibc itself. */ -extern pthread_t __pthread_self (void); -extern int __pthread_kill (pthread_t threadid, int signo); extern struct __pthread **__pthread_threads; extern int __pthread_mutex_init (pthread_mutex_t *__mutex, const pthread_mutexattr_t *__attr); diff --git a/sysdeps/posix/raise.c b/sysdeps/posix/raise.c index 9fdb4d538b..4806c0cc63 100644 --- a/sysdeps/posix/raise.c +++ b/sysdeps/posix/raise.c @@ -16,13 +16,20 @@ . */ #include -#include +#include +#include /* Raise the signal SIG. */ int raise (int sig) { - return __kill (__getpid (), sig); + int ret = __pthread_kill (__pthread_self (), sig); + if (ret != 0) + { + __set_errno (ret); + ret = -1; + } + return ret; } libc_hidden_def (raise) weak_alias (raise, gsignal) diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c deleted file mode 100644 index 9be3b37f53..0000000000 --- a/sysdeps/unix/sysv/linux/raise.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2002-2021 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - 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 -#include -#include -#include -#include -#include - -int -raise (int sig) -{ - /* rt_sigprocmask may fail if: - - 1. sigsetsize != sizeof (sigset_t) (EINVAL) - 2. a failure in copy from/to user space (EFAULT) - 3. an invalid 'how' operation (EINVAL) - - The first case is already handle in glibc syscall call by using the arch - defined _NSIG. Second case is handled by using a stack allocated mask. - The last one should be handled by the block/unblock functions. */ - - sigset_t set; - __libc_signal_block_app (&set); - - pid_t pid = INTERNAL_SYSCALL_CALL (getpid); - pid_t tid = INTERNAL_SYSCALL_CALL (gettid); - - int ret = INLINE_SYSCALL_CALL (tgkill, pid, tid, sig); - - __libc_signal_restore_set (&set); - - return ret; -} -libc_hidden_def (raise) -weak_alias (raise, gsignal)