From patchwork Tue Apr 12 10:43:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tyler Retzlaff X-Patchwork-Id: 109607 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C4B47A0509; Tue, 12 Apr 2022 12:43:50 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6BD37427ED; Tue, 12 Apr 2022 12:43:46 +0200 (CEST) Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by mails.dpdk.org (Postfix) with ESMTP id 1EA3140DF6 for ; Tue, 12 Apr 2022 12:43:44 +0200 (CEST) Received: by linux.microsoft.com (Postfix, from userid 1086) id 63F652034C73; Tue, 12 Apr 2022 03:43:43 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 63F652034C73 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1649760223; bh=SdTWb618vra0cMDWkcSoSoL7GHSpKNIsQA9hlwxGGYU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oWoI2PT0Ac8fPjPCXbVCUpqQ77vyrkQZHYTLpcLNM+sPLNKTqQswye+Q6mXuIMue7 qIMhozaV/Ha7TgyW+eSepJfX8t8n4pj7NJ6dqcSbCNaqVH1Gyolq9sDdUqFP0NZSzJ 8LO1JDcQCom67Uq1xNPbx0Z7BxLh2xQdqR7HscKY= From: Tyler Retzlaff To: dev@dpdk.org Cc: thomas@monjalon.net, dmitry.kozliuk@gmail.com, anatoly.burakov@intel.com, Tyler Retzlaff , Narcisa Vasile Subject: [PATCH v2 1/4] eal/windows: translate Windows errors to errno-style errors Date: Tue, 12 Apr 2022 03:43:37 -0700 Message-Id: <1649760220-8683-2-git-send-email-roretzla@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> References: <1648819793-18948-1-git-send-email-roretzla@linux.microsoft.com> <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add function to translate Windows error codes to errno-style error codes. The possible return values are chosen so that we have as much semantical compatibility between platforms as possible. Signed-off-by: Narcisa Vasile Signed-off-by: Tyler Retzlaff --- lib/eal/windows/rte_thread.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c index 667287c..c272018 100644 --- a/lib/eal/windows/rte_thread.c +++ b/lib/eal/windows/rte_thread.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright 2021 Mellanox Technologies, Ltd + * Copyright (C) 2022 Microsoft Corporation */ #include @@ -11,6 +12,54 @@ struct eal_tls_key { DWORD thread_index; }; +/* Translates the most common error codes related to threads */ +static int +thread_translate_win32_error(DWORD error) +{ + switch (error) { + case ERROR_SUCCESS: + return 0; + + case ERROR_INVALID_PARAMETER: + return EINVAL; + + case ERROR_INVALID_HANDLE: + return EFAULT; + + case ERROR_NOT_ENOUGH_MEMORY: + /* FALLTHROUGH */ + case ERROR_NO_SYSTEM_RESOURCES: + return ENOMEM; + + case ERROR_PRIVILEGE_NOT_HELD: + /* FALLTHROUGH */ + case ERROR_ACCESS_DENIED: + return EACCES; + + case ERROR_ALREADY_EXISTS: + return EEXIST; + + case ERROR_POSSIBLE_DEADLOCK: + return EDEADLK; + + case ERROR_INVALID_FUNCTION: + /* FALLTHROUGH */ + case ERROR_CALL_NOT_IMPLEMENTED: + return ENOSYS; + } + + return EINVAL; +} + +static int +thread_log_last_error(const char *message) +{ + DWORD error = GetLastError(); + RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message); + + return thread_translate_win32_error(error); +} + int rte_thread_key_create(rte_thread_key *key, __rte_unused void (*destructor)(void *)) From patchwork Tue Apr 12 10:43:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tyler Retzlaff X-Patchwork-Id: 109608 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C9735A0509; Tue, 12 Apr 2022 12:43:55 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5587A427FC; Tue, 12 Apr 2022 12:43:47 +0200 (CEST) Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by mails.dpdk.org (Postfix) with ESMTP id 2314340E03 for ; Tue, 12 Apr 2022 12:43:44 +0200 (CEST) Received: by linux.microsoft.com (Postfix, from userid 1086) id 7029320A6925; Tue, 12 Apr 2022 03:43:43 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 7029320A6925 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1649760223; bh=IjYmSzwgiThoMwit8p1nMw05kQ64ZJKGuAJ+ULlhZEs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SpInfG7acQG6K3EQ7hCeQYZNG3eJcEAva+3sjWMi0uvX9yp80QHKIm+yx8L8WF1o9 uz4170nWtkWGQcZSOBFxLZjndNtjy9xnU8CIabw+IeuOmxI9GBsFRQNkg8638A+SJK ruPenlQPXNOy9ROgFuANtjGDuo/uzV6S8pXK5ohQ= From: Tyler Retzlaff To: dev@dpdk.org Cc: thomas@monjalon.net, dmitry.kozliuk@gmail.com, anatoly.burakov@intel.com, Tyler Retzlaff , Narcisa Vasile Subject: [PATCH v2 2/4] eal: add basic thread ID and current thread identifier API Date: Tue, 12 Apr 2022 03:43:38 -0700 Message-Id: <1649760220-8683-3-git-send-email-roretzla@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> References: <1648819793-18948-1-git-send-email-roretzla@linux.microsoft.com> <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Provide a portable type-safe thread identifier. Provide rte_thread_self for obtaining current thread identifier. Signed-off-by: Narcisa Vasile Signed-off-by: Tyler Retzlaff --- lib/eal/include/rte_thread.h | 22 ++++++++++++++++++++++ lib/eal/unix/rte_thread.c | 11 +++++++++++ lib/eal/version.map | 3 +++ lib/eal/windows/rte_thread.c | 10 ++++++++++ 4 files changed, 46 insertions(+) diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h index 8be8ed8..fb66d9a 100644 --- a/lib/eal/include/rte_thread.h +++ b/lib/eal/include/rte_thread.h @@ -1,7 +1,10 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2021 Mellanox Technologies, Ltd + * Copyright (C) 2022 Microsoft Corporation */ +#include + #include #include @@ -21,10 +24,29 @@ #endif /** + * Thread id descriptor. + */ +typedef struct rte_thread_tag { + uintptr_t opaque_id; /**< thread identifier */ +} rte_thread_t; + +/** * TLS key type, an opaque pointer. */ typedef struct eal_tls_key *rte_thread_key; +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Get the id of the calling thread. + * + * @return + * Return the thread id of the calling thread. + */ +__rte_experimental +rte_thread_t rte_thread_self(void); + #ifdef RTE_HAS_CPUSET /** diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c index c34ede9..82e008f 100644 --- a/lib/eal/unix/rte_thread.c +++ b/lib/eal/unix/rte_thread.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright 2021 Mellanox Technologies, Ltd + * Copyright (C) 2022 Microsoft Corporation */ #include @@ -15,6 +16,16 @@ struct eal_tls_key { pthread_key_t thread_index; }; +rte_thread_t +rte_thread_self(void) +{ + rte_thread_t thread_id; + + thread_id.opaque_id = (uintptr_t)pthread_self(); + + return thread_id; +} + int rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *)) { diff --git a/lib/eal/version.map b/lib/eal/version.map index b53eeb3..05ce8f9 100644 --- a/lib/eal/version.map +++ b/lib/eal/version.map @@ -420,6 +420,9 @@ EXPERIMENTAL { rte_intr_instance_free; rte_intr_type_get; rte_intr_type_set; + + # added in 22.07 + rte_thread_self; }; INTERNAL { diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c index c272018..d730bb4 100644 --- a/lib/eal/windows/rte_thread.c +++ b/lib/eal/windows/rte_thread.c @@ -60,6 +60,16 @@ struct eal_tls_key { return thread_translate_win32_error(error); } +rte_thread_t +rte_thread_self(void) +{ + rte_thread_t thread_id; + + thread_id.opaque_id = GetCurrentThreadId(); + + return thread_id; +} + int rte_thread_key_create(rte_thread_key *key, __rte_unused void (*destructor)(void *)) From patchwork Tue Apr 12 10:43:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tyler Retzlaff X-Patchwork-Id: 109609 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 402B1A0509; Tue, 12 Apr 2022 12:44:01 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 31AC042802; Tue, 12 Apr 2022 12:43:48 +0200 (CEST) Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by mails.dpdk.org (Postfix) with ESMTP id 2CD1E410E1 for ; Tue, 12 Apr 2022 12:43:44 +0200 (CEST) Received: by linux.microsoft.com (Postfix, from userid 1086) id 7CDC520BE4A2; Tue, 12 Apr 2022 03:43:43 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 7CDC520BE4A2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1649760223; bh=0B/wLBgTVQf55A/yAo4F8c0X72LGahjqW0XPtBtJEcw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XQm47OEGPjOxynR6YjeJtzpG9fIBnL29WoaYEeZbnOPWaxQTGh+CG0E6N2I7kWmkf mXmcUv6CRlKLjBEmqS7SqEJJ3KXqQXxYZflxg3miwS5/B5kmUKOYNfOIrItrKDHehq 1h5jUgtKppL1IJIYkAGS3p+Zlb6ju8ClyshSxEyE= From: Tyler Retzlaff To: dev@dpdk.org Cc: thomas@monjalon.net, dmitry.kozliuk@gmail.com, anatoly.burakov@intel.com, Tyler Retzlaff , Narcisa Vasile Subject: [PATCH v2 3/4] eal: implement functions for get/set thread affinity Date: Tue, 12 Apr 2022 03:43:39 -0700 Message-Id: <1649760220-8683-4-git-send-email-roretzla@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> References: <1648819793-18948-1-git-send-email-roretzla@linux.microsoft.com> <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Implement functions for getting/setting thread affinity. Threads can be pinned to specific cores by setting their affinity attribute. note: rte_convert_cpuset_to_affinity has a limitation that all cpus of the set belong to the same processor group. Signed-off-by: Narcisa Vasile Signed-off-by: Tyler Retzlaff --- lib/eal/include/rte_thread.h | 42 ++++++++++ lib/eal/unix/rte_thread.c | 16 ++++ lib/eal/version.map | 2 + lib/eal/windows/eal_lcore.c | 173 +++++++++++++++++++++++++++++---------- lib/eal/windows/eal_windows.h | 10 +++ lib/eal/windows/include/rte_os.h | 2 + lib/eal/windows/rte_thread.c | 131 ++++++++++++++++++++++++++++- 7 files changed, 331 insertions(+), 45 deletions(-) diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h index fb66d9a..c26ca1d 100644 --- a/lib/eal/include/rte_thread.h +++ b/lib/eal/include/rte_thread.h @@ -50,6 +50,48 @@ #ifdef RTE_HAS_CPUSET /** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Set the affinity of thread 'thread_id' to the cpu set + * specified by 'cpuset'. + * + * @param thread_id + * Id of the thread for which to set the affinity. + * + * @param cpuset + * Pointer to CPU affinity to set. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_set_affinity_by_id(rte_thread_t thread_id, + const rte_cpuset_t *cpuset); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Get the affinity of thread 'thread_id' and store it + * in 'cpuset'. + * + * @param thread_id + * Id of the thread for which to get the affinity. + * + * @param cpuset + * Pointer for storing the affinity value. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_get_affinity_by_id(rte_thread_t thread_id, + rte_cpuset_t *cpuset); + +/** * Set core affinity of the current thread. * Support both EAL and non-EAL thread and update TLS. * diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c index 82e008f..c64198f 100644 --- a/lib/eal/unix/rte_thread.c +++ b/lib/eal/unix/rte_thread.c @@ -100,3 +100,19 @@ struct eal_tls_key { } return pthread_getspecific(key->thread_index); } + +int +rte_thread_set_affinity_by_id(rte_thread_t thread_id, + const rte_cpuset_t *cpuset) +{ + return pthread_setaffinity_np((pthread_t)thread_id.opaque_id, + sizeof(*cpuset), cpuset); +} + +int +rte_thread_get_affinity_by_id(rte_thread_t thread_id, + rte_cpuset_t *cpuset) +{ + return pthread_getaffinity_np((pthread_t)thread_id.opaque_id, + sizeof(*cpuset), cpuset); +} diff --git a/lib/eal/version.map b/lib/eal/version.map index 05ce8f9..d49e30b 100644 --- a/lib/eal/version.map +++ b/lib/eal/version.map @@ -422,7 +422,9 @@ EXPERIMENTAL { rte_intr_type_set; # added in 22.07 + rte_thread_get_affinity_by_id; rte_thread_self; + rte_thread_set_affinity_by_id; }; INTERNAL { diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c index 476c2d2..4f2224e 100644 --- a/lib/eal/windows/eal_lcore.c +++ b/lib/eal/windows/eal_lcore.c @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2019 Intel Corporation + * Copyright (C) 2022 Microsoft Corporation */ -#include #include #include @@ -27,13 +27,15 @@ struct socket_map { }; struct cpu_map { - unsigned int socket_count; unsigned int lcore_count; + unsigned int socket_count; + unsigned int cpu_count; struct lcore_map lcores[RTE_MAX_LCORE]; struct socket_map sockets[RTE_MAX_NUMA_NODES]; + GROUP_AFFINITY cpus[CPU_SETSIZE]; }; -static struct cpu_map cpu_map = { 0 }; +static struct cpu_map cpu_map; /* eal_create_cpu_map() is called before logging is initialized */ static void @@ -47,13 +49,115 @@ struct cpu_map { va_end(va); } +static int +eal_query_group_affinity(void) +{ + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL; + unsigned int *cpu_count = &cpu_map.cpu_count; + DWORD infos_size = 0; + int ret = 0; + USHORT group_count; + KAFFINITY affinity; + USHORT group_no; + unsigned int i; + + if (!GetLogicalProcessorInformationEx(RelationGroup, NULL, + &infos_size)) { + DWORD error = GetLastError(); + if (error != ERROR_INSUFFICIENT_BUFFER) { + log_early("Cannot get group information size, error %lu\n", error); + rte_errno = EINVAL; + ret = -1; + goto cleanup; + } + } + + infos = malloc(infos_size); + if (infos == NULL) { + log_early("Cannot allocate memory for NUMA node information\n"); + rte_errno = ENOMEM; + ret = -1; + goto cleanup; + } + + if (!GetLogicalProcessorInformationEx(RelationGroup, infos, + &infos_size)) { + log_early("Cannot get group information, error %lu\n", + GetLastError()); + rte_errno = EINVAL; + ret = -1; + goto cleanup; + } + + *cpu_count = 0; + group_count = infos->Group.ActiveGroupCount; + for (group_no = 0; group_no < group_count; group_no++) { + affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask; + for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) { + if ((affinity & ((KAFFINITY)1 << i)) == 0) + continue; + cpu_map.cpus[*cpu_count].Group = group_no; + cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i; + (*cpu_count)++; + } + } + +cleanup: + free(infos); + return ret; +} + +static bool +eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info) +{ + const unsigned int node_id = info->NumaNode.NodeNumber; + const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask; + struct lcore_map *lcore; + unsigned int socket_id; + unsigned int i; + + /* + * NUMA node may be reported multiple times if it includes + * cores from different processor groups, e. g. 80 cores + * of a physical processor comprise one NUMA node, but two + * processor groups, because group size is limited by 32/64. + */ + for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) + if (cpu_map.sockets[socket_id].node_id == node_id) + break; + + if (socket_id == cpu_map.socket_count) { + if (socket_id == RTE_DIM(cpu_map.sockets)) + return true; + + cpu_map.sockets[socket_id].node_id = node_id; + cpu_map.socket_count++; + } + + for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) { + if ((cores->Mask & ((KAFFINITY)1 << i)) == 0) + continue; + + if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) + return true; + + lcore = &cpu_map.lcores[cpu_map.lcore_count]; + lcore->socket_id = socket_id; + lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i; + cpu_map.lcore_count++; + } + return false; +} + int eal_create_cpu_map(void) { SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info; DWORD infos_size; bool full = false; + int ret = 0; + infos = NULL; infos_size = 0; if (!GetLogicalProcessorInformationEx( RelationNumaNode, NULL, &infos_size)) { @@ -62,7 +166,8 @@ struct cpu_map { log_early("Cannot get NUMA node info size, error %lu\n", GetLastError()); rte_errno = ENOMEM; - return -1; + ret = -1; + goto exit; } } @@ -83,52 +188,24 @@ struct cpu_map { info = infos; while ((uint8_t *)info - (uint8_t *)infos < infos_size) { - unsigned int node_id = info->NumaNode.NodeNumber; - GROUP_AFFINITY *cores = &info->NumaNode.GroupMask; - struct lcore_map *lcore; - unsigned int i, socket_id; - - /* NUMA node may be reported multiple times if it includes - * cores from different processor groups, e. g. 80 cores - * of a physical processor comprise one NUMA node, but two - * processor groups, because group size is limited by 32/64. - */ - for (socket_id = 0; socket_id < cpu_map.socket_count; - socket_id++) { - if (cpu_map.sockets[socket_id].node_id == node_id) - break; - } - - if (socket_id == cpu_map.socket_count) { - if (socket_id == RTE_DIM(cpu_map.sockets)) { - full = true; - goto exit; - } - - cpu_map.sockets[socket_id].node_id = node_id; - cpu_map.socket_count++; - } - - for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) { - if ((cores->Mask & ((KAFFINITY)1 << i)) == 0) - continue; - - if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) { - full = true; - goto exit; - } - - lcore = &cpu_map.lcores[cpu_map.lcore_count]; - lcore->socket_id = socket_id; - lcore->core_id = - cores->Group * EAL_PROCESSOR_GROUP_SIZE + i; - cpu_map.lcore_count++; + if (eal_create_lcore_map(info)) { + full = true; + break; } info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)( (uint8_t *)info + info->Size); } + if (eal_query_group_affinity()) { + /* + * No need to set rte_errno here. + * It is set by eal_query_group_affinity(). + */ + ret = -1; + goto exit; + } + exit: if (full) { /* Not a fatal error, but important for troubleshooting. */ @@ -164,3 +241,11 @@ struct cpu_map { { return cpu_map.sockets[socket_id].node_id; } + +PGROUP_AFFINITY +eal_get_cpu_affinity(size_t cpu_index) +{ + RTE_VERIFY(cpu_index < CPU_SETSIZE); + + return &cpu_map.cpus[cpu_index]; +} diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h index 245aa60..c96eca5 100644 --- a/lib/eal/windows/eal_windows.h +++ b/lib/eal/windows/eal_windows.h @@ -56,6 +56,16 @@ unsigned int eal_socket_numa_node(unsigned int socket_id); /** + * Get pointer to the group affinity for the cpu. + * + * @param cpu_index + * Index of the cpu, as it comes from rte_cpuset_t. + * @return + * Pointer to the group affinity for the cpu. + */ +PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index); + +/** * Schedule code for execution in the interrupt thread. * * @param func diff --git a/lib/eal/windows/include/rte_os.h b/lib/eal/windows/include/rte_os.h index a0a3114..1c33058 100644 --- a/lib/eal/windows/include/rte_os.h +++ b/lib/eal/windows/include/rte_os.h @@ -14,6 +14,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c index d730bb4..032b09f 100644 --- a/lib/eal/windows/rte_thread.c +++ b/lib/eal/windows/rte_thread.c @@ -6,7 +6,8 @@ #include #include #include -#include + +#include "eal_windows.h" struct eal_tls_key { DWORD thread_index; @@ -146,3 +147,131 @@ struct eal_tls_key { } return output; } + +static int +rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset, + PGROUP_AFFINITY affinity) +{ + int ret = 0; + PGROUP_AFFINITY cpu_affinity = NULL; + unsigned int cpu_idx; + + memset(affinity, 0, sizeof(GROUP_AFFINITY)); + affinity->Group = (USHORT)-1; + + /* Check that all cpus of the set belong to the same processor group and + * accumulate thread affinity to be applied. + */ + for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) { + if (!CPU_ISSET(cpu_idx, cpuset)) + continue; + + cpu_affinity = eal_get_cpu_affinity(cpu_idx); + + if (affinity->Group == (USHORT)-1) { + affinity->Group = cpu_affinity->Group; + } else if (affinity->Group != cpu_affinity->Group) { + ret = ENOTSUP; + goto cleanup; + } + + affinity->Mask |= cpu_affinity->Mask; + } + + if (affinity->Mask == 0) { + ret = EINVAL; + goto cleanup; + } + +cleanup: + return ret; +} + +int +rte_thread_set_affinity_by_id(rte_thread_t thread_id, + const rte_cpuset_t *cpuset) +{ + int ret = 0; + GROUP_AFFINITY thread_affinity; + HANDLE thread_handle = NULL; + + if (cpuset == NULL) { + ret = EINVAL; + goto cleanup; + } + + ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity); + if (ret != 0) { + RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n"); + goto cleanup; + } + + thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, + thread_id.opaque_id); + if (thread_handle == NULL) { + ret = thread_log_last_error("OpenThread()"); + goto cleanup; + } + + if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) { + ret = thread_log_last_error("SetThreadGroupAffinity()"); + goto cleanup; + } + +cleanup: + if (thread_handle != NULL) { + CloseHandle(thread_handle); + thread_handle = NULL; + } + + return ret; +} + +int +rte_thread_get_affinity_by_id(rte_thread_t thread_id, + rte_cpuset_t *cpuset) +{ + HANDLE thread_handle = NULL; + PGROUP_AFFINITY cpu_affinity; + GROUP_AFFINITY thread_affinity; + unsigned int cpu_idx; + int ret = 0; + + if (cpuset == NULL) { + ret = EINVAL; + goto cleanup; + } + + thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, + thread_id.opaque_id); + if (thread_handle == NULL) { + ret = thread_log_last_error("OpenThread()"); + goto cleanup; + } + + /* obtain previous thread affinity */ + if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) { + ret = thread_log_last_error("GetThreadGroupAffinity()"); + goto cleanup; + } + + CPU_ZERO(cpuset); + + /* Convert affinity to DPDK cpu set */ + for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) { + + cpu_affinity = eal_get_cpu_affinity(cpu_idx); + + if ((cpu_affinity->Group == thread_affinity.Group) && + ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) { + CPU_SET(cpu_idx, cpuset); + } + } + +cleanup: + if (thread_handle != NULL) { + CloseHandle(thread_handle); + thread_handle = NULL; + } + return ret; +} From patchwork Tue Apr 12 10:43:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tyler Retzlaff X-Patchwork-Id: 109610 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 88AD1A0509; Tue, 12 Apr 2022 12:44:06 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2A50D42805; Tue, 12 Apr 2022 12:43:49 +0200 (CEST) Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by mails.dpdk.org (Postfix) with ESMTP id 3185541611 for ; Tue, 12 Apr 2022 12:43:44 +0200 (CEST) Received: by linux.microsoft.com (Postfix, from userid 1086) id 8920420A692A; Tue, 12 Apr 2022 03:43:43 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 8920420A692A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1649760223; bh=9I9Z1TqpHIsU62LYCeZMOImOHdJUNHCSQ3M66bC9JPk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S/KbVrbGK2hSUOHIP60nD/LxZle3RdEAH5LXUo5otdjbqEDyFUoftA9UCKx6+Lz1y O3jXtwyfe8VQ2gLoLRAEHLcUDRtRFAZK0GZpozNU+1w8JxuDXvulqwtyx2IfRMDbPN HYTv4TomKRE7MUFnZZf4nULRMhxUnpPUXnPE0b7o= From: Tyler Retzlaff To: dev@dpdk.org Cc: thomas@monjalon.net, dmitry.kozliuk@gmail.com, anatoly.burakov@intel.com, Tyler Retzlaff , Narcisa Vasile Subject: [PATCH v2 4/4] test/threads: add unit test for thread API Date: Tue, 12 Apr 2022 03:43:40 -0700 Message-Id: <1649760220-8683-5-git-send-email-roretzla@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> References: <1648819793-18948-1-git-send-email-roretzla@linux.microsoft.com> <1649760220-8683-1-git-send-email-roretzla@linux.microsoft.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Establish unit test for testing thread api. Initial unit tests for rte_thread_{get,set}_affinity_by_id(). Signed-off-by: Narcisa Vasile Signed-off-by: Tyler Retzlaff --- app/test/meson.build | 2 ++ app/test/test_threads.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 app/test/test_threads.c diff --git a/app/test/meson.build b/app/test/meson.build index 5fc1dd1..5a9d69b 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -133,6 +133,7 @@ test_sources = files( 'test_tailq.c', 'test_thash.c', 'test_thash_perf.c', + 'test_threads.c', 'test_timer.c', 'test_timer_perf.c', 'test_timer_racecond.c', @@ -238,6 +239,7 @@ fast_tests = [ ['reorder_autotest', true], ['service_autotest', true], ['thash_autotest', true], + ['threads_autotest', true], ['trace_autotest', true], ] diff --git a/app/test/test_threads.c b/app/test/test_threads.c new file mode 100644 index 0000000..0ca6745 --- /dev/null +++ b/app/test/test_threads.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2022 Microsoft Corporation + */ + +#include +#include + +#include +#include + +#include "test.h" + +RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO); + +static uint32_t thread_id_ready; + +static void * +thread_main(void *arg) +{ + *(rte_thread_t *)arg = rte_thread_self(); + __atomic_store_n(&thread_id_ready, 1, __ATOMIC_RELEASE); + + return NULL; +} + +static int +test_thread_affinity(void) +{ + pthread_t id; + rte_thread_t thread_id; + + RTE_TEST_ASSERT(pthread_create(&id, NULL, thread_main, &thread_id) == 0, + "Failed to create thread"); + + while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) + ; + + rte_cpuset_t cpuset0; + RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset0) == 0, + "Failed to get thread affinity"); + + rte_cpuset_t cpuset1; + RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0, + "Failed to get thread affinity"); + RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, + "Affinity should be stable"); + + RTE_TEST_ASSERT(rte_thread_set_affinity_by_id(thread_id, &cpuset1) == 0, + "Failed to set thread affinity"); + RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset0) == 0, + "Failed to get thread affinity"); + RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, + "Affinity should be stable"); + + size_t i; + for (i = 1; i < CPU_SETSIZE; i++) + if (CPU_ISSET(i, &cpuset0)) { + CPU_ZERO(&cpuset0); + CPU_SET(i, &cpuset0); + + break; + } + RTE_TEST_ASSERT(rte_thread_set_affinity_by_id(thread_id, &cpuset0) == 0, + "Failed to set thread affinity"); + RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0, + "Failed to get thread affinity"); + RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, + "Affinity should be stable"); + + return 0; +} + +static struct unit_test_suite threads_test_suite = { + .suite_name = "threads autotest", + .setup = NULL, + .teardown = NULL, + .unit_test_cases = { + TEST_CASE(test_thread_affinity), + TEST_CASES_END() + } +}; + +static int +test_threads(void) +{ + return unit_test_suite_runner(&threads_test_suite); +} + +REGISTER_TEST_COMMAND(threads_autotest, test_threads);