From patchwork Sun Nov 15 18:40:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Wagner X-Patchwork-Id: 324918 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32503C61DD8 for ; Sun, 15 Nov 2020 18:41:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EFF8622450 for ; Sun, 15 Nov 2020 18:41:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727340AbgKOSlK (ORCPT ); Sun, 15 Nov 2020 13:41:10 -0500 Received: from mx2.suse.de ([195.135.220.15]:54436 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726817AbgKOSlK (ORCPT ); Sun, 15 Nov 2020 13:41:10 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 26C37AC90; Sun, 15 Nov 2020 18:41:09 +0000 (UTC) From: Daniel Wagner To: Clark Williams , John Kacur Cc: linux-rt-users@vger.kernel.org, Sebastian Andrzej Siewior , Daniel Wagner Subject: [rt-tests v1 1/3] rt-numa: Move thread placement code to rt-numa library Date: Sun, 15 Nov 2020 19:40:57 +0100 Message-Id: <20201115184059.7286-2-dwagner@suse.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201115184059.7286-1-dwagner@suse.de> References: <20201115184059.7286-1-dwagner@suse.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-rt-users@vger.kernel.org cyclictest contains code for calculating where to place threads accoring the cpumask. Let's move it the rt-numa library to be able to reuse it. Signed-off-by: Daniel Wagner --- src/cyclictest/cyclictest.c | 98 +++---------------------------------- src/include/rt-numa.h | 12 +++++ src/lib/rt-numa.c | 78 +++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 90 deletions(-) diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c index f10f064f7a8e..0a797c540531 100644 --- a/src/cyclictest/cyclictest.c +++ b/src/cyclictest/cyclictest.c @@ -893,12 +893,6 @@ static int interval = DEFAULT_INTERVAL; static int distance = -1; static struct bitmask *affinity_mask = NULL; static int smp = 0; - -enum { - AFFINITY_UNSPECIFIED, - AFFINITY_SPECIFIED, - AFFINITY_USEALL -}; static int setaffinity = AFFINITY_UNSPECIFIED; static int clocksources[] = { @@ -906,72 +900,6 @@ static int clocksources[] = { CLOCK_REALTIME, }; -/* Get available cpus according to getaffinity or according to the - * intersection of getaffinity and the user specified affinity - * in the case of AFFINITY_SPECIFIED, the function has to be called - * after the call to parse_cpumask made in process_options() - */ -static int get_available_cpus(void) -{ - if (affinity_mask) - return numa_bitmask_weight(affinity_mask); - - return numa_num_task_cpus(); -} - -/* cpu_for_thread AFFINITY_SPECIFIED */ -static int cpu_for_thread_sp(int thread_num, int max_cpus) -{ - unsigned int m, cpu, i, num_cpus; - - num_cpus = rt_numa_bitmask_count(affinity_mask); - - if (num_cpus == 0) - fatal("No allowable cpus to run on\n"); - - m = thread_num % num_cpus; - - /* there are num_cpus bits set, we want position of m'th one */ - for (i = 0, cpu = 0; i < max_cpus; i++) { - if (rt_numa_bitmask_isbitset(affinity_mask, i)) { - if (cpu == m) - return i; - cpu++; - } - } - fprintf(stderr, "Bug in cpu mask handling code.\n"); - return 0; -} - -/* cpu_for_thread AFFINITY_USEALL */ -static int cpu_for_thread_ua(int thread_num, int max_cpus) -{ - int res, num_cpus, i, m, cpu; - pthread_t thread; - cpu_set_t cpuset; - - thread = pthread_self(); - CPU_ZERO(&cpuset); - - res = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset); - if (res != 0) - fatal("pthread_getaffinity_np failed: %s\n", strerror(res)); - - num_cpus = CPU_COUNT(&cpuset); - m = thread_num % num_cpus; - - for (i = 0, cpu = 0; i < max_cpus; i++) { - if (CPU_ISSET(i, &cpuset)) { - if (cpu == m) - return i; - cpu++; - } - } - - fprintf(stderr, "Bug in cpu mask handling code.\n"); - return 0; -} - static void handlepolicy(char *polname) { if (strncasecmp(polname, "other", 5) == 0) @@ -1027,20 +955,6 @@ enum option_values { OPT_TRACEMARK, OPT_POSIX_TIMERS, }; -/* numa_available() must be called before any other calls to the numa library */ -static void numa_initialize(void) -{ - static int is_initialized; - - if (is_initialized == 1) - return; - - if (numa_available() != -1) - numa = 1; - - is_initialized = 1; -} - /* Process commandline options */ static void process_options(int argc, char *argv[], int max_cpus) { @@ -1104,7 +1018,9 @@ static void process_options(int argc, char *argv[], int max_cpus) /* smp sets AFFINITY_USEALL in OPT_SMP */ if (smp) break; - numa_initialize(); + if (numa_initialize()) + fatal("Couldn't initilize libnuma"); + numa = 1; if (optarg) { parse_cpumask(optarg, max_cpus, &affinity_mask); setaffinity = AFFINITY_SPECIFIED; @@ -1285,7 +1201,9 @@ static void process_options(int argc, char *argv[], int max_cpus) /* if smp wasn't requested, test for numa automatically */ if (!smp) { - numa_initialize(); + if (numa_initialize()) + fatal("Couldn't initilize libnuma"); + numa = 1; if (setaffinity == AFFINITY_UNSPECIFIED) setaffinity = AFFINITY_USEALL; } @@ -1330,7 +1248,7 @@ static void process_options(int argc, char *argv[], int max_cpus) error = 1; if (num_threads == -1) - num_threads = get_available_cpus(); + num_threads = get_available_cpus(affinity_mask); if (priospread && priority == 0) { fprintf(stderr, "defaulting realtime priority to %d\n", @@ -1998,7 +1916,7 @@ int main(int argc, char **argv) switch (setaffinity) { case AFFINITY_UNSPECIFIED: cpu = -1; break; case AFFINITY_SPECIFIED: - cpu = cpu_for_thread_sp(i, max_cpus); + cpu = cpu_for_thread_sp(i, max_cpus, affinity_mask); if (verbose) printf("Thread %d using cpu %d.\n", i, cpu); break; diff --git a/src/include/rt-numa.h b/src/include/rt-numa.h index 047c8b6257cc..ca86a45dab3a 100644 --- a/src/include/rt-numa.h +++ b/src/include/rt-numa.h @@ -4,6 +4,18 @@ #include +enum { + AFFINITY_UNSPECIFIED, + AFFINITY_SPECIFIED, + AFFINITY_USEALL +}; + +int numa_initialize(void); + +int get_available_cpus(struct bitmask *cpumask); +int cpu_for_thread_sp(int thread_num, int max_cpus, struct bitmask *cpumask); +int cpu_for_thread_ua(int thread_num, int max_cpus); + int parse_cpumask(char *str, int max_cpus, struct bitmask **cpumask); #endif diff --git a/src/lib/rt-numa.c b/src/lib/rt-numa.c index a52a56e8aadd..76f8bd2f0ebe 100644 --- a/src/lib/rt-numa.c +++ b/src/lib/rt-numa.c @@ -6,9 +6,87 @@ #include #include #include +#include +#include +#include "error.h" #include "rt-numa.h" +/* numa_available() must be called before any other calls to the numa library */ +int numa_initialize(void) +{ + static int is_initialized; + + if (is_initialized == 1) + return 0; + + if (numa_available() == -1) + return -1; + + is_initialized = 1; + return 0; +} + +int get_available_cpus(struct bitmask *cpumask) +{ + if (cpumask) + return numa_bitmask_weight(cpumask); + + return numa_num_task_cpus(); +} + +int cpu_for_thread_sp(int thread_num, int max_cpus, struct bitmask *cpumask) +{ + unsigned int m, cpu, i, num_cpus; + + num_cpus = numa_bitmask_weight(cpumask); + + if (num_cpus == 0) + fatal("No allowable cpus to run on\n"); + + m = thread_num % num_cpus; + + /* there are num_cpus bits set, we want position of m'th one */ + for (i = 0, cpu = 0; i < max_cpus; i++) { + if (numa_bitmask_isbitset(cpumask, i)) { + if (cpu == m) + return i; + cpu++; + } + } + fprintf(stderr, "Bug in cpu mask handling code.\n"); + return 0; +} + +/* cpu_for_thread AFFINITY_USEALL */ +int cpu_for_thread_ua(int thread_num, int max_cpus) +{ + int res, num_cpus, i, m, cpu; + pthread_t thread; + cpu_set_t cpuset; + + thread = pthread_self(); + CPU_ZERO(&cpuset); + + res = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset); + if (res != 0) + fatal("pthread_getaffinity_np failed: %s\n", strerror(res)); + + num_cpus = CPU_COUNT(&cpuset); + m = thread_num % num_cpus; + + for (i = 0, cpu = 0; i < max_cpus; i++) { + if (CPU_ISSET(i, &cpuset)) { + if (cpu == m) + return i; + cpu++; + } + } + + fprintf(stderr, "Bug in cpu mask handling code.\n"); + return 0; +} + /* * After this function is called, affinity_mask is the intersection of * the user supplied affinity mask and the affinity mask from the run