From patchwork Thu Mar 16 12:30:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Elver X-Patchwork-Id: 664354 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 634D2C6FD1F for ; Thu, 16 Mar 2023 12:32:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229678AbjCPMb7 (ORCPT ); Thu, 16 Mar 2023 08:31:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229732AbjCPMb6 (ORCPT ); Thu, 16 Mar 2023 08:31:58 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F7BAC88B4 for ; Thu, 16 Mar 2023 05:31:57 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-541942bfdccso13771087b3.14 for ; Thu, 16 Mar 2023 05:31:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1678969916; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=87DZZv3zvWxq1JNrpUvBlJXCIWW+Rra/IVtOi+lv2AY=; b=qCtLERy62hEhlxSG/0eouCyDubA5IlOQzhKT2mnHloimO+vyrKei3sI8aJq1Tfj3qo 14b4Ounm+uimNdlEK6Gl1oKiwLH2oXLtNv7TDzmIibqjvnhVsYKbFeHnWom15qxZpv7E 5tOLPt/Rhk6QEnPn8W1CABp2zBMKp0CBPEXm1BE2uMklheDAqZWfiip3/rl6zFZvRNo1 r2Z8izryfAq4Y83tOgyd4a84rYY84JZ4Xsr8I1WQTjjxx5eNPvCps/nAEOnaV8B1vU7D 3V/f1c1bck0wJUie1OxMnbvg8BDG+pUfLdOJT4U31Beb6tiecEyvJAK/k9YvtACNmOeC /+tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678969916; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=87DZZv3zvWxq1JNrpUvBlJXCIWW+Rra/IVtOi+lv2AY=; b=nfKv95IGP5nOEhkZ45kHLmqeVf7yaLvcPNT9V+1rp2kVlyctoTctaOgUKcXE24byxX fkQGC/TJDntY7KqU7fv1T9AkK/52SBytz0V7aXD+gszMDQiydK4AAohnBHUtN6NYiK3r yokN8sZoxsEh9RPgEqJ77o3P9P34POZbjvGTI/lnSK7Z3L/9O8iDyvghENwtop0L1Lqg y6LVuVkqKKMNt10WXTjtDGswBlutnJ9ClviVjH0qU1sMxUkaBXoHhlZcucCRmvG4ETRk jUyf3ozFmDb0DekIK9p8bLGwPDsTyd8mxFUXjtZJKwg4wrMBTYYJYZxcRR2oAsIfQ5d7 Zigg== X-Gm-Message-State: AO0yUKXP+tIA0eiIkU7kopgJ2c9vpRvWpCPN0RuY/dxzMTPIg7gJpxza a7ng/QTcPUWGQ+pfxdOaLZ8uqGu2qg== X-Google-Smtp-Source: AK7set8JP+8/fO1CBDiuj35SBYwSWx/12DvLYxR4mHEgN+gX3ZM7tBbPLfdlKovQQ+AeL7C/2ao8pYromw== X-Received: from elver.muc.corp.google.com ([2a00:79e0:9c:201:f359:6b95:96e:1317]) (user=elver job=sendgmr) by 2002:a81:b306:0:b0:541:61aa:9e60 with SMTP id r6-20020a81b306000000b0054161aa9e60mr2038578ywh.6.1678969916701; Thu, 16 Mar 2023 05:31:56 -0700 (PDT) Date: Thu, 16 Mar 2023 13:30:27 +0100 Mime-Version: 1.0 X-Mailer: git-send-email 2.40.0.rc1.284.g88254d51c5-goog Message-ID: <20230316123028.2890338-1-elver@google.com> Subject: [PATCH v6 1/2] posix-timers: Prefer delivery of signals to the current thread From: Marco Elver To: elver@google.com, Peter Zijlstra , Thomas Gleixner , Ingo Molnar Cc: Oleg Nesterov , "Eric W. Biederman" , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Dmitry Vyukov , kasan-dev@googlegroups.com Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Dmitry Vyukov POSIX timers using the CLOCK_PROCESS_CPUTIME_ID clock prefer the main thread of a thread group for signal delivery. However, this has a significant downside: it requires waking up a potentially idle thread. Instead, prefer to deliver signals to the current thread (in the same thread group) if SIGEV_THREAD_ID is not set by the user. This does not change guaranteed semantics, since POSIX process CPU time timers have never guaranteed that signal delivery is to a specific thread (without SIGEV_THREAD_ID set). The effect is that we no longer wake up potentially idle threads, and the kernel is no longer biased towards delivering the timer signal to any particular thread (which better distributes the timer signals esp. when multiple timers fire concurrently). Signed-off-by: Dmitry Vyukov Suggested-by: Oleg Nesterov Reviewed-by: Oleg Nesterov Signed-off-by: Marco Elver Acked-by: Peter Zijlstra (Intel) --- v6: - Split test from this patch. - Update wording on what this patch aims to improve. v5: - Rebased onto v6.2. v4: - Restructured checks in send_sigqueue() as suggested. v3: - Switched to the completely different implementation (much simpler) based on the Oleg's idea. RFC v2: - Added additional Cc as Thomas asked. --- kernel/signal.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index 8cb28f1df294..605445fa27d4 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1003,8 +1003,7 @@ static void complete_signal(int sig, struct task_struct *p, enum pid_type type) /* * Now find a thread we can wake up to take the signal off the queue. * - * If the main thread wants the signal, it gets first crack. - * Probably the least surprising to the average bear. + * Try the suggested task first (may or may not be the main thread). */ if (wants_signal(sig, p)) t = p; @@ -1970,8 +1969,23 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type) ret = -1; rcu_read_lock(); + /* + * This function is used by POSIX timers to deliver a timer signal. + * Where type is PIDTYPE_PID (such as for timers with SIGEV_THREAD_ID + * set), the signal must be delivered to the specific thread (queues + * into t->pending). + * + * Where type is not PIDTYPE_PID, signals must just be delivered to the + * current process. In this case, prefer to deliver to current if it is + * in the same thread group as the target, as it avoids unnecessarily + * waking up a potentially idle task. + */ t = pid_task(pid, type); - if (!t || !likely(lock_task_sighand(t, &flags))) + if (!t) + goto ret; + if (type != PIDTYPE_PID && same_thread_group(t, current)) + t = current; + if (!likely(lock_task_sighand(t, &flags))) goto ret; ret = 1; /* the signal is ignored */ @@ -1993,6 +2007,11 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type) q->info.si_overrun = 0; signalfd_notify(t, sig); + /* + * If the type is not PIDTYPE_PID, we just use shared_pending, which + * won't guarantee that the specified task will receive the signal, but + * is sufficient if t==current in the common case. + */ pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending; list_add_tail(&q->list, &pending->list); sigaddset(&pending->signal, sig); From patchwork Thu Mar 16 12:30:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Elver X-Patchwork-Id: 664674 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8DAD4C6FD19 for ; Thu, 16 Mar 2023 12:32:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229813AbjCPMcF (ORCPT ); Thu, 16 Mar 2023 08:32:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229802AbjCPMcD (ORCPT ); Thu, 16 Mar 2023 08:32:03 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B90ECA1CE for ; Thu, 16 Mar 2023 05:32:01 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id d7-20020a25adc7000000b00953ffdfbe1aso1669590ybe.23 for ; Thu, 16 Mar 2023 05:32:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1678969920; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Wgf7EduwhN6551MQujeSUTn74g+txYbPhrHuCm2tsLY=; b=AyWoKrQzAyrLTzIXGUwTfXlrMUQUEzcdqf58netne9uKl/Mp/DJZVbiMFCi75BVjg+ 37c6H916KKaLMAgkXrmdOY8pnJVXd4UEw39b1nnvb+SPDcNuL1VNWE8CcpNXuYM7sQuJ zyD77kK2ta0teFzQHy6va89aFHW5sPOGNWgZV3p1aK/SSz2v/ay4t5IsUhsPe/LYFgzg n/f5CzIIYi4gIevSJE6Q0bWZMZi42L4mD5RRoh5vBVKr8UHiha9Zev2fizVH/+a7lykf qQQIICCLpehxLMZbHdpUvlgFU0WCE9A2i6/fLSSJVd8/iXqmMiSLyDZdu7DN3D6qQv0k xt0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678969920; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Wgf7EduwhN6551MQujeSUTn74g+txYbPhrHuCm2tsLY=; b=Re4dmS1jGg3R7eLe4+fjW1PMaRFBtp93wf7TT1P2dstgnzkveodXAfGT+xcYOyqAy7 0Vm30/xm5FyLgeL1y1mCs3mPnUia8rMbzK+ZPX6L1+4Y3VPeDSEsXkFSOmARtPcfahXJ CSjHLaWstfwoovjhnDf2kTWoZvun8fDKQEOQgDY/JuovkfOfn8xl/bcCtIDoGvxmhjNC GNPizMRnrKChD0FdnhPvF9ZAY0Gc6Q9ruNJnYUt1SPv9pQtCfS5SnRKajOUU6rpe1u2t 4Z9usjOY4fVx8IbO0JErFYGbRcROxpU9neqAgsoGHGYdeZLfIjdV3it4P5ZuKVN+cyt4 BJdw== X-Gm-Message-State: AO0yUKXIGUeZ6ABFTndu700WSdoNcNpUX4HI8Gn1wC7FmsI3JvwHZb+m k7T9gPJGTtQkQrYb++9Otzl5V/1wiQ== X-Google-Smtp-Source: AK7set/u/hog7qriGRuTm81gsBOhizqGgDKI210by82U6cLVLThJ5+FWaQSPpbb1TmvQ5L53tUN4kqsCHQ== X-Received: from elver.muc.corp.google.com ([2a00:79e0:9c:201:f359:6b95:96e:1317]) (user=elver job=sendgmr) by 2002:a81:e508:0:b0:544:5fc7:f01f with SMTP id s8-20020a81e508000000b005445fc7f01fmr2036499ywl.4.1678969920431; Thu, 16 Mar 2023 05:32:00 -0700 (PDT) Date: Thu, 16 Mar 2023 13:30:28 +0100 In-Reply-To: <20230316123028.2890338-1-elver@google.com> Mime-Version: 1.0 References: <20230316123028.2890338-1-elver@google.com> X-Mailer: git-send-email 2.40.0.rc1.284.g88254d51c5-goog Message-ID: <20230316123028.2890338-2-elver@google.com> Subject: [PATCH v6 2/2] selftests/timers/posix_timers: Test delivery of signals across threads From: Marco Elver To: elver@google.com, Peter Zijlstra , Thomas Gleixner , Ingo Molnar Cc: Oleg Nesterov , "Eric W. Biederman" , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Dmitry Vyukov , kasan-dev@googlegroups.com Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Dmitry Vyukov Test that POSIX timers using CLOCK_PROCESS_CPUTIME_ID eventually deliver a signal to all running threads. This effectively tests that the kernel doesn't prefer any one thread (or subset of threads) for signal delivery. Signed-off-by: Dmitry Vyukov Signed-off-by: Marco Elver --- v6: - Update wording on what the test aims to test. - Fix formatting per checkpatch.pl. --- tools/testing/selftests/timers/posix_timers.c | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c index 0ba500056e63..8a17c0e8d82b 100644 --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c @@ -188,6 +188,80 @@ static int check_timer_create(int which) return 0; } +int remain; +__thread int got_signal; + +static void *distribution_thread(void *arg) +{ + while (__atomic_load_n(&remain, __ATOMIC_RELAXED)); + return NULL; +} + +static void distribution_handler(int nr) +{ + if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED)) + __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED); +} + +/* + * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID + * timer signals. This primarily tests that the kernel does not favour any one. + */ +static int check_timer_distribution(void) +{ + int err, i; + timer_t id; + const int nthreads = 10; + pthread_t threads[nthreads]; + struct itimerspec val = { + .it_value.tv_sec = 0, + .it_value.tv_nsec = 1000 * 1000, + .it_interval.tv_sec = 0, + .it_interval.tv_nsec = 1000 * 1000, + }; + + printf("Check timer_create() per process signal distribution... "); + fflush(stdout); + + remain = nthreads + 1; /* worker threads + this thread */ + signal(SIGALRM, distribution_handler); + err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id); + if (err < 0) { + perror("Can't create timer\n"); + return -1; + } + err = timer_settime(id, 0, &val, NULL); + if (err < 0) { + perror("Can't set timer\n"); + return -1; + } + + for (i = 0; i < nthreads; i++) { + if (pthread_create(&threads[i], NULL, distribution_thread, NULL)) { + perror("Can't create thread\n"); + return -1; + } + } + + /* Wait for all threads to receive the signal. */ + while (__atomic_load_n(&remain, __ATOMIC_RELAXED)); + + for (i = 0; i < nthreads; i++) { + if (pthread_join(threads[i], NULL)) { + perror("Can't join thread\n"); + return -1; + } + } + + if (timer_delete(id)) { + perror("Can't delete timer\n"); + return -1; + } + + printf("[OK]\n"); + return 0; +} + int main(int argc, char **argv) { printf("Testing posix timers. False negative may happen on CPU execution \n"); @@ -217,5 +291,8 @@ int main(int argc, char **argv) if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) return ksft_exit_fail(); + if (check_timer_distribution() < 0) + return ksft_exit_fail(); + return ksft_exit_pass(); }