From patchwork Fri Aug 9 20:14:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Mattias_R=C3=B6nnblom?= X-Patchwork-Id: 143058 X-Patchwork-Delegate: thomas@monjalon.net 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 B39314577D; Fri, 9 Aug 2024 22:24:42 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1EF6F42E7B; Fri, 9 Aug 2024 22:24:23 +0200 (CEST) Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2068.outbound.protection.outlook.com [40.107.21.68]) by mails.dpdk.org (Postfix) with ESMTP id B7BFC42E58 for ; Fri, 9 Aug 2024 22:24:19 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=iTSNuMpdNR9P0soIF7jzGrIW67xqUhEI/Pj/h4jHOKeDk0gEgXp5KEmJmZfCIp08qCX/Ji0u7Ws074x1qaZsSKiUJauKb3E78kVeuzL2gsuWzwL/BkGYkUVQ8s08n6ir/fgDdhf7y+D5jIOX6Ysun5IWnwoINPuYKVz4eLUSwWZ4cTGHG0BN24ydQ4KqofKQvpcPliLYpb9eJ9Uo3iTwOAuRm4Q/Csv5V9ZIw4Y7rJYWuQnWxhWwKVN2BMl8A5Xu/sBzth9q795dYqPI+RBKSGMJNWknwb9XLuB4pH/QenQj3qAHETYwC+3Q0bOqEc2OAnDbu1+SPWmrFFu3IUWKxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=svYx6gam6T3RMnkg67LL2UGDesVvmCuWPnXiZeaRMtU=; b=mz4pTkao1vEw4MQHS15C15IYZ6nMlRb6Lq48j371D6c+WmgkJox2gjRu5uHlftcuh1M+f2V62UCs49r0RrucORRCXixnDh5FBQRG1sFOi1D+lf2xqjrPJAYp63ICpV76ZmPjDGh4PSupnMtqMDAfEzAS4n7vkDCqJ1a/6SVMe64vzINa+pwO2Jhbj1bmBvOFs5vBTorhHWF7B9/zD57hhldcH77KpKRnoa6rex699HBBMHTxPT6z+4x9qEKQWgZ2ZEOfqB1OdNModAk/gTleXiwezUASiw/XCH8Dq0On70HC5fj45iCkoY2TcSPiWQ2lrOIcDeEcWLjsL9gJxXDYKg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=svYx6gam6T3RMnkg67LL2UGDesVvmCuWPnXiZeaRMtU=; b=VjAEE5qGvODXUfD4ZLwVTIsRhzbTaZdc1FzyV+/JMaP5eF5IDnmr9yxJXs+k+LVppe7UNefERYzvX+DPPmjqDsPSsJs7NF5EyCxSjnbAML5dU3sdlVt8x75wVKJ7SwJctXTkSyvJWSRLtNLPcpuGOqFIkB6yAljTM9+xK+BoD6oNrC7WFYqBMfgdlblrpzDiyBTbt16nXZdbE6gQ2eV2knRyugsd1ziDjg+Gtv5y1jkDQPHuJdmPlqb5b+mDxaQ5B4jJqZN99DV5EoY1i2REPjqWSMG5yfLrjC4Sjs5ZP6sgK8MnM6wtvmFMrL2g60aYx0WY+u5Uz50iNmfWXSiJAg== Received: from DUZP191CA0069.EURP191.PROD.OUTLOOK.COM (2603:10a6:10:4fa::22) by DBAPR07MB6872.eurprd07.prod.outlook.com (2603:10a6:10:17c::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.15; Fri, 9 Aug 2024 20:24:16 +0000 Received: from DB5PEPF00014B94.eurprd02.prod.outlook.com (2603:10a6:10:4fa:cafe::51) by DUZP191CA0069.outlook.office365.com (2603:10a6:10:4fa::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.14 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by DB5PEPF00014B94.mail.protection.outlook.com (10.167.8.232) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.8 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.60) with Microsoft SMTP Server id 15.2.1544.11; Fri, 9 Aug 2024 22:24:15 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id 73BD71C006A; Fri, 9 Aug 2024 22:24:15 +0200 (CEST) From: =?utf-8?q?Mattias_R=C3=B6nnblom?= To: CC: , =?utf-8?q?Morten_Br=C3=B8rup?= , Tyler Retzlaff , Stephen Hemminger , Harry van Haaren , =?utf-8?q?Mattias_R=C3=B6nnb?= =?utf-8?q?lom?= Subject: [PATCH 1/6] eal: add bitset type Date: Fri, 9 Aug 2024 22:14:35 +0200 Message-ID: <20240809201440.590464-1-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> References: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB5PEPF00014B94:EE_|DBAPR07MB6872:EE_ X-MS-Office365-Filtering-Correlation-Id: 4de876fb-c6ff-4e3c-58d3-08dcb8b13d96 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|376014|82310400026|36860700013; X-Microsoft-Antispam-Message-Info: =?utf-8?q?9B2KWkC2tsrUEht4thZgmbwW6EePhy0?= =?utf-8?q?HlODba4U9iY3yznlygNKMac6NThNVYtLNd70EQYkK+6x6H2x7+B98I4V9kyJj3DYE?= =?utf-8?q?r6gbZSbbAFCpX2BS+WJUamKke6tVTCkcH7C4fv0dTcBnBY73J0WrsfgS9cjxOQNV6?= =?utf-8?q?VG+UN6NYcINT38eF0koUFCVLzcODdmCq7QJUPIXHv4e3tP6dx7MvkAYoTPc/gw1pY?= =?utf-8?q?NIGFi1vXrtgyVYZQZEoxksvr+SjcHSGb1Kvlco6hUVuaPTpSXDz3IiF5DjAx5YlgY?= =?utf-8?q?AwbkpkuSzuEeXPD7CSEpqwvlcPTWva2W7e4usjQmlztL+gt0U/IFTBB70BRh1fD+d?= =?utf-8?q?DrStUf+dgVsGMQn61Fnx1xf4I9vh2vj0ctyfKbe27FCSrQdSN1+RPmnroCfpbmAi+?= =?utf-8?q?bY6FUdOugNiM3y7X1AZb+Vobk1EpkqHQnmbp7VENR4aL4/A2zjn9I25FSCDEdcZie?= =?utf-8?q?I1NbvuQy2n+vda5gL1ICWNqqDNUyly5r9Uo+iCam1cdLbUTkuG3QdZh+eM+805POH?= =?utf-8?q?myidXKg5ulId9TiJJKlHd6KCanCXDXGC03nGx7zhlQyHNJC2PmpUvqwGdDrkEYaS7?= =?utf-8?q?KrkrBqe0zBOThpV4PQBFr1SUZStGkZMHkJddtTsceYgFvmv3LsOrWSulCkT97TRp3?= =?utf-8?q?RQDNV86dO8FdRDtxVLlEceMLRBh7IkfQIg/jgf62Dp2omkjydzdAimEchpsOH0t4B?= =?utf-8?q?tSwDp6T70NduByEZXaDVIQxk/bcbXEBoZELL/xBAPJgvsBCYeIwUaE++aOueRvr5O?= =?utf-8?q?L/9CRMuGQt4i50ZpGKfxrTLzAuDgpKKOW9hbCbIFdLpSK0QnNIsPtwYotwRQxO3Wo?= =?utf-8?q?54llJJM+tdbNcdHc4DXKfEm0UD8YACXdlX1NvGFwI5rayjB5Qu69UE+6spI9PZO9q?= =?utf-8?q?yRSABuX0a2XxuqURcmaFHQ7msvo95mHavOgEVXIMLnH/4o7KiycRXW0net84L0f/h?= =?utf-8?q?GJ15vHg2rLn5E0pcO0UTHYiVAHNRbveVVhrV4GtlGtfptWh4Rt3MOCO9aWWSBtUcJ?= =?utf-8?q?TXa7FJcLZi92Wc70FuZ9Wx1KGyTZklXTZ5l13LO7z4mlGUiYFpezKFqwzSjT5tBNU?= =?utf-8?q?qO7DLo7ghAPkHGQ39THVUd9C6/fyaghWGdIlOlWeLXB9FsxnmGQKEyAmoNmsaB9lM?= =?utf-8?q?MmV9nvG/rrXGvNSI4ZnmbGenn53gsWYjON7jlSEWLbpFdQLfHKK4krOg54D/6nffc?= =?utf-8?q?iNlHSokSLPHcBVowBb6IEBKO+Sm7xWRQMvVGTuKhSV5BQRHF2D0mzGp09D4ccRPwt?= =?utf-8?q?hxu0D/H3SQlhnGFnNqmE/by4pm9Ar8wlqLNnoiFvfptnYTHC++c4f6e9U2h1MaE+3?= =?utf-8?q?cg2sFqeFzsETv012WcTMVfTIRzJw2iNb9g=3D=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(1800799024)(376014)(82310400026)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 20:24:16.0970 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4de876fb-c6ff-4e3c-58d3-08dcb8b13d96 X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: DB5PEPF00014B94.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBAPR07MB6872 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 Introduce a set of functions and macros that operate on sets of bits, kept in arrays of 64-bit words. RTE bitset is designed for bitsets which are larger than what fits in a single machine word (i.e., 64 bits). For very large bitsets, the API may be a more appropriate choice. Depends-on: series-32740 ("Improve EAL bit operations API") Signed-off-by: Mattias Rönnblom Acked-by: Morten Brørup Acked-by: Tyler Retzlaff --- PATCH: * Update MAINTAINERS. * Update release notes. RFC v5: * Delegate bit test/set/clear/assign/flip to RTE bitops. * Note in the documentation that set/clear/assign/flip are not atomic. RFC v4: * Add function rte_bitset_flip() to change the value of a bit. * Add function rte_bitset_complement(), flipping the value of all bits. * Add function rte_bitset_assign(), setting the value of a bit based on a 'bool' parameter. * Add functions to perform logical shift the bitset left or right. * Add explicit destination bitset to logic operation type functions (e.g., rte_bitset_and()), to increase flexibility. * Split implementation and test suite into distinct commits. RFC v3: * Split the bitset from the htimer patchset, where it was originally hosted. * Rebase to current DPDK main. * Add note that rte_bitset_init() need not be called if bitset words have already been zeroed. * Use REGISTER_FAST_TEST instead of REGISTER_TEST_COMMAND. * Use rte_popcount64() instead of compiler builtin. RFC v2: * Replaced with include, to properly get size_t typedef. * Add to get __rte_experimental in . --- MAINTAINERS | 6 + doc/api/doxy-api-index.md | 1 + doc/guides/rel_notes/release_24_11.rst | 10 + lib/eal/common/meson.build | 1 + lib/eal/common/rte_bitset.c | 29 + lib/eal/include/meson.build | 1 + lib/eal/include/rte_bitset.h | 1061 ++++++++++++++++++++++++ lib/eal/version.map | 3 + 8 files changed, 1112 insertions(+) create mode 100644 lib/eal/common/rte_bitset.c create mode 100644 lib/eal/include/rte_bitset.h diff --git a/MAINTAINERS b/MAINTAINERS index c5a703b5c0..00ad6fd318 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -260,6 +260,12 @@ M: Cristian Dumitrescu F: lib/eal/include/rte_bitmap.h F: app/test/test_bitmap.c +Bitset +M: Mattias Rönnblom +F: lib/eal/include/rte_bitset.h +F: lib/eal/include/rte_bitset.c +F: app/test/test_bitset.c + MCSlock M: Honnappa Nagarahalli F: lib/eal/include/rte_mcslock.h diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index f9f0300126..abd44b1861 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -174,6 +174,7 @@ The public API headers are grouped by topics: [ring](@ref rte_ring.h), [stack](@ref rte_stack.h), [tailq](@ref rte_tailq.h), + [bitset](@ref rte_bitset.h), [bitmap](@ref rte_bitmap.h) - **packet framework**: diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index 3111b1e4c0..89716defac 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -73,6 +73,16 @@ New Features based macros (for C) and function overloading (in C++ translation units). +* **Added multi-word bitset API.** + + A new multi-word bitset API has been introduced in the EAL. The RTE + bitset is optimized for scenarios where the bitset size exceeds the + capacity of a single word (e.g., larger than 64 bits), but is not + large enough to justify the overhead and complexity of the more + scalable, yet slower, API. This addition provides an + efficient and straightforward alternative for handling bitsets of + intermediate sizes. + Removed Items ------------- diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build index 22a626ba6f..c1bbf26654 100644 --- a/lib/eal/common/meson.build +++ b/lib/eal/common/meson.build @@ -31,6 +31,7 @@ sources += files( 'eal_common_uuid.c', 'malloc_elem.c', 'malloc_heap.c', + 'rte_bitset.c', 'rte_malloc.c', 'rte_random.c', 'rte_reciprocal.c', diff --git a/lib/eal/common/rte_bitset.c b/lib/eal/common/rte_bitset.c new file mode 100644 index 0000000000..35e55a64db --- /dev/null +++ b/lib/eal/common/rte_bitset.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Ericsson AB + */ + +#include + +#include "rte_bitset.h" + +ssize_t +rte_bitset_to_str(const uint64_t *bitset, size_t num_bits, char *buf, + size_t capacity) +{ + size_t i; + + if (capacity < (num_bits + 1)) + return -EINVAL; + + for (i = 0; i < num_bits; i++) { + bool value; + + value = rte_bitset_test(bitset, num_bits - 1 - i); + + buf[i] = value ? '1' : '0'; + } + + buf[num_bits] = '\0'; + + return num_bits + 1; +} diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build index e94b056d46..4b5f120a66 100644 --- a/lib/eal/include/meson.build +++ b/lib/eal/include/meson.build @@ -5,6 +5,7 @@ includes += include_directories('.') headers += files( 'rte_alarm.h', + 'rte_bitset.h', 'rte_bitmap.h', 'rte_bitops.h', 'rte_branch_prediction.h', diff --git a/lib/eal/include/rte_bitset.h b/lib/eal/include/rte_bitset.h new file mode 100644 index 0000000000..49a07c77b8 --- /dev/null +++ b/lib/eal/include/rte_bitset.h @@ -0,0 +1,1061 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Ericsson AB + */ + +#ifndef _RTE_BITSET_H_ +#define _RTE_BITSET_H_ + +/** + * @file + * RTE Bitset + * + * This file provides functions and macros for querying and + * manipulating sets of bits kept in arrays of @c uint64_t-sized + * elements. + * + * The bits in a bitset are numbered from 0 to @c size - 1, with the + * lowest index being the least significant bit. + * + * The bitset array must be properly aligned. + * + * For optimal performance, the @c size parameter, required by + * many of the API's functions, should be a compile-time constant. + * + * For large bitsets, the rte_bitmap.h API may be more appropriate. + * + * @warning + * All functions modifying a bitset may overwrite any unused bits of + * the last word. Such unused bits are ignored by all functions reading + * bits. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The size (in bytes) of each element in the array used to represent + * a bitset. + */ +#define RTE_BITSET_WORD_SIZE (sizeof(uint64_t)) + +/** + * The size (in bits) of each element in the array used to represent + * a bitset. + */ +#define RTE_BITSET_WORD_BITS (RTE_BITSET_WORD_SIZE * CHAR_BIT) + +/** + * Computes the number of words required to store @c size bits. + */ +#define RTE_BITSET_NUM_WORDS(size) \ + ((size + RTE_BITSET_WORD_BITS - 1) / RTE_BITSET_WORD_BITS) + +/** + * Computes the amount of memory (in bytes) required to fit a bitset + * holding @c size bits. + */ +#define RTE_BITSET_SIZE(size) \ + ((size_t)(RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_SIZE)) + +#define __RTE_BITSET_WORD_IDX(bit_num) ((bit_num) / RTE_BITSET_WORD_BITS) +#define __RTE_BITSET_BIT_OFFSET(bit_num) ((bit_num) % RTE_BITSET_WORD_BITS) +#define __RTE_BITSET_UNUSED(size) \ + ((RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_BITS) \ + - (size)) +#define __RTE_BITSET_USED_MASK(size) \ + (UINT64_MAX >> __RTE_BITSET_UNUSED(size)) + +#define __RTE_BITSET_DELEGATE_N(fun, bitset, bit_num, ...) \ + fun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)], \ + __RTE_BITSET_BIT_OFFSET(bit_num), __VA_ARGS__) + +/* MSVC doesn't have ##__VA_ARGS__, so argument-less -> special case */ +#define __RTE_BITSET_DELEGATE(fun, bitset, bit_num) \ + fun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)], \ + __RTE_BITSET_BIT_OFFSET(bit_num)) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Declare a bitset. + * + * Declare (e.g., as a struct field) or define (e.g., as a stack + * variable) a bitset of the specified size. + * + * @param size + * The number of bits the bitset must be able to represent. Must be + * a compile-time constant. + * @param name + * The field or variable name of the resulting definition. + */ +#define RTE_BITSET_DECLARE(name, size) \ + uint64_t name[RTE_BITSET_NUM_WORDS(size)] + +#define __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len) \ + ((len) - 1 - ((var) >= (start_bit) ? (var) - (start_bit) : \ + (size) - (start_bit) + (var))) + +#define __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, flags) \ + for ((var) = __rte_bitset_find(bitset, size, start_bit, len, \ + flags); \ + (var) != -1; \ + (var) = __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, \ + len) > 0 ? \ + __rte_bitset_find(bitset, size, \ + ((var) + 1) % (size), \ + __RTE_BITSET_FOREACH_LEFT(var, \ + size, \ + start_bit, \ + len), \ + flags) : -1) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Iterate over all bits set. + * + * This macro iterates over all bits set (i.e., all ones) in the + * bitset, in the forward direction (i.e., starting with the least + * significant '1'). + * + * @param var + * An iterator variable of type @c ssize_t. For each successive + * iteration, this variable will hold the bit index of a set bit. + * @param bitset + * A const uint64_t * pointer to the bitset array. + * @param size + * The size of the bitset (in bits). + */ + +#define RTE_BITSET_FOREACH_SET(var, bitset, size) \ + __RTE_BITSET_FOREACH(var, bitset, size, 0, size, 0) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Iterate over all bits cleared. + * + * This macro iterates over all bits cleared in the bitset, in the + * forward direction (i.e., starting with the lowest-indexed set bit). + * + * @param var + * An iterator variable of type @c ssize_t. For each successive iteration, + * this variable will hold the bit index of a cleared bit. + * @param bitset + * A const uint64_t * pointer to the bitset array. + * @param size + * The size of the bitset (in bits). + */ + +#define RTE_BITSET_FOREACH_CLEAR(var, bitset, size) \ + __RTE_BITSET_FOREACH(var, bitset, size, 0, size, \ + __RTE_BITSET_FIND_FLAG_FIND_CLEAR) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Iterate over all bits set within a range. + * + * This macro iterates over all bits set (i.e., all ones) in the + * specified range, in the forward direction (i.e., starting with the + * least significant '1'). + * + * @param var + * An iterator variable of type @c ssize_t. For each successive iteration, + * this variable will hold the bit index of a set bit. + * @param bitset + * A const uint64_t * pointer to the bitset array. + * @param size + * The size of the bitset (in bits). + * @param start_bit + * The index of the first bit to check. Must be less than @c size. + * @param len + * The length (in bits) of the range. @c start_bit + @c len must be less + * than or equal to @c size. + */ + +#define RTE_BITSET_FOREACH_SET_RANGE(var, bitset, size, start_bit, \ + len) \ + __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, 0) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Iterate over all cleared bits within a range. + * + * This macro iterates over all bits cleared (i.e., all zeroes) in the + * specified range, in the forward direction (i.e., starting with the + * least significant '0'). + * + * @param var + * An iterator variable of type @c ssize_t. For each successive iteration, + * this variable will hold the bit index of a set bit. + * @param bitset + * A const uint64_t * pointer to the bitset array. + * @param size + * The size of the bitset (in bits). + * @param start_bit + * The index of the first bit to check. Must be less than @c size. + * @param len + * The length (in bits) of the range. @c start_bit + @c len must be less + * than or equal to @c size. + */ + +#define RTE_BITSET_FOREACH_CLEAR_RANGE(var, bitset, size, start_bit, \ + len) \ + __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, \ + __RTE_BITSET_FIND_FLAG_FIND_CLEAR) + +#define RTE_BITSET_FOREACH_SET_WRAP(var, bitset, size, start_bit, \ + len) \ + __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, \ + __RTE_BITSET_FIND_FLAG_WRAP) + +#define RTE_BITSET_FOREACH_CLEAR_WRAP(var, bitset, size, start_bit, \ + len) \ + __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, \ + __RTE_BITSET_FIND_FLAG_WRAP | \ + __RTE_BITSET_FIND_FLAG_FIND_CLEAR) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Initializes a bitset. + * + * All bits are cleared. + * + * In case all words in the bitset array are already set to zero by + * other means (e.g., at the time of memory allocation), this function + * need not be called. + * + * @param bitset + * A pointer to the array of bitset 64-bit words. + * @param size + * The size of the bitset (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_init(uint64_t *bitset, size_t size) +{ + memset(bitset, 0, RTE_BITSET_SIZE(size)); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Test if a bit is set. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * Index of the bit to test. Index 0 is the least significant bit. + * @return + * Returns true if the bit is '1', and false if the bit is '0'. + */ + +__rte_experimental +static inline bool +rte_bitset_test(const uint64_t *bitset, size_t bit_num) +{ + return __RTE_BITSET_DELEGATE(rte_bit_test, bitset, bit_num); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Set a bit in the bitset. + * + * Bits are numbered from 0 to (size - 1) (inclusive). + * + * The operation is not guaranteed to be atomic. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be set. + */ + +__rte_experimental +static inline void +rte_bitset_set(uint64_t *bitset, size_t bit_num) +{ + __RTE_BITSET_DELEGATE(rte_bit_set, bitset, bit_num); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Clear a bit in the bitset. + * + * Bits are numbered 0 to (size - 1) (inclusive). + * + * The operation is not guaranteed to be atomic. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be cleared. + */ + +__rte_experimental +static inline void +rte_bitset_clear(uint64_t *bitset, size_t bit_num) +{ + __RTE_BITSET_DELEGATE(rte_bit_clear, bitset, bit_num); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Set or clear a bit in the bitset. + * + * Bits are numbered 0 to (size - 1) (inclusive). + * + * The operation is not guaranteed to be atomic. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be set or cleared. + * @param bit_value + * Control if the bit should be set or cleared. + */ + +__rte_experimental +static inline void +rte_bitset_assign(uint64_t *bitset, size_t bit_num, bool bit_value) +{ + __RTE_BITSET_DELEGATE_N(rte_bit_assign, bitset, bit_num, bit_value); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Change the value of a bit in the bitset. + * + * Bits are numbered 0 to (size - 1) (inclusive). + * + * The operation is not guaranteed to be atomic. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be flipped. + */ + +__rte_experimental +static inline void +rte_bitset_flip(uint64_t *bitset, size_t bit_num) +{ + __RTE_BITSET_DELEGATE(rte_bit_flip, bitset, bit_num); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Set all bits in the bitset. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_set_all(uint64_t *bitset, size_t size) +{ + memset(bitset, 0xFF, RTE_BITSET_SIZE(size)); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Clear all bits in the bitset. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_clear_all(uint64_t *bitset, size_t size) +{ + rte_bitset_init(bitset, size); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Count all set bits (also known as the @e weight). + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @return + * Returns the number of '1' bits in the bitset. + */ + +__rte_experimental +static inline size_t +rte_bitset_count_set(const uint64_t *bitset, size_t size) +{ + size_t i; + size_t total = 0; + + /* + * Unused bits in a rte_bitset are always '0', and thus are + * not included in this count. + */ + for (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++) + total += rte_popcount64(bitset[i]); + + total += rte_popcount64(bitset[i] & __RTE_BITSET_USED_MASK(size)); + + return total; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Count all cleared bits. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @return + * Returns the number of '0' bits in the bitset. + */ + +__rte_experimental +static inline size_t +rte_bitset_count_clear(const uint64_t *bitset, size_t size) +{ + return size - rte_bitset_count_set(bitset, size); +} + +#define __RTE_BITSET_FIND_FLAG_FIND_CLEAR (1U << 0) +#define __RTE_BITSET_FIND_FLAG_WRAP (1U << 1) + +__rte_experimental +static inline ssize_t +__rte_bitset_find_nowrap(const uint64_t *bitset, size_t __rte_unused size, + size_t start_bit, size_t len, bool find_clear) +{ + size_t word_idx; + size_t offset; + size_t end_bit = start_bit + len; + + RTE_ASSERT(end_bit <= size); + + if (unlikely(len == 0)) + return -1; + + word_idx = __RTE_BITSET_WORD_IDX(start_bit); + offset = __RTE_BITSET_BIT_OFFSET(start_bit); + + while (word_idx <= __RTE_BITSET_WORD_IDX(end_bit - 1)) { + uint64_t word; + int word_ffs; + + word = bitset[word_idx]; + if (find_clear) + word = ~word; + + word >>= offset; + + word_ffs = __builtin_ffsll(word); + + if (word_ffs != 0) { + ssize_t ffs = start_bit + word_ffs - 1; + + /* + * Check if set bit were among the last, + * unused bits, in the last word. + */ + if (unlikely(ffs >= (ssize_t)end_bit)) + return -1; + + return ffs; + } + + start_bit += (RTE_BITSET_WORD_BITS - offset); + word_idx++; + offset = 0; + } + + return -1; + +} + +__rte_experimental +static inline ssize_t +__rte_bitset_find(const uint64_t *bitset, size_t size, size_t start_bit, + size_t len, unsigned int flags) +{ + bool find_clear = flags & __RTE_BITSET_FIND_FLAG_FIND_CLEAR; + bool may_wrap = flags & __RTE_BITSET_FIND_FLAG_WRAP; + bool does_wrap = (start_bit + len) > size; + ssize_t rc; + + RTE_ASSERT(len <= size); + if (!may_wrap) + RTE_ASSERT(!does_wrap); + + if (may_wrap && does_wrap) { + size_t len0 = size - start_bit; + size_t len1 = len - len0; + + rc = __rte_bitset_find_nowrap(bitset, size, start_bit, len0, + find_clear); + if (rc < 0) + rc = __rte_bitset_find_nowrap(bitset, size, + 0, len1, find_clear); + } else + rc = __rte_bitset_find_nowrap(bitset, size, start_bit, + len, find_clear); + + return rc; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Find first bit set. + * + * Scans the bitset in the forward direction (i.e., starting at the + * least significant bit), and returns the index of the first '1'. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @return + * Returns the index of the least significant '1', or -1 if all + * bits are '0'. + */ + +__rte_experimental +static inline ssize_t +rte_bitset_find_first_set(const uint64_t *bitset, size_t size) +{ + return __rte_bitset_find(bitset, size, 0, size, 0); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Find first bit set at offset. + * + * Scans the bitset in the forward direction (i.e., starting at the + * least significant bit), starting at an offset @c start_bit into the + * bitset, and returns the index of the first '1' encountered. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @param start_bit + * The index of the first bit to check. Must be less than @c size. + * @param len + * The number of bits to scan. @c start_bit + @c len must be less + * than or equal to @c size. + * @return + * Returns the index of the least significant '1', or -1 if all + * bits are '0'. + */ + +__rte_experimental +static inline ssize_t +rte_bitset_find_set(const uint64_t *bitset, size_t size, + size_t start_bit, size_t len) +{ + return __rte_bitset_find(bitset, size, start_bit, len, 0); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Find first bit set at offset, with wrap-around. + * + * Scans the bitset in the forward direction (i.e., starting at the + * least significant bit), starting at an offset @c start_bit into the + * bitset. If no '1' is encountered before the end of the bitset, the search + * will continue at index 0. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @param start_bit + * The index of the first bit to check. Must be less than @c size. + * @param len + * The number of bits to scan. @c start_bit + @c len must be less + * than or equal to @c size. + * @return + * Returns the index of the least significant '1', or -1 if all + * bits are '0'. + */ + +__rte_experimental +static inline ssize_t +rte_bitset_find_set_wrap(const uint64_t *bitset, size_t size, + size_t start_bit, size_t len) +{ + return __rte_bitset_find(bitset, size, start_bit, len, + __RTE_BITSET_FIND_FLAG_WRAP); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Find first cleared bit. + * + * Scans the bitset in the forward direction (i.e., starting at the + * least significant bit), and returns the index of the first '0'. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @return + * Returns the index of the least significant '0', or -1 if all + * bits are '1'. + */ + +__rte_experimental +static inline ssize_t +rte_bitset_find_first_clear(const uint64_t *bitset, size_t size) +{ + return __rte_bitset_find(bitset, size, 0, size, + __RTE_BITSET_FIND_FLAG_FIND_CLEAR); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Find first cleared bit at offset. + * + * Scans the bitset in the forward direction (i.e., starting at the + * least significant bit), starting at an offset @c start_bit into the + * bitset, and returns the index of the first '0' encountered. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @param start_bit + * The index of the first bit to check. Must be less than @c size. + * @param len + * The number of bits to scan. @c start_bit + @c len must be less + * than or equal to @c size. + * @return + * Returns the index of the least significant '0', or -1 if all + * bits are '1'. + */ + +__rte_experimental +static inline ssize_t +rte_bitset_find_clear(const uint64_t *bitset, size_t size, + size_t start_bit, size_t len) +{ + return __rte_bitset_find(bitset, size, start_bit, len, + __RTE_BITSET_FIND_FLAG_FIND_CLEAR); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Find first cleared bit at offset, with wrap-around. + * + * Scans the bitset in the forward direction (i.e., starting at the + * least significant bit), starting at an offset @c start_bit into the + * bitset. If no '0' is encountered before the end of the bitset, the + * search will continue at index 0. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitset (in bits). + * @param start_bit + * The index of the first bit to check. Must be less than @c size. + * @param len + * The number of bits to scan. @c start_bit + @c len must be less + * than or equal to @c size. + * @return + * Returns the index of the least significant '0', or -1 if all + * bits are '1'. + */ + +__rte_experimental +static inline ssize_t +rte_bitset_find_clear_wrap(const uint64_t *bitset, size_t size, + size_t start_bit, size_t len) +{ + return __rte_bitset_find(bitset, size, start_bit, len, + __RTE_BITSET_FIND_FLAG_FIND_CLEAR | + __RTE_BITSET_FIND_FLAG_WRAP); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Copy bitset. + * + * Copy the bits of the @c src_bitset to the @c dst_bitset. + * + * The bitsets may not overlap and must be of equal size. + * + * @param dst_bitset + * A pointer to the array of words making up the bitset. + * @param src_bitset + * A pointer to the array of words making up the bitset. + * @param size + * The size of the bitsets (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_copy(uint64_t *__rte_restrict dst_bitset, + const uint64_t *__rte_restrict src_bitset, + size_t size) +{ + rte_memcpy(dst_bitset, src_bitset, RTE_BITSET_SIZE(size)); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Bitwise or two bitsets. + * + * Perform a bitwise OR operation on all bits in the two equal-size + * bitsets @c src_bitset0 and @c src_bitset1, and store the results in + * @c dst_bitset. + * + * @param dst_bitset + * A pointer to the destination bitset. + * @param src_bitset0 + * A pointer to the first source bitset. + * @param src_bitset1 + * A pointer to the second source bitset. + * @param size + * The size of the bitsets (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_or(uint64_t *dst_bitset, const uint64_t *src_bitset0, + const uint64_t *src_bitset1, size_t size) +{ + size_t i; + + for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++) + dst_bitset[i] = src_bitset0[i] | src_bitset1[i]; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Bitwise and two bitsets. + * + * Perform a bitwise AND operation on all bits in the two equal-size + * bitsets @c src_bitset0 and @c src_bitset1, and store the result in + * @c dst_bitset. + * + * @param dst_bitset + * A pointer to the destination bitset. + * @param src_bitset0 + * A pointer to the first source bitset. + * @param src_bitset1 + * A pointer to the second source bitset. + * @param size + * The size of the bitsets (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_and(uint64_t *dst_bitset, const uint64_t *src_bitset0, + const uint64_t *src_bitset1, size_t size) +{ + size_t i; + + for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++) + dst_bitset[i] = src_bitset0[i] & src_bitset1[i]; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Bitwise xor two bitsets. + * + * Perform a bitwise XOR operation on all bits in the two equal-size + * bitsets @c src_bitset0 and @c src_bitset1, and store the result in + * @c dst_bitset. + * + * @param dst_bitset + * A pointer to the destination bitset. + * @param src_bitset0 + * A pointer to the first source bitset. + * @param src_bitset1 + * A pointer to the second source bitset. + * @param size + * The size of the bitsets (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_xor(uint64_t *dst_bitset, const uint64_t *src_bitset0, + const uint64_t *src_bitset1, size_t size) +{ + size_t i; + + for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++) + dst_bitset[i] = src_bitset0[i] ^ src_bitset1[i]; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Compute the bitwise complement of a bitset. + * + * Flip every bit in the @c src_bitset, and store the result in @c + * dst_bitset. + * + * @param dst_bitset + * A pointer to the destination bitset. + * @param src_bitset + * A pointer to the source bitset. + * @param size + * The size of the bitsets (in bits). + */ + +__rte_experimental +static inline void +rte_bitset_complement(uint64_t *dst_bitset, const uint64_t *src_bitset, + size_t size) +{ + size_t i; + + for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++) + dst_bitset[i] = ~src_bitset[i]; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Shift bitset left. + * + * Perform a logical shift left of (multiply) @c src_bitset, and store + * the result in @c dst_bitset. + * + * @param dst_bitset + * A pointer to the destination bitset. + * @param src_bitset + * A pointer to the source bitset. + * @param size + * The size of the bitsets (in bits). + * @param shift_bits + * The number of bits to shift the bitset. + */ + +__rte_experimental +static inline void +rte_bitset_shift_left(uint64_t *dst_bitset, const uint64_t *src_bitset, + size_t size, size_t shift_bits) +{ + const int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS; + const int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS; + unsigned int dst_idx; + + for (dst_idx = 0; dst_idx < RTE_BITSET_NUM_WORDS(size); dst_idx++) { + int src_high_idx = dst_idx - src_word_offset; + uint64_t low_bits = 0; + uint64_t high_bits = 0; + + if (src_high_idx >= 0) { + int src_low_idx = src_high_idx - 1; + + high_bits = src_bitset[src_high_idx] << src_bit_offset; + + if (src_bit_offset > 0 && src_low_idx >= 0) + low_bits = src_bitset[src_low_idx] >> + (RTE_BITSET_WORD_BITS - src_bit_offset); + } + dst_bitset[dst_idx] = low_bits | high_bits; + } +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Shift bitset right. + * + * Perform a logical shift right of (divide) @c src_bitset, and store + * the result in @c dst_bitset. + * + * @param dst_bitset + * A pointer to the destination bitset. + * @param src_bitset + * A pointer to the source bitset. + * @param size + * The size of the bitsets (in bits). + * @param shift_bits + * The number of bits to shift the bitset. + */ + +__rte_experimental +static inline void +rte_bitset_shift_right(uint64_t *dst_bitset, const uint64_t *src_bitset, + size_t size, size_t shift_bits) +{ + const int num_words = RTE_BITSET_NUM_WORDS(size); + const uint64_t used_mask = __RTE_BITSET_USED_MASK(size); + const int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS; + const int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS; + int dst_idx; + + for (dst_idx = 0; dst_idx < num_words; dst_idx++) { + int src_low_idx = src_word_offset + dst_idx; + int src_high_idx = src_low_idx + 1; + uint64_t src_low_word_bits = 0; + uint64_t src_high_word_bits = 0; + + if (src_low_idx < num_words) { + src_low_word_bits = src_bitset[src_low_idx]; + + if (src_low_idx == (num_words - 1)) + src_low_word_bits &= used_mask; + + src_low_word_bits >>= src_bit_offset; + + if (src_bit_offset > 0 && src_high_idx < num_words) { + src_high_word_bits = src_bitset[src_high_idx]; + + if (src_high_idx == (num_words - 1)) + src_high_word_bits &= used_mask; + + src_high_word_bits <<= + (RTE_BITSET_WORD_BITS - src_bit_offset); + } + } + dst_bitset[dst_idx] = src_low_word_bits | src_high_word_bits; + } +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Compare two bitsets. + * + * Compare two bitsets for equality. + * + * @param bitset_a + * A pointer to the destination bitset. + * @param bitset_b + * A pointer to the source bitset. + * @param size + * The size of the bitsets (in bits). + */ + +__rte_experimental +static inline bool +rte_bitset_equal(const uint64_t *bitset_a, const uint64_t *bitset_b, + size_t size) +{ + size_t i; + uint64_t last_a, last_b; + + for (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++) + if (bitset_a[i] != bitset_b[i]) + return false; + + last_a = bitset_a[i] << __RTE_BITSET_UNUSED(size); + last_b = bitset_b[i] << __RTE_BITSET_UNUSED(size); + + return last_a == last_b; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Converts a bitset to a string. + * + * This function prints a string representation of the bitstring to + * the supplied buffer. + * + * Each bit is represented either by '0' or '1' in the output, with + * the first (left-most) character in the output being the most + * significant bit. The resulting string is NUL terminated. + * + * @param bitset + * A pointer to the array of bitset 64-bit words. + * @param size + * The number of bits the bitset represent. + * @param buf + * A buffer to hold the output. + * @param capacity + * The size of the buffer. Must be @c size + 1 or larger. + * @return + * Returns the number of bytes written (i.e., @c size + 1), or -EINVAL + * in case the buffer capacity was too small. + */ + +__rte_experimental +ssize_t +rte_bitset_to_str(const uint64_t *bitset, size_t size, char *buf, + size_t capacity); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_BITSET_H_ */ diff --git a/lib/eal/version.map b/lib/eal/version.map index e3ff412683..f493cd1ca7 100644 --- a/lib/eal/version.map +++ b/lib/eal/version.map @@ -396,6 +396,9 @@ EXPERIMENTAL { # added in 24.03 rte_vfio_get_device_info; # WINDOWS_NO_EXPORT + + # added in 24.11 + rte_bitset_to_str; }; INTERNAL { From patchwork Fri Aug 9 20:14:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Mattias_R=C3=B6nnblom?= X-Patchwork-Id: 143059 X-Patchwork-Delegate: thomas@monjalon.net 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 0931B4577D; Fri, 9 Aug 2024 22:24:57 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 13D1942EA0; Fri, 9 Aug 2024 22:24:25 +0200 (CEST) Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on2083.outbound.protection.outlook.com [40.107.241.83]) by mails.dpdk.org (Postfix) with ESMTP id 3E07242E58 for ; Fri, 9 Aug 2024 22:24:20 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=RMvbYCXvoScbuebAYNdgkHl0JfgjNUSYwdu8LGVpXA8CSlV0peJ3KWVGplRL07qyNvdW1HQ0D6EPAvAZ5CgIJlc98RFsuyw/TCH2LJe5d0lFb/C6sr64xPoiVbMh8XAYpKW8dEQ8RlKnOUI+5j9lGm5ZTTqo9g7Xb8Gmk5VAAQf8JBz7kqb3L66SO8KDQ3OZhbPEeV2egwhcJXGYJbsPvqjz/jkbD/iukJJYUlBRXQf0li08/sUe3bln39M7xzfUQCPAAmpVXHxUrWaxR58q3z28dHVMWISWeS/tqaVXi3k5LBKEMOixIxDVCdEfcdx6GNyqcU0LPgG3920EchWOIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=VkCkMGh9ILWbh8tNxIgfZlaD6gLf18LkBqkNHp1LM4o=; b=HzHCjVSij1wzy2rRUnLH4/Bw8DsxMq/hQJwekroQLHRgmqU1O3UHnv6nRRt4BQGYDI5n7mEvX3LH9prEag3ls8oCnw++CxAyTz1ebWkCK3jlKrwRslR/GqK/4F5vcYUm77gMZrLXyXMyH9bwnKqIJSCTvkAUHnA04c8TW0/Nly7ZLM9mxVBPFvNrKUwjKrPDt7TgMzDyycL2H2nHm1Kw5l293gMblVGQM1XkEgqDb/ul7Z/WWRKsS8ZWXbzbinw2Pdgif7pKfcJOEMewnCB7AlgbaG/I2mY3ptKbn6+qAUkJGSg5MIoXR0SheBvFBSgh+GqvCbyj0Fmljb9NLddgeQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=VkCkMGh9ILWbh8tNxIgfZlaD6gLf18LkBqkNHp1LM4o=; b=ugTpK6zQKqNTYlLBhgl+mwBY69vd+uEBYgOLLtwsCjfwHMSLSuw9y6cIzcvnImE/QpJU1P8GdAtg1C5G4/tfhddnqvgZvyxkhOSnN4d8FAbGxUpiViJegnZwyNuW/djsJpbQR3dB6mpXsGVHWMIqFnLZ8qnsIzTeU6qrWjMKy3MzDePeF2Z1mB+yVOD5p3uOBX+HR729nia7tG2yt38dylZSq/A9aZ+PCIuV2f7UTV2q0zDDqykr/ugkWW4qhYisIUFJ231xHjeFKOZzJysQkuHsAwuSSVKKOnHYZc+R9r+B6gM5fDICcWWSI39at6pW67p2eWtcb14gZvOJxxnuAA== Received: from AM0PR02CA0073.eurprd02.prod.outlook.com (2603:10a6:208:154::14) by DBBPR07MB7435.eurprd07.prod.outlook.com (2603:10a6:10:1e2::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.14; Fri, 9 Aug 2024 20:24:17 +0000 Received: from AM3PEPF0000A794.eurprd04.prod.outlook.com (2603:10a6:208:154:cafe::4c) by AM0PR02CA0073.outlook.office365.com (2603:10a6:208:154::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.15 via Frontend Transport; Fri, 9 Aug 2024 20:24:17 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by AM3PEPF0000A794.mail.protection.outlook.com (10.167.16.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.8 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.66) with Microsoft SMTP Server id 15.2.1544.11; Fri, 9 Aug 2024 22:24:15 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id 8A7C01C006B; Fri, 9 Aug 2024 22:24:15 +0200 (CEST) From: =?utf-8?q?Mattias_R=C3=B6nnblom?= To: CC: , =?utf-8?q?Morten_Br=C3=B8rup?= , Tyler Retzlaff , Stephen Hemminger , Harry van Haaren , =?utf-8?q?Mattias_R=C3=B6nnb?= =?utf-8?q?lom?= Subject: [PATCH 2/6] eal: add bitset test suite Date: Fri, 9 Aug 2024 22:14:36 +0200 Message-ID: <20240809201440.590464-2-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240809201440.590464-1-mattias.ronnblom@ericsson.com> References: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> <20240809201440.590464-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM3PEPF0000A794:EE_|DBBPR07MB7435:EE_ X-MS-Office365-Filtering-Correlation-Id: 1dee5326-db49-4daa-fe3c-08dcb8b13dd5 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|1800799024|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?utf-8?q?tXYTrZr3xPkUOcbpaDCuFhjoElv31rk?= =?utf-8?q?4B5LYkVFK3C04MwnTMPXgmZWkg6pK9reKwKJJIKgqE1JYuCxb8ifZ3AL8/eACFH+P?= =?utf-8?q?MlkPikWrhNJGpDB24qYBANWMk4mura5iWXCjBSP8nUAo+UIl3rguwQJmpfZB+F8qC?= =?utf-8?q?ynN0AK8r6urmsE+B9AlJYaBWAW8uR0VMIMP1fETBwh6pfNTApFqPg5PF2BzZh5wNf?= =?utf-8?q?wIyaI3+3HBIYm08+GaJ2qdes3A4BC/gYznQVKPCK6EWMxtUbgxnBfiWpdhpjvJrln?= =?utf-8?q?DGG9o1o0z6lk7fdnVUX6G6hqXPy8KESX9F1ghaUptBfoTLgpQeQiZmohTAUVLXar0?= =?utf-8?q?tJaEuD9iqZFSjdt814Fi4HOIQLA3xr4MOAeAU2o3RwSv4C0EGtQJ/xPEB7Fg+/+F3?= =?utf-8?q?YdPbjz1mQiQ8GWcrim/bjQ8D86qjoYw6k1/irt8idmQxmLcrdd0Q+5boZnd6Y0hPl?= =?utf-8?q?ABMHp4s2/56bs5VuHOjlVFX0VRbY1bhqetvmtWTTa/o5tI92++MoEvy+UubKRWgBh?= =?utf-8?q?vDSjyNdnPXv7bQXWCz/cDcexhgIPIKkX4z2BfGC/p9YP6+9CuhhHvvHfiR9LjR3us?= =?utf-8?q?KrVYVHCKt7fMedR2gM6+6CF48V5YLtgjJmk0ne4T2YiDb4jal+W0NHOxe4NHXPZYQ?= =?utf-8?q?T3xyggZn8m90rR5tuGRk+OVVD8Jle89pPpqbjmEoulvVpQAifH1gfveTV5RgKgtme?= =?utf-8?q?CpMgWYX94m78NDgjopIkWQmBoaK6xlT+PgFLHs9injPR2P1lZzde5E7uifJzdhNKk?= =?utf-8?q?AaIZzidK7g39WOCddqnw4CwtSwucljqTaU4JDQXD9juP1ADqoYElPBpSNnnYqxcUj?= =?utf-8?q?oui4Iv9KoltLpfjK6p4sYjXLY7qAFiq7xPGnxGBF70g2nt8ZPf0qQRAivrdLs17Ow?= =?utf-8?q?wiQQBPPgruMqLdMEccnXUee8cGzxD9stXUkTUmv2NlMs3/VCFnAMP4ea1S3Dr8fKj?= =?utf-8?q?sJMY35IhdnP5d6p+GYxFzFjlStXka1e4Ai+zcNsHMhltkYvQNDy8Eh/nXi6YxsjmI?= =?utf-8?q?ZENGza/0YOSwlfV0yWrXZPSvZ992GK3NuMSQCYxJ5jRbISrx8lZ4A28kUuCgYU8PA?= =?utf-8?q?MND7AlRyxFPEYeOuHTvUsNHWHyS/epQRfW081IAn21dEk3dYBI318e03gxuRGWEM7?= =?utf-8?q?6ZZTQdWc6vWA+5M4YRLI9x+agXKqwl/hPbvdqmW0n//WOv7OgZ5+URBw2DFFmGTdf?= =?utf-8?q?DvSMjR+bbP6GoDJhDkhG4HSVbuwHxcqibDUVkJe9NBGpYw+OZqmM1MbuFQ4uVvkyc?= =?utf-8?q?wKTdSgXuCwiGS2AwDkBf9aVLtSbXL8Ix1k1x1HF1MZXY7/7qwyfcCG+YfEtBay9EY?= =?utf-8?q?BeFMgMWBh2FM5zE2BqIavuRGZpRrAmKFAA=3D=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(36860700013)(1800799024)(376014)(82310400026); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 20:24:16.5455 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1dee5326-db49-4daa-fe3c-08dcb8b13dd5 X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: AM3PEPF0000A794.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR07MB7435 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 test suite exercising . Signed-off-by: Mattias Rönnblom Acked-by: Tyler Retzlaff --- RFC v5: * Parameterize tests to allow reuse across both atomic and non-atomic functions. RFC v4: * Fix signed char issue in test cases. (Stephen Hemminger) * Add test cases for logic operations. * Use the unit test suite runner helper. --- app/test/meson.build | 1 + app/test/test_bitset.c | 894 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 895 insertions(+) create mode 100644 app/test/test_bitset.c diff --git a/app/test/meson.build b/app/test/meson.build index e29258e6ec..fe248b786c 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -33,6 +33,7 @@ source_file_deps = { 'test_bitcount.c': [], 'test_bitmap.c': [], 'test_bitops.c': [], + 'test_bitset.c': [], 'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps, 'test_bpf.c': ['bpf', 'net'], 'test_byteorder.c': [], diff --git a/app/test/test_bitset.c b/app/test/test_bitset.c new file mode 100644 index 0000000000..b3496df1c0 --- /dev/null +++ b/app/test/test_bitset.c @@ -0,0 +1,894 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Ericsson AB + */ + +#include +#include + +#include + +#include + +#include "test.h" + +#define MAGIC UINT64_C(0xdeadbeefdeadbeef) + +static void +rand_buf(void *buf, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) + ((unsigned char *)buf)[i] = rte_rand(); +} + +static uint64_t * +alloc_bitset(size_t size) +{ + uint64_t *p; + + p = malloc(RTE_BITSET_SIZE(size) + 2 * sizeof(uint64_t)); + + if (p == NULL) + rte_panic("Unable to allocate memory\n"); + + rand_buf(&p[0], RTE_BITSET_SIZE(size)); + + p[0] = MAGIC; + p[RTE_BITSET_NUM_WORDS(size) + 1] = MAGIC; + + return p + 1; +} + + +static int +free_bitset(uint64_t *bitset, size_t size) +{ + uint64_t *p; + + p = bitset - 1; + + if (p[0] != MAGIC) + return TEST_FAILED; + + if (p[RTE_BITSET_NUM_WORDS(size) + 1] != MAGIC) + return TEST_FAILED; + + free(p); + + return TEST_SUCCESS; +} + +static bool +rand_bool(void) +{ + return rte_rand_max(2); +} + +static void +rand_bool_ary(bool *ary, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + ary[i] = rand_bool(); +} + +static void +rand_unused_bits(uint64_t *bitset, size_t size) +{ + uint64_t bits = rte_rand() & ~__RTE_BITSET_USED_MASK(size); + + bitset[RTE_BITSET_NUM_WORDS(size) - 1] |= bits; +} + +static void +rand_bitset(uint64_t *bitset, size_t size) +{ + size_t i; + + rte_bitset_init(bitset, size); + + for (i = 0; i < size; i++) + rte_bitset_assign(bitset, i, rand_bool()); + + rand_unused_bits(bitset, size); +} + +typedef bool test_fun(const uint64_t *bitset, size_t bit_num); +typedef void set_fun(uint64_t *bitset, size_t bit_num); +typedef void clear_fun(uint64_t *bitset, size_t bit_num); +typedef void assign_fun(uint64_t *bitset, size_t bit_num, bool value); +typedef void flip_fun(uint64_t *bitset, size_t bit_num); + +static int +test_set_clear_size(test_fun test_fun, set_fun set_fun, clear_fun clear_fun, + size_t size) +{ + size_t i; + bool reference[size]; + uint64_t *bitset; + + rand_bool_ary(reference, size); + + bitset = alloc_bitset(size); + + TEST_ASSERT(bitset != NULL, "Failed to allocate memory"); + + rte_bitset_init(bitset, size); + + for (i = 0; i < size; i++) { + if (reference[i]) + set_fun(bitset, i); + else + clear_fun(bitset, i); + } + + for (i = 0; i < size; i++) + if (reference[i] != test_fun(bitset, i)) + return TEST_FAILED; + + TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS, + "Buffer over- or underrun detected"); + + return TEST_SUCCESS; +} + +#define RAND_ITERATIONS (10000) +#define RAND_SET_MAX_SIZE (1000) + +static int +test_set_clear_fun(test_fun test_fun, set_fun set_fun, clear_fun clear_fun) +{ + size_t i; + + for (i = 0; i < RAND_ITERATIONS; i++) { + size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1); + + if (test_set_clear_size(test_fun, set_fun, clear_fun, + size) != TEST_SUCCESS) + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +test_set_clear(void) +{ + return test_set_clear_fun(rte_bitset_test, rte_bitset_set, + rte_bitset_clear); +} + +static int +test_flip_size(test_fun test_fun, assign_fun assign_fun, flip_fun flip_fun, + size_t size) +{ + size_t i; + uint64_t *bitset; + + bitset = alloc_bitset(size); + + TEST_ASSERT(bitset != NULL, "Failed to allocate memory"); + + rand_bitset(bitset, size); + + for (i = 0; i < size; i++) { + RTE_BITSET_DECLARE(reference, size); + + rte_bitset_copy(reference, bitset, size); + + bool value = test_fun(bitset, i); + + flip_fun(bitset, i); + + TEST_ASSERT(test_fun(bitset, i) != value, + "Bit %zd was not flipped", i); + + assign_fun(reference, i, !value); + + TEST_ASSERT(rte_bitset_equal(bitset, reference, size), + "Not only the target bit %zd was flipped", i); + + + } + + TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS, + "Buffer over- or underrun detected"); + + return TEST_SUCCESS; +} + +static int +test_flip_fun(test_fun test_fun, assign_fun assign_fun, flip_fun flip_fun) +{ + size_t i; + + for (i = 0; i < RAND_ITERATIONS; i++) { + size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1); + + if (test_flip_size(test_fun, assign_fun, flip_fun, + size) != TEST_SUCCESS) + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +test_flip(void) +{ + return test_flip_fun(rte_bitset_test, rte_bitset_assign, + rte_bitset_flip); +} + +static ssize_t +find(const bool *ary, size_t num_bools, size_t start, size_t len, bool set) +{ + size_t i; + + for (i = 0; i < len; i++) { + ssize_t idx = (start + i) % num_bools; + + if (ary[idx] == set) + return idx; + } + + return -1; +} + +static ssize_t +find_set(const bool *ary, size_t num_bools, size_t start, size_t len) +{ + return find(ary, num_bools, start, len, true); +} + +static ssize_t +find_clear(const bool *ary, size_t num_bools, size_t start, size_t len) +{ + return find(ary, num_bools, start, len, false); +} + +#define FFS_ITERATIONS (100) + +static int +test_find_size(size_t size, bool set) +{ + uint64_t *bitset; + bool reference[size]; + size_t i; + + bitset = alloc_bitset(size); + + TEST_ASSERT(bitset != NULL, "Failed to allocate memory"); + + rte_bitset_init(bitset, size); + + for (i = 0; i < size; i++) { + bool bit = rand_bool(); + reference[i] = bit; + + if (bit) + rte_bitset_set(bitset, i); + else /* redundant, still useful for testing */ + rte_bitset_clear(bitset, i); + } + + for (i = 0; i < FFS_ITERATIONS; i++) { + size_t start_bit = rte_rand_max(size); + size_t len = rte_rand_max(size + 1); + bool full_range = len == size && start_bit == 0; + bool wraps = start_bit + len > size; + ssize_t rc; + + if (set) { + if (full_range && rand_bool()) + rc = rte_bitset_find_first_set(bitset, + size); + else if (wraps || rand_bool()) { + rc = rte_bitset_find_set_wrap(bitset, size, + start_bit, len); + + } else + rc = rte_bitset_find_set(bitset, size, + start_bit, len); + + if (rc != find_set(reference, size, start_bit, + len)) + return TEST_FAILED; + } else { + if (full_range && rand_bool()) + rc = rte_bitset_find_first_clear(bitset, + size); + else if (wraps || rand_bool()) + rc = rte_bitset_find_clear_wrap(bitset, + size, + start_bit, len); + else + rc = rte_bitset_find_clear(bitset, size, + start_bit, len); + + if (rc != find_clear(reference, size, start_bit, + len)) + return TEST_FAILED; + } + + } + + TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS, + "Buffer over- or underrun detected"); + + return TEST_SUCCESS; +} + +static int +test_find_set_size(size_t size) +{ + return test_find_size(size, true); +} + +static int +test_find_clear_size(size_t size) +{ + return test_find_size(size, false); +} + +static int +test_find(void) +{ + size_t i; + + for (i = 0; i < RAND_ITERATIONS; i++) { + size_t size = 2 + rte_rand_max(RAND_SET_MAX_SIZE - 2); + + if (test_find_set_size(size) != TEST_SUCCESS) + return TEST_FAILED; + + if (test_find_clear_size(size) != TEST_SUCCESS) + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +record_match(ssize_t match_idx, size_t size, int *calls) +{ + if (match_idx < 0 || (size_t)match_idx >= size) + return TEST_FAILED; + + calls[match_idx]++; + + return TEST_SUCCESS; +} + +static int +test_foreach_size(ssize_t size, bool may_wrap, bool set) +{ + bool reference[size]; + int calls[size]; + uint64_t *bitset; + ssize_t i; + ssize_t start_bit; + ssize_t len; + bool full_range; + size_t total_calls = 0; + + rand_bool_ary(reference, size); + + bitset = alloc_bitset(size); + + TEST_ASSERT(bitset != NULL, "Failed to allocate memory"); + + memset(calls, 0, sizeof(calls)); + + start_bit = rte_rand_max(size); + len = may_wrap ? rte_rand_max(size + 1) : + rte_rand_max(size - start_bit + 1); + + rte_bitset_init(bitset, size); + + /* random data in the unused bits should not matter */ + rand_buf(bitset, RTE_BITSET_SIZE(size)); + + for (i = start_bit; i < start_bit + len; i++) { + size_t idx = i % size; + + if (reference[idx]) + rte_bitset_set(bitset, idx); + else + rte_bitset_clear(bitset, idx); + + if (rte_bitset_test(bitset, idx) != reference[idx]) + return TEST_FAILED; + } + + full_range = (len == size && start_bit == 0); + + /* XXX: verify iteration order as well */ + if (set) { + if (full_range && rand_bool()) { + RTE_BITSET_FOREACH_SET(i, bitset, size) { + if (record_match(i, size, calls) != + TEST_SUCCESS) + return TEST_FAILED; + } + } else if (may_wrap) { + RTE_BITSET_FOREACH_SET_WRAP(i, bitset, size, + start_bit, len) { + if (record_match(i, size, calls) != + TEST_SUCCESS) { + printf("failed\n"); + return TEST_FAILED; + } + } + } else { + RTE_BITSET_FOREACH_SET_RANGE(i, bitset, size, + start_bit, len) { + if (record_match(i, size, calls) != + TEST_SUCCESS) + return TEST_FAILED; + } + } + } else { + if (full_range && rand_bool()) { + RTE_BITSET_FOREACH_CLEAR(i, bitset, size) + if (record_match(i, size, calls) != + TEST_SUCCESS) + return TEST_FAILED; + } else if (may_wrap) { + RTE_BITSET_FOREACH_CLEAR_WRAP(i, bitset, size, + start_bit, len) { + if (record_match(i, size, calls) != + TEST_SUCCESS) + return TEST_FAILED; + } + } else { + RTE_BITSET_FOREACH_CLEAR_RANGE(i, bitset, size, + start_bit, len) + if (record_match(i, size, calls) != + TEST_SUCCESS) + return TEST_FAILED; + } + } + + for (i = 0; i < len; i++) { + size_t idx = (start_bit + i) % size; + + if (reference[idx] == set && calls[idx] != 1) { + printf("bit %zd shouldn't have been found %d " + "times\n", idx, calls[idx]); + return TEST_FAILED; + } + + if (reference[idx] != set && calls[idx] != 0) { + puts("bar"); + return TEST_FAILED; + } + + total_calls += calls[idx]; + } + + if (full_range) { + size_t count; + + count = set ? rte_bitset_count_set(bitset, size) : + rte_bitset_count_clear(bitset, size); + + if (count != total_calls) + return TEST_FAILED; + } + + TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS, + "Buffer over- or underrun detected"); + + return TEST_SUCCESS; +} + +static int +test_foreach(void) +{ + size_t i; + + for (i = 0; i < RAND_ITERATIONS; i++) { + size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1); + + if (test_foreach_size(size, false, true) != TEST_SUCCESS) + return TEST_FAILED; + + if (test_foreach_size(size, false, false) != TEST_SUCCESS) + return TEST_FAILED; + + if (test_foreach_size(size, true, true) != TEST_SUCCESS) + return TEST_FAILED; + + if (test_foreach_size(size, true, false) != TEST_SUCCESS) + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +test_count_size(size_t size) +{ + uint64_t *bitset; + + bitset = alloc_bitset(size); + + TEST_ASSERT(bitset != NULL, "Failed to allocate memory"); + + rte_bitset_init(bitset, size); + + rand_unused_bits(bitset, size); + + if (rte_bitset_count_set(bitset, size) != 0) + return TEST_FAILED; + + if (rte_bitset_count_clear(bitset, size) != size) + return TEST_FAILED; + + rte_bitset_set_all(bitset, size); + + if (rte_bitset_count_set(bitset, size) != size) + return TEST_FAILED; + + if (rte_bitset_count_clear(bitset, size) != 0) + return TEST_FAILED; + + rte_bitset_clear_all(bitset, size); + + if (rte_bitset_count_set(bitset, size) != 0) + return TEST_FAILED; + + if (rte_bitset_count_clear(bitset, size) != size) + return TEST_FAILED; + + rte_bitset_set(bitset, rte_rand_max(size)); + + if (rte_bitset_count_set(bitset, size) != 1) + return TEST_FAILED; + + if (rte_bitset_count_clear(bitset, size) != (size - 1)) + return TEST_FAILED; + + rte_bitset_clear_all(bitset, size); + if (rte_bitset_count_set(bitset, size) != 0) + return TEST_FAILED; + if (rte_bitset_count_clear(bitset, size) != size) + return TEST_FAILED; + + rte_bitset_set_all(bitset, size); + if (rte_bitset_count_set(bitset, size) != size) + return TEST_FAILED; + if (rte_bitset_count_clear(bitset, size) != 0) + return TEST_FAILED; + + TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS, + "Buffer over- or underrun detected"); + + return TEST_SUCCESS; +} + +static int +test_count(void) +{ + size_t i; + + if (test_count_size(128) != TEST_SUCCESS) + return TEST_FAILED; + if (test_count_size(1) != TEST_SUCCESS) + return TEST_FAILED; + if (test_count_size(63) != TEST_SUCCESS) + return TEST_FAILED; + if (test_count_size(64) != TEST_SUCCESS) + return TEST_FAILED; + if (test_count_size(65) != TEST_SUCCESS) + return TEST_FAILED; + + for (i = 0; i < RAND_ITERATIONS; i++) { + size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1); + + if (test_count_size(size) != TEST_SUCCESS) + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +#define GEN_DECLARE(size) \ + { \ + RTE_BITSET_DECLARE(bitset, size); \ + size_t idx; \ + \ + idx = rte_rand_max(size); \ + rte_bitset_init(bitset, size); \ + \ + rte_bitset_set(bitset, idx); \ + if (!rte_bitset_test(bitset, idx)) \ + return TEST_FAILED; \ + if (rte_bitset_count_set(bitset, size) != 1) \ + return TEST_FAILED; \ + return TEST_SUCCESS; \ + } + +static int +test_define(void) +{ + GEN_DECLARE(1); + GEN_DECLARE(64); + GEN_DECLARE(65); + GEN_DECLARE(4097); +} + +static int test_logic_op(void (*bitset_op)(uint64_t *, const uint64_t *, + const uint64_t *, size_t), + bool (*bool_op)(bool, bool)) +{ + const size_t size = 1 + rte_rand_max(200); + RTE_BITSET_DECLARE(bitset_a, size); + RTE_BITSET_DECLARE(bitset_b, size); + RTE_BITSET_DECLARE(bitset_d, size); + + bool ary_a[size]; + bool ary_b[size]; + bool ary_d[size]; + + rand_bool_ary(ary_a, size); + rand_bool_ary(ary_b, size); + + size_t i; + for (i = 0; i < size; i++) { + rte_bitset_assign(bitset_a, i, ary_a[i]); + rte_bitset_assign(bitset_b, i, ary_b[i]); + ary_d[i] = bool_op(ary_a[i], ary_b[i]); + } + + bitset_op(bitset_d, bitset_a, bitset_b, size); + + for (i = 0; i < size; i++) + TEST_ASSERT_EQUAL(rte_bitset_test(bitset_d, i), + ary_d[i], "Unexpected value of bit %zd", i); + + return TEST_SUCCESS; +} + +static bool +bool_or(bool a, bool b) +{ + return a || b; +} + +static int +test_or(void) +{ + return test_logic_op(rte_bitset_or, bool_or); +} + +static bool +bool_and(bool a, bool b) +{ + return a && b; +} + +static int +test_and(void) +{ + return test_logic_op(rte_bitset_and, bool_and); +} + +static bool +bool_xor(bool a, bool b) +{ + return a != b; +} + +static int +test_xor(void) +{ + return test_logic_op(rte_bitset_xor, bool_xor); +} + +static int +test_complement(void) +{ + int i; + + for (i = 0; i < RAND_ITERATIONS; i++) { + const size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1); + + RTE_BITSET_DECLARE(src, size); + + rand_bitset(src, size); + + bool bit_idx = rte_rand_max(size); + bool bit_value = rte_bitset_test(src, bit_idx); + + RTE_BITSET_DECLARE(dst, size); + + rte_bitset_complement(dst, src, size); + + TEST_ASSERT(bit_value != rte_bitset_test(dst, bit_idx), + "Bit %d was not flipped", bit_idx); + } + + return TEST_SUCCESS; +} + +static int +test_shift(bool right) +{ + int i; + + const char *direction = right ? "right" : "left"; + + for (i = 0; i < 10000; i++) { + const int size = 1 + (int)rte_rand_max(500); + const int shift_count = (int)rte_rand_max(1.5 * size); + int src_idx; + + RTE_BITSET_DECLARE(src, size); + RTE_BITSET_DECLARE(reference, size); + + rte_bitset_init(src, size); + rte_bitset_init(reference, size); + + rand_unused_bits(src, size); + rand_unused_bits(reference, size); + + for (src_idx = 0; src_idx < size; src_idx++) { + bool value = rand_bool(); + + rte_bitset_assign(src, src_idx, value); + + int dst_idx = right ? src_idx - shift_count : + src_idx + shift_count; + + if (dst_idx >= 0 && dst_idx < size) + rte_bitset_assign(reference, dst_idx, value); + } + + uint64_t *dst = alloc_bitset(size); + + if (right) + rte_bitset_shift_right(dst, src, size, shift_count); + else + rte_bitset_shift_left(dst, src, size, shift_count); + + TEST_ASSERT(rte_bitset_equal(dst, reference, size), + "Unexpected result from shifting bitset of size " + "%d bits %d bits %s", size, shift_count, direction); + + TEST_ASSERT_EQUAL(free_bitset(dst, size), TEST_SUCCESS, + "Shift %s operation overwrote buffer", + direction); + } + + return TEST_SUCCESS; +} + +static int +test_shift_right(void) +{ + return test_shift(true); +} + +static int +test_shift_left(void) +{ + return test_shift(false); +} + +static int +test_equal(void) +{ + const size_t size = 100; + RTE_BITSET_DECLARE(bitset_a, size); + RTE_BITSET_DECLARE(bitset_b, size); + + rand_buf(bitset_a, RTE_BITSET_SIZE(size)); + rand_buf(bitset_b, RTE_BITSET_SIZE(size)); + + rte_bitset_init(bitset_a, size); + rte_bitset_init(bitset_b, size); + + rte_bitset_set(bitset_a, 9); + rte_bitset_set(bitset_b, 9); + rte_bitset_set(bitset_a, 90); + rte_bitset_set(bitset_b, 90); + + if (!rte_bitset_equal(bitset_a, bitset_b, size)) + return TEST_FAILED; + + /* set unused bit, which should be ignored */ + rte_bitset_set(&bitset_a[1], 60); + + if (!rte_bitset_equal(bitset_a, bitset_b, size)) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_copy(void) +{ + const size_t size = 100; + RTE_BITSET_DECLARE(bitset_a, size); + RTE_BITSET_DECLARE(bitset_b, size); + + rand_buf(bitset_a, RTE_BITSET_SIZE(size)); + rand_buf(bitset_b, RTE_BITSET_SIZE(size)); + + rte_bitset_copy(bitset_a, bitset_b, size); + + if (!rte_bitset_equal(bitset_a, bitset_b, size)) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_to_str(void) +{ + char buf[1024]; + RTE_BITSET_DECLARE(bitset, 128); + + rte_bitset_init(bitset, 128); + rte_bitset_set(bitset, 1); + + if (rte_bitset_to_str(bitset, 2, buf, 3) != 3) + return TEST_FAILED; + if (strcmp(buf, "10") != 0) + return TEST_FAILED; + + rte_bitset_set(bitset, 0); + + if (rte_bitset_to_str(bitset, 1, buf, sizeof(buf)) != 2) + return TEST_FAILED; + if (strcmp(buf, "1") != 0) + return TEST_FAILED; + + rte_bitset_init(bitset, 99); + rte_bitset_set(bitset, 98); + + if (rte_bitset_to_str(bitset, 99, buf, sizeof(buf)) != 100) + return TEST_FAILED; + + if (buf[0] != '1' || strchr(&buf[1], '1') != NULL) + return TEST_FAILED; + + if (rte_bitset_to_str(bitset, 128, buf, 64) != -EINVAL) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static struct unit_test_suite bitset_tests = { + .suite_name = "bitset test suite", + .unit_test_cases = { + TEST_CASE_ST(NULL, NULL, test_set_clear), + TEST_CASE_ST(NULL, NULL, test_flip), + TEST_CASE_ST(NULL, NULL, test_find), + TEST_CASE_ST(NULL, NULL, test_foreach), + TEST_CASE_ST(NULL, NULL, test_count), + TEST_CASE_ST(NULL, NULL, test_define), + TEST_CASE_ST(NULL, NULL, test_or), + TEST_CASE_ST(NULL, NULL, test_and), + TEST_CASE_ST(NULL, NULL, test_xor), + TEST_CASE_ST(NULL, NULL, test_complement), + TEST_CASE_ST(NULL, NULL, test_shift_right), + TEST_CASE_ST(NULL, NULL, test_shift_left), + TEST_CASE_ST(NULL, NULL, test_equal), + TEST_CASE_ST(NULL, NULL, test_copy), + TEST_CASE_ST(NULL, NULL, test_to_str), + TEST_CASES_END() + } +}; + +static int +test_bitset(void) +{ + return unit_test_suite_runner(&bitset_tests); +} + +REGISTER_FAST_TEST(bitset_autotest, true, true, test_bitset); From patchwork Fri Aug 9 20:14:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Mattias_R=C3=B6nnblom?= X-Patchwork-Id: 143060 X-Patchwork-Delegate: thomas@monjalon.net 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 CB4384577D; Fri, 9 Aug 2024 22:25:03 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5512642E8D; Fri, 9 Aug 2024 22:24:26 +0200 (CEST) Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) by mails.dpdk.org (Postfix) with ESMTP id 82C1342E5C for ; Fri, 9 Aug 2024 22:24:20 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=B5cFAtQXwHXo1oSUhSt7lRiWQz9oT8CFnEKYvit5oJuE+sRfZsnI5cxeHNOW0FSYJO6+gzkFCzI+MKcYvhJjrYOa083DlNx+Rdhvys59BrfY4rOmlDGpL6UQNHQ9u3SJNyYznfrK0Ej56u2tK/k1KwZ05UiwC42nY2iI9Zwu4GOg33cBlQCh7dvKy7rXPbu4IxBS6U/N0daMEZUR8AKG/YKr0b7HGdcQ8sicgFartMM6/1A6w45aD4ZfCzDmjKYlRYTlvskasPgWZLVbEYjUi9VDpHdtGFq++4IR9AebtmKDMSZ4LK5oC/ib+oUPVKUpJuND37S/NxjqM9WPHs1e0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Q/piwczi3n4aqfjxagcziK2QUx6rtehUaviNWwb6gFI=; b=hF3G1wjYBPfasVcD6DFe1jrir0+54aeYlawKfi+GE376vB8uNZTIFeVMjkNnstH8qvbsoE7nc+LRNtx34nXzGhnsNxLCg9hzxj4CAF5NGqfhRpBmdxlBoDd8hftt1/qQp79H/52UvNKOsesYCbFvg8e7l/x6AFo6f5sP75YTVAmp1ItRi/mc6HcjRqRpW/LSQvOnWE4sUfhg5Quv0FcK1ObxzB2bNAQPJm2IQKGr4u0bPRR2xa/s/nEgu5EHXZUbkhli7vHaaIDeIoEbwfwOXHptRUwKrcNt1blt50XdDEcNuj1Prr2KFNX615cyCvZzTlOBZCUVuI+QJEmMcIW4tA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Q/piwczi3n4aqfjxagcziK2QUx6rtehUaviNWwb6gFI=; b=XtUWa42L1W69+669SVr2PcgOc77JjeZjwHiAoP1F8sDd+oe1nLnLQVwcT3x7W1MtfUSXiGNrh3bXL64+2Z4UdZ3oX/0lLKspEyD+/3TTNEqjsbQdq+aDiG5Oj0mQj6knJAJkJO5OMHxVXo7LABW5PFI3aog/5/jw7ZEUxom3PMvl/F4X6o7pkNZAjodzMjr6g0RhrQgyoPWTkh600j1e21kjU8mMe4vpF9jL1vv89adxKNQlG21+GovgQE4fUIRaiDBDFpcALaDqPu37dDt03r1sv/kBYaoJlgNRVtnu2NPY2hhAAkcpEEfEWxxOxIW/Edno6WmjSHVP+pOcvd9u6A== Received: from AM0PR02CA0082.eurprd02.prod.outlook.com (2603:10a6:208:154::23) by AS8PR07MB7495.eurprd07.prod.outlook.com (2603:10a6:20b:2ab::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.15; Fri, 9 Aug 2024 20:24:18 +0000 Received: from AM3PEPF0000A794.eurprd04.prod.outlook.com (2603:10a6:208:154:cafe::a6) by AM0PR02CA0082.outlook.office365.com (2603:10a6:208:154::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.14 via Frontend Transport; Fri, 9 Aug 2024 20:24:18 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by AM3PEPF0000A794.mail.protection.outlook.com (10.167.16.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.8 via Frontend Transport; Fri, 9 Aug 2024 20:24:18 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.66) with Microsoft SMTP Server id 15.2.1544.11; Fri, 9 Aug 2024 22:24:15 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id 9EF911C006D; Fri, 9 Aug 2024 22:24:15 +0200 (CEST) From: =?utf-8?q?Mattias_R=C3=B6nnblom?= To: CC: , =?utf-8?q?Morten_Br=C3=B8rup?= , Tyler Retzlaff , Stephen Hemminger , Harry van Haaren , =?utf-8?q?Mattias_R=C3=B6nnb?= =?utf-8?q?lom?= Subject: [PATCH 3/6] eal: add atomic bitset functions Date: Fri, 9 Aug 2024 22:14:37 +0200 Message-ID: <20240809201440.590464-3-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240809201440.590464-1-mattias.ronnblom@ericsson.com> References: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> <20240809201440.590464-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM3PEPF0000A794:EE_|AS8PR07MB7495:EE_ X-MS-Office365-Filtering-Correlation-Id: f8263dd2-6de7-4a40-2e99-08dcb8b13ec9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|376014|82310400026|36860700013; X-Microsoft-Antispam-Message-Info: =?utf-8?q?Sm+qAZeouHuchAEs4Oz5jlGSl1d8+7f?= =?utf-8?q?pzYgFxkgFpfmZpYhao/sFdsgUttS6CXapLyIR1+9YvWEq+wnXWGSGcDc729euPkXJ?= =?utf-8?q?gHEIsXsngxv8506Tz0VRlLu69o+YCjWmNCPC2uWEAcR3J9T4dv8qYMn+BTc1cXiG2?= =?utf-8?q?2cpALTnA6xTQc4Ox1gRIC/BlZc/uOdqZ5MOrL618/pAAKUvNRva7CQsybMMQrvm31?= =?utf-8?q?/HJD3qjPNKV8D7fJ7YAP8mPi3PwgghjBugZ8WnxNZj2M/LjxMVIHMwqrw/7WQuVmY?= =?utf-8?q?kE9crezjisz44zClM1KPYD6rzPO/bC8lbmPyDxeLSlj7XJfBCTrmnl6PjOZEssT9r?= =?utf-8?q?dsM92yFTCkTJga+jS1Tgf6+Qs1XxImlH4nEvtqd9We+voleCQil+BqRFcoH2XjEhM?= =?utf-8?q?UqjfUfE+vUGuQgClc2Pfwq61nnyfjczlQjzev6F/k91XJhM3fG0RKr8Fe6xtJxVJb?= =?utf-8?q?TkQ2vtI51YRARNb5FkCln+uus9g1H9RXo+AQz9H5mti2u3s5KN1EaFLFkwRV+Y1OI?= =?utf-8?q?Jn+HK0Vm/MWF1Cb2+rEcJj/ARh2Z7ZZfFpbFVtDCnFig7ThoEpi8IaVVEWG0dB5HC?= =?utf-8?q?vIOvD7HM67BHUFwEnTSOt+/W7+S8Bj+l0ydKbgKTYvqxdIMb3uAh7E86I/YC2zWqZ?= =?utf-8?q?V24sCCtvyMXzgr02i5qppAzdWc+6gcgxIwbVlTTOFMB5+HMDhp+ibJkA2o2eyc3w4?= =?utf-8?q?r2wpBl4alI149QWdvZajq7SM5n9LPcGEbZJsWCVsKz3EMjcoTba7XBJ8aMXRMI8TR?= =?utf-8?q?WJO1dpDmr1oKscSRN/uuQt7b2mgFE/kXkOt9rDoSHe3TonDgwn6ZbWVjEasb2GGwI?= =?utf-8?q?+kf6iqxmtpWX8aE3vyB1Vghx0hC1F/mxQGdX5d6KX4oHwiiGnNbD0ygM96l0zKd56?= =?utf-8?q?1LGIwNMf2HHiRUpoiHGnsf59r/6a9UomsntBnCRGqSqJZbXuWprnBZbDjBFb9fmhP?= =?utf-8?q?DjII8RKdQ9cupZraePf2fXTiBfktwQNer8ttnQtJAQ+N/J64Wj3Pqs9OAYj28lQOe?= =?utf-8?q?b3N68WqeUhUq0xhWk4vlHGPmy0qPUK5z5lNyxLr3clieQKOinpEgsXkfuqxnAHmNP?= =?utf-8?q?SVpC1QhlH4b/0GikuLZEQo/3sXox58WPwmvuK+JmRKKN1UK089VKDadPISDxiDZz7?= =?utf-8?q?ZXZa+zLdQeWzVy2a8Dd09Is/sD9YOjo404YxtW54x690oGQAJNrgaDIC9C2FxRGYs?= =?utf-8?q?Exu5aFLsUoPfRnfYO5flFzjnLrYwOFSShkNfxzxcmedE3kCV8YVGPDP3HyK+G1rJ1?= =?utf-8?q?tSlDqJn0czsR5A2YlvsMPYQIyPv8ZG2yYBKemEGpQvnXv53A9dRIpg8p3Xn+HVsZH?= =?utf-8?q?4TCYcWKet6eUPSNz+Petl5rVfyGeiuHi+g=3D=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(1800799024)(376014)(82310400026)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 20:24:18.1393 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f8263dd2-6de7-4a40-2e99-08dcb8b13ec9 X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: AM3PEPF0000A794.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR07MB7495 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 Extend the bitset API with atomic versions of the most basic bitset operations. Signed-off-by: Mattias Rönnblom Acked-by: Tyler Retzlaff --- lib/eal/include/rte_bitset.h | 155 +++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/lib/eal/include/rte_bitset.h b/lib/eal/include/rte_bitset.h index 49a07c77b8..c0441b0e22 100644 --- a/lib/eal/include/rte_bitset.h +++ b/lib/eal/include/rte_bitset.h @@ -376,6 +376,161 @@ rte_bitset_flip(uint64_t *bitset, size_t bit_num) __RTE_BITSET_DELEGATE(rte_bit_flip, bitset, bit_num); } +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Atomically test if a bit is set. + * + * Atomically test if a bit in a bitset is set with the specified + * memory ordering. + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * Index of the bit to test. Index 0 is the least significant bit. + * @param memory_order + * The memory order to use. + * @return + * Returns true if the bit is '1', and false if the bit is '0'. + */ + +__rte_experimental +static inline bool +rte_bitset_atomic_test(const uint64_t *bitset, size_t bit_num, + int memory_order) +{ + return __RTE_BITSET_DELEGATE_N(rte_bit_atomic_test, bitset, bit_num, + memory_order); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Atomically set a bit in the bitset. + * + * Set a bit in a bitset as an atomic operation, with the specified + * memory ordering. + * + * rte_bitset_atomic_set() is multi-thread safe, provided all threads + * acting in parallel on the same bitset does so through + * @c rte_bitset_atomic_*() functions. + * + * Bits are numbered from 0 to (size - 1) (inclusive). + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be set. + * @param memory_order + * The memory order to use. + */ + +__rte_experimental +static inline void +rte_bitset_atomic_set(uint64_t *bitset, size_t bit_num, int memory_order) +{ + __RTE_BITSET_DELEGATE_N(rte_bit_atomic_set, bitset, bit_num, + memory_order); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Atomically clear a bit in the bitset. + * + * Clear a bit in a bitset as an atomic operation, with the specified + * memory ordering. + * + * rte_bitset_atomic_clear() is multi-thread safe, provided all + * threads acting in parallel on the same bitset does so through @c + * rte_bitset_atomic_*() functions. + * + * Bits are numbered from 0 to (size - 1) (inclusive). + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be cleared. + * @param memory_order + * The memory order to use. + */ + +__rte_experimental +static inline void +rte_bitset_atomic_clear(uint64_t *bitset, size_t bit_num, int memory_order) +{ + __RTE_BITSET_DELEGATE_N(rte_bit_atomic_clear, bitset, bit_num, + memory_order); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Atomically set or clear a bit in the bitset. + * + * Assign a value to a bit in a bitset as an atomic operation, with + * the specified memory ordering. + * + * rte_bitset_atomic_assign() is multi-thread safe, provided all + * threads acting in parallel on the same bitset does so through + * @c rte_bitset_atomic_*() functions. + * + * Bits are numbered from 0 to (size - 1) (inclusive). + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be set or cleared. + * @param bit_value + * Control if the bit should be set or cleared. + * @param memory_order + * The memory order to use. + */ + +__rte_experimental +static inline void +rte_bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value, + int memory_order) +{ + __RTE_BITSET_DELEGATE_N(rte_bit_atomic_assign, bitset, bit_num, + bit_value, memory_order); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Atomically change the value of a bit in the bitset. + * + * Flip a bit in a bitset as an atomic operation, with the specified + * memory ordering. + * + * rte_bitset_atomic_flip() is multi-thread safe, provided all threads + * acting in parallel on the same bitset does so through + * @c rte_bitset_atomic_*() functions. + * + * Bits are numbered from 0 to (size - 1) (inclusive). + * + * @param bitset + * A pointer to the array of words making up the bitset. + * @param bit_num + * The index of the bit to be flipped. + * @param memory_order + * The memory order to use. + */ + +__rte_experimental +static inline void +rte_bitset_atomic_flip(uint64_t *bitset, size_t bit_num, int memory_order) +{ + __RTE_BITSET_DELEGATE_N(rte_bit_atomic_flip, bitset, bit_num, + memory_order); +} + /** * @warning * @b EXPERIMENTAL: this API may change without prior notice. From patchwork Fri Aug 9 20:14:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Mattias_R=C3=B6nnblom?= X-Patchwork-Id: 143057 X-Patchwork-Delegate: thomas@monjalon.net 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 2F6A24577D; Fri, 9 Aug 2024 22:24:34 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DA18042E74; Fri, 9 Aug 2024 22:24:21 +0200 (CEST) Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2087.outbound.protection.outlook.com [40.107.22.87]) by mails.dpdk.org (Postfix) with ESMTP id 5768742DB1 for ; Fri, 9 Aug 2024 22:24:19 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=RBoxTcnZi0NMVlEyaUnMcz5+hqn/ZO351dBFhkGYMvks5YNi8wv7SMz/3U9MlFn7DjCo3l+uImfEWHTaI/tCjVP7zA+6KBHqUVLFo1u9shl82OVCiDBTGBy7/4TNAK2ZggwmOSuff5ISnbggK2Acl8HqynJoUywzIA8zbhoSvvpGvTyvjS4vBUUaRICnLh75NzTWCuebOh2XJkWWALSUfZaGcA3jqy9GqRy9umuXt3jDXGAksCx3rIeKvvGW5CbAQvMG13rtwIFhfWWcFzwLWEfoVAQWetoScdWGHnw5SrFKyOIKhBnbcwpsMpEtlAUqbOYY1NDQKEOpOgcJ6UOETA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=pgqb9JEA77f9APhXHTEjz7+NixtL0Wc7nymsW0DjEkk=; b=m2Vji0bQWI4oJOuVVwnPrYJT4Fh2eVIpJ2m6jPn49QMYAkLGq4ZJTq+Q5JaMXKnFT29e+CElHSo8Q+3OsDFbyynFkrLGRKj6MLvAkOixjiKB6ePMwRzhF9IXoIOZHAZu18XH7WDpFThA31ub1kb1gfsVUg+G+aJAkBReHI2Q2zLHykJgKuV3Bi6BmzFRVrHx/vySe6bYO4A1UPRqUJPeztdv1h1u7RT9OiDCiO3k6AOcPhTF+hYAB5iZmNRlKZ5I3YQGWtamQZMoXB17yF6cJ/XqC01w8yOygbMlMrnI4Q0wJBEKxGFz8HzDc+IC4jNlp6a5PLeUOb1YbQOxZWD3vQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pgqb9JEA77f9APhXHTEjz7+NixtL0Wc7nymsW0DjEkk=; b=u0fJ0d40fXeI2k4463hDyNrfnnt/VZWFoQWYw/rPxKvkktc+Q63lUgruOzKEiBt/CcwPelJgJqnTM85azrF/+m6iRa9bRkzwQLHJKaUab+RggY7CErKF5t+oLun/Vf9JhgdM/mhnJ4eYTsNg/+Y8RXDt5iHctkCh+Ns3ygfk5+YplZvKkQ25fvt95agKEh6iQKx5nbXO4f5yHaUfk9JlDys6eZYuG4VXAWMJiTCkkblTaj7wi/3tOVsmv1lVqNlzqO8/b8761bv20r5DzRiFim8lnHz5OZMfRZlMjdnWu76fcIzsXLp3w5tKinkFBFCh7DudVZ3c+CwVepepCYRDKA== Received: from DUZPR01CA0167.eurprd01.prod.exchangelabs.com (2603:10a6:10:4b3::8) by AS8PR07MB8249.eurprd07.prod.outlook.com (2603:10a6:20b:378::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.15; Fri, 9 Aug 2024 20:24:16 +0000 Received: from DB1PEPF000509FA.eurprd03.prod.outlook.com (2603:10a6:10:4b3:cafe::2) by DUZPR01CA0167.outlook.office365.com (2603:10a6:10:4b3::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.17 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by DB1PEPF000509FA.mail.protection.outlook.com (10.167.242.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.19 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.68) with Microsoft SMTP Server id 15.2.1544.11; Fri, 9 Aug 2024 22:24:15 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id AE9621C006A; Fri, 9 Aug 2024 22:24:15 +0200 (CEST) From: =?utf-8?q?Mattias_R=C3=B6nnblom?= To: CC: , =?utf-8?q?Morten_Br=C3=B8rup?= , Tyler Retzlaff , Stephen Hemminger , Harry van Haaren , =?utf-8?q?Mattias_R=C3=B6nnb?= =?utf-8?q?lom?= Subject: [PATCH 4/6] eal: add unit tests for atomic bitset operations Date: Fri, 9 Aug 2024 22:14:38 +0200 Message-ID: <20240809201440.590464-4-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240809201440.590464-1-mattias.ronnblom@ericsson.com> References: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> <20240809201440.590464-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB1PEPF000509FA:EE_|AS8PR07MB8249:EE_ X-MS-Office365-Filtering-Correlation-Id: 7b907f71-6a08-4e69-75b6-08dcb8b13dda X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|376014|1800799024|36860700013; X-Microsoft-Antispam-Message-Info: =?utf-8?q?/66WGMnlVaDTnA3PhvlV4q8k36Gf5ie?= =?utf-8?q?FD5SQtMFI+ek76dj+ponBMcNw5aC7tmyGJp/L8nMg+exch13r4Yy5jBtFRxx4Nc3B?= =?utf-8?q?i3N0lSd0xaa9M+HcKFCUFPMGm2t2x3xCGdm4PLWfAg+NOoBDErQNUu/tgqCARCAQV?= =?utf-8?q?vR9xLhIa+Fp1VHiROLiaXJpHrj2I/xI0p5J/JJFlCOd4jyp5EVQXNhU5u/igpthYS?= =?utf-8?q?nFYY6ebt/d//XwzlYL5kmhiL1q91nBq/g0e0BNiyWMUkxKN7VKiqoGgkB7J97s9hW?= =?utf-8?q?UOimhDS8tAgHOVJVZHL8K9+G4dhdVJ7Gj8vbo+4YObdbErvknk3x1ovWNrAo/qlqt?= =?utf-8?q?fr6VTL48QOHVc0Hpj5MJozgrqDUGifidNfdk5BUyvJwbABOt1Md2rIx2DPd3tqITP?= =?utf-8?q?LZx+lN+pDLmnum3bBxy8ZDOEuHZTTlj2RJH/ViOQoFeRpUEzjZHWA0L/vm88Gdl7/?= =?utf-8?q?Ql7xafH9NrLfXgIQHFP4m7uRL8kCOD5uCo//ru/Ac8yRtAXtj1KbvJBI4EhtBSdCt?= =?utf-8?q?9uRAyhBtbzsq5p7nmGOw9C3TMosGkQlMuMsPxdUPalmhIuVQs/PLhUmkBFyI4wYHB?= =?utf-8?q?2SHsghTEZre8VIkF0UzyU4R9BjIbHBetQmJ7xxTG9O2EtFmRHD+oUizvKu2WlAvhl?= =?utf-8?q?MSw7auJlR9dbwr0EgZe9NZ4dLWRkbUNB2ZqTw90PKxExl92q2exk3gzjLnH/j/3hU?= =?utf-8?q?dA1a7PzGqowrMRtujO4Rgu9na6EdcEgq+rB8X47/4HaNvQNUh77z1cid+zPo6eAlG?= =?utf-8?q?H/OZzgCp5RotHp6ZWAhfYtslW3m7D/VfPE3sQV2MAeJ2k2N7epA00846PbSy5raba?= =?utf-8?q?P4+5yoWf/FEzggIPFk+FzYkrvLYpQpdpnO8XVqA11/qY6ulWWiF4hK5YsJM37AOLV?= =?utf-8?q?jc4KCq1vlNoTGb21eiB8Q2v87w/rxtOXlkzZINUQOscjNhRxWHr+0s/emGQ4+cZwb?= =?utf-8?q?slldzcqPvcB65Bjg7RZV9lMcgRd1HDoc5KoPj024H2/pNUe5ETDPKUrZr7bp1ZigJ?= =?utf-8?q?qjxFFnvjyJAIX2/OiTPFAB9U0IdUxEHdkfTLm7Q3GVf5VaGmqdyoJsPqaWsB+0n2j?= =?utf-8?q?wcosGcVGnOfygQRTSzqZ8uKI3PlZun4ByO9l11GUjuf8OdWYwDPOeqj/y/sFb7+aG?= =?utf-8?q?TMBeNW1/YSArUFy/Y5+/NjUBi9LksrHFy/bRWfy/IqX4CNgoRAmiQWdwPfQ6XKBEi?= =?utf-8?q?qhtAJaxfxKrtx2tfVGEAzX7B88GnDgX2YxAZgjcr/6vynxkYaNWnS8AcT0o+1WP3i?= =?utf-8?q?u6jZLifCRT5y38VaSSUeoWVJBxMgnnWhoQov5Zm8JV95nDSTd1FPUiIBsk5zSj8l1?= =?utf-8?q?WmZc1AZepE2bdO2gnlfEraMNIaTOAFrSBg=3D=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(82310400026)(376014)(1800799024)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 20:24:16.5279 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7b907f71-6a08-4e69-75b6-08dcb8b13dda X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: DB1PEPF000509FA.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR07MB8249 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 Extend bitset tests to cover the basic operation of the rte_bitset_atomic_*() family of functions. Signed-off-by: Mattias Rönnblom --- app/test/test_bitset.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/app/test/test_bitset.c b/app/test/test_bitset.c index b3496df1c0..32224a1eee 100644 --- a/app/test/test_bitset.c +++ b/app/test/test_bitset.c @@ -222,6 +222,52 @@ test_flip(void) rte_bitset_flip); } +static bool +bitset_atomic_test(const uint64_t *bitset, size_t bit_num) +{ + return rte_bitset_atomic_test(bitset, bit_num, + rte_memory_order_relaxed); +} + +static void +bitset_atomic_set(uint64_t *bitset, size_t bit_num) +{ + rte_bitset_atomic_set(bitset, bit_num, rte_memory_order_relaxed); +} + +static void +bitset_atomic_clear(uint64_t *bitset, size_t bit_num) +{ + rte_bitset_atomic_clear(bitset, bit_num, rte_memory_order_relaxed); +} + +static void +bitset_atomic_flip(uint64_t *bitset, size_t bit_num) +{ + rte_bitset_atomic_flip(bitset, bit_num, rte_memory_order_relaxed); +} + +static void +bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value) +{ + rte_bitset_atomic_assign(bitset, bit_num, bit_value, + rte_memory_order_relaxed); +} + +static int +test_atomic_set_clear(void) +{ + return test_set_clear_fun(bitset_atomic_test, bitset_atomic_set, + bitset_atomic_clear); +} + +static int +test_atomic_flip(void) +{ + return test_flip_fun(bitset_atomic_test, bitset_atomic_assign, + bitset_atomic_flip); +} + static ssize_t find(const bool *ary, size_t num_bools, size_t start, size_t len, bool set) { @@ -868,6 +914,8 @@ static struct unit_test_suite bitset_tests = { .unit_test_cases = { TEST_CASE_ST(NULL, NULL, test_set_clear), TEST_CASE_ST(NULL, NULL, test_flip), + TEST_CASE_ST(NULL, NULL, test_atomic_set_clear), + TEST_CASE_ST(NULL, NULL, test_atomic_flip), TEST_CASE_ST(NULL, NULL, test_find), TEST_CASE_ST(NULL, NULL, test_foreach), TEST_CASE_ST(NULL, NULL, test_count), From patchwork Fri Aug 9 20:14:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Mattias_R=C3=B6nnblom?= X-Patchwork-Id: 143056 X-Patchwork-Delegate: thomas@monjalon.net 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 4E9F24577D; Fri, 9 Aug 2024 22:24:26 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A9E8842E58; Fri, 9 Aug 2024 22:24:20 +0200 (CEST) Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2056.outbound.protection.outlook.com [40.107.21.56]) by mails.dpdk.org (Postfix) with ESMTP id DC5C042DC1 for ; Fri, 9 Aug 2024 22:24:18 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=JK96aCr6jdwgzJs47jUWe/RF0UXSiFk7zY0OA+TIXWzR2/XSgv9yIZpySNnLhgrLydyvu8JsA2+KgkcdCB5tv5wygqKnpFOGaXHJDv8QjOwngmweD5r1ETfp10ioj+SDMpKHzYNEEDDdfChNMZ1FXZgx30LaAhvBh7t+g+pJ6N0RhgDCg9z0tiO8bkwR8/CH0Vj2020LCFHjfNg/pi7T/a6brTu1fmXHWhJh5kvtJjun7pq2fXHAKSq0IH3zS87L2a1G2P+i4NzGic78Ok5stbPTpxduCWmRcOIKEVPvmAjMAroIHNSKaDxPCC8cKVMuIfSPdRpzk5qYXyMUEjNnOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Mx2k72mHtMfvaE5BD+qrppgugwcEHxL9T3OLZibFkgE=; b=YCyz/MDHIOcqSORyiw56HlV3fI6v9vBrvQnkDHktoLD1O7IJ3PpEUfC8Eas+Z4yM85tqea1Zb3CiGi5OOLNBEQFzswxrsKtvAwrXSGQaCLADVlXGLShBMBQ9thnq4squm8H7WSuee63hBKxQ5JwspeDoyB4zTykwMhznx8flroGZwfGf5+HCfL9Cib+/EQpND6jS+ZVgrT58NHJctuzg88VUVMRt5xRyQR0lW4K5MmkjjCsGreoiot7ssjy26c1usxe3LNgYuWXx1KYt2d5ktcYxs4JfgbU6TvmjI8lQFQZunuuKyH030VhVPBzGKa5z2qZ7szdiwAGta7yisnLwpw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Mx2k72mHtMfvaE5BD+qrppgugwcEHxL9T3OLZibFkgE=; b=dcgp5Lvzh8n9n6NHCTlSMg8sTvp4Xxv2rjdWmwOJuZmLhn37f08Zl3Th32yA2ZtndMrnSN22GnMsT5FR6pfw9lWZbpOjmhZUXwUt7oQMP+qiJx2EAmuVnF7+xej1Tb1PXRRTJcORYsyAMl5MjdInXyT9+47jxTmie0WLHR7uh0Tc76Tz82pcfMTEJhxZdmy6D0J55EaQ+CYRh6jt3HY+SmpUQXDCT7PrSzGzifg/WBSKFznnRdz3143rUegmnhtUPHI3E/V90JpNDyXDsEz9DWP35Ri9BPDDFTuPxTyO3c9rm8X20Uaox1XjY9MOS5M/VE4PGjXpZ8+vIc9UyXgzzg== Received: from AM4PR07CA0028.eurprd07.prod.outlook.com (2603:10a6:205:1::41) by DBAPR07MB6583.eurprd07.prod.outlook.com (2603:10a6:10:184::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.15; Fri, 9 Aug 2024 20:24:16 +0000 Received: from AM4PEPF00027A6C.eurprd04.prod.outlook.com (2603:10a6:205:1:cafe::4f) by AM4PR07CA0028.outlook.office365.com (2603:10a6:205:1::41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.10 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by AM4PEPF00027A6C.mail.protection.outlook.com (10.167.16.90) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.8 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.65) with Microsoft SMTP Server id 15.2.1544.11; Fri, 9 Aug 2024 22:24:15 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id BD8EF1C006B; Fri, 9 Aug 2024 22:24:15 +0200 (CEST) From: =?utf-8?q?Mattias_R=C3=B6nnblom?= To: CC: , =?utf-8?q?Morten_Br=C3=B8rup?= , Tyler Retzlaff , Stephen Hemminger , Harry van Haaren , =?utf-8?q?Mattias_R=C3=B6nnb?= =?utf-8?q?lom?= Subject: [PATCH 5/6] service: use multi-word bitset to represent service flags Date: Fri, 9 Aug 2024 22:14:39 +0200 Message-ID: <20240809201440.590464-5-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240809201440.590464-1-mattias.ronnblom@ericsson.com> References: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> <20240809201440.590464-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM4PEPF00027A6C:EE_|DBAPR07MB6583:EE_ X-MS-Office365-Filtering-Correlation-Id: 89e920d8-050b-4bdd-eaf2-08dcb8b13d9d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|1800799024|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?utf-8?q?2+rXoIcJzQF17/RlhQlnFn/an+TBews?= =?utf-8?q?1bRijVbZtO+kp1pBRN8a3Me0t8Im/1HmKbecFImk5GrffqcVFf564hpFlflpPHdD1?= =?utf-8?q?/69s978YKYyzz3YfO9ws4uIntBzT+2QXAoVnH/DhaqwvgRVWVpD4pfiqnW7O3wy2t?= =?utf-8?q?fvhnuf9UpNiFIrYjP0ATjYuhvmB4QIAPPfAfA5QQzyR91BelojWHQ7FrcywPhUPMs?= =?utf-8?q?Cm6qOiStg0Okr2286McntIYizeiQcvJfoAKqPhIGgeQ5oUXvevHhFcLt5rWl3bSXw?= =?utf-8?q?eGachUATOJO/AbkcnTA+c2R7QILgSyUh0aCy5LHYf+4MeRs5d6PcKTw/WhkU/wpiG?= =?utf-8?q?M2NYNE+2WdindbkFz1YiEIKRzYHP7y8g2cbioCg9TYkYtl/sq/8NQsW5inAR5zoN/?= =?utf-8?q?14muqBvoeDWaZcQok4eceIRHEQCIQaBsa7geyr/odfQw76NauktJkp29za1kXPdjE?= =?utf-8?q?PJZudK6QAkhTyQPQuFR4aXvk7hu4CR7g2pzn1tjaBl+Azh9EDBhCk42lsWWTbocvR?= =?utf-8?q?4uEAcn636fJSA3ytaku+DO2Bt8U5rZBizCEkqnd1KKKAJDeG9FSPON/cHBJq/mp6B?= =?utf-8?q?AbhEZyfIkNqVkhZSb6QqsfkMJSt00jXC0Yy9giLENqc4rxvWOzfRRuNd8CTIi/fAv?= =?utf-8?q?PxUSK4mDrQQUoJ7vXrwSkusw2rlgi3LqSIhy26ySEwHL1JagOWQHjCsoqN8silIIF?= =?utf-8?q?Z6MbdmWS7msRphthcyGuBH0B9UO6nvY343ZHuqVRiWhgZ/Gefwp3VwV3LZagg4QlG?= =?utf-8?q?EZLIfkYqT85SEl57h3WacQd8ZDE67dOVtxZ1Do2KVDdeQc1wvPDlOGtgxUbww0Ckj?= =?utf-8?q?TL45uF1Oibp4WLTuRI+UtHvfF98zUlxG4R6jFyFue26lH31SF9ZsUUDKvh0ZsU6ie?= =?utf-8?q?S5p4s5IZQVDYS3oOxEs6CTrnmSSwBQ7RwVObfomNMY/saemixschkPI4R5RO0+rOu?= =?utf-8?q?WMAIGay0/5QztxzAkyOMaCj67sqyI95AP7ZArdakaElorXtm3LovwkGtmyOt9lnZ9?= =?utf-8?q?Cf4nWZK1DuoLAmJkiHOlDSeNS0wPXpwt0KP6KGoWhORu9JL1NJyGDFjLy1N39fuLy?= =?utf-8?q?Z1hoBuWRLDAwhLsxJU7wNVwFBghqVpomJBNMlGzT/r+m9r9tdpQlw2zG6yu2pKWIt?= =?utf-8?q?TkDBh+vINe3v9Y4N94WPQkx8TfGUkq5qJR/tEx+5XirCv2VhH5aRB+kgntFmawfFD?= =?utf-8?q?LjDcT7ewQWN2DoqIRyvjpK8wJ2EEoSTVcamH9fY2obLj3bd3YfRJ8B1Ui8KQFhKuZ?= =?utf-8?q?cu9xLkjWrcR52tze0g2i0V3uHZSri5fXllC+FZBOJEAVqGMYaGL7T7i7IYlZwdDqM?= =?utf-8?q?/8/BMMd7/afVQzzAcJv5lu901RbpHaOA0w=3D=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(36860700013)(1800799024)(376014)(82310400026); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 20:24:16.1780 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 89e920d8-050b-4bdd-eaf2-08dcb8b13d9d X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: AM4PEPF00027A6C.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBAPR07MB6583 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 Use a multi-word bitset to track which services are mapped to which lcores, allowing the RTE_SERVICE_NUM_MAX compile-time constant to be > 64. Replace array-of-bytes service-currently-active flags with a more compact multi-word bitset-based representation, reducing memory footprint somewhat. Signed-off-by: Mattias Rönnblom Acked-by: Tyler Retzlaff --- lib/eal/common/rte_service.c | 70 ++++++++++++++---------------------- 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/lib/eal/common/rte_service.c b/lib/eal/common/rte_service.c index 56379930b6..ec0f47e141 100644 --- a/lib/eal/common/rte_service.c +++ b/lib/eal/common/rte_service.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -63,11 +64,11 @@ struct service_stats { /* the internal values of a service core */ struct __rte_cache_aligned core_state { /* map of services IDs are run on this core */ - uint64_t service_mask; + RTE_BITSET_DECLARE(mapped_services, RTE_SERVICE_NUM_MAX); RTE_ATOMIC(uint8_t) runstate; /* running or stopped */ RTE_ATOMIC(uint8_t) thread_active; /* indicates when thread is in service_run() */ uint8_t is_service_core; /* set if core is currently a service core */ - uint8_t service_active_on_lcore[RTE_SERVICE_NUM_MAX]; + RTE_BITSET_DECLARE(service_active_on_lcore, RTE_SERVICE_NUM_MAX); RTE_ATOMIC(uint64_t) loops; RTE_ATOMIC(uint64_t) cycles; struct service_stats service_stats[RTE_SERVICE_NUM_MAX]; @@ -81,11 +82,6 @@ static uint32_t rte_service_library_initialized; int32_t rte_service_init(void) { - /* Hard limit due to the use of an uint64_t-based bitmask (and the - * clzl intrinsic). - */ - RTE_BUILD_BUG_ON(RTE_SERVICE_NUM_MAX > 64); - if (rte_service_library_initialized) { EAL_LOG(NOTICE, "service library init() called, init flag %d", @@ -296,7 +292,7 @@ rte_service_component_unregister(uint32_t id) /* clear the run-bit in all cores */ for (i = 0; i < RTE_MAX_LCORE; i++) - lcore_states[i].service_mask &= ~(UINT64_C(1) << id); + rte_bitset_clear(lcore_states[i].mapped_services, id); memset(&rte_services[id], 0, sizeof(struct rte_service_spec_impl)); @@ -410,7 +406,7 @@ service_runner_do_callback(struct rte_service_spec_impl *s, /* Expects the service 's' is valid. */ static int32_t -service_run(uint32_t i, struct core_state *cs, uint64_t service_mask, +service_run(uint32_t i, struct core_state *cs, const uint64_t *mapped_services, struct rte_service_spec_impl *s, uint32_t serialize_mt_unsafe) { if (!s) @@ -424,12 +420,12 @@ service_run(uint32_t i, struct core_state *cs, uint64_t service_mask, RUNSTATE_RUNNING || rte_atomic_load_explicit(&s->app_runstate, rte_memory_order_acquire) != RUNSTATE_RUNNING || - !(service_mask & (UINT64_C(1) << i))) { - cs->service_active_on_lcore[i] = 0; + !rte_bitset_test(mapped_services, i)) { + rte_bitset_clear(cs->service_active_on_lcore, i); return -ENOEXEC; } - cs->service_active_on_lcore[i] = 1; + rte_bitset_set(cs->service_active_on_lcore, i); if ((service_mt_safe(s) == 0) && (serialize_mt_unsafe == 1)) { if (!rte_spinlock_trylock(&s->execute_lock)) @@ -454,7 +450,7 @@ rte_service_may_be_active(uint32_t id) return -EINVAL; for (i = 0; i < lcore_count; i++) { - if (lcore_states[ids[i]].service_active_on_lcore[id]) + if (rte_bitset_test(lcore_states[ids[i]].service_active_on_lcore, id)) return 1; } @@ -474,7 +470,9 @@ rte_service_run_iter_on_app_lcore(uint32_t id, uint32_t serialize_mt_unsafe) */ rte_atomic_fetch_add_explicit(&s->num_mapped_cores, 1, rte_memory_order_relaxed); - int ret = service_run(id, cs, UINT64_MAX, s, serialize_mt_unsafe); + RTE_BITSET_DECLARE(all_services, RTE_SERVICE_NUM_MAX); + rte_bitset_set_all(all_services, RTE_SERVICE_NUM_MAX); + int ret = service_run(id, cs, all_services, s, serialize_mt_unsafe); rte_atomic_fetch_sub_explicit(&s->num_mapped_cores, 1, rte_memory_order_relaxed); @@ -485,7 +483,6 @@ static int32_t service_runner_func(void *arg) { RTE_SET_USED(arg); - uint8_t i; const int lcore = rte_lcore_id(); struct core_state *cs = &lcore_states[lcore]; @@ -497,20 +494,11 @@ service_runner_func(void *arg) */ while (rte_atomic_load_explicit(&cs->runstate, rte_memory_order_acquire) == RUNSTATE_RUNNING) { + ssize_t id; - const uint64_t service_mask = cs->service_mask; - uint8_t start_id; - uint8_t end_id; - - if (service_mask == 0) - continue; - - start_id = rte_ctz64(service_mask); - end_id = 64 - rte_clz64(service_mask); - - for (i = start_id; i < end_id; i++) { + RTE_BITSET_FOREACH_SET(id, cs->mapped_services, RTE_SERVICE_NUM_MAX) { /* return value ignored as no change to code flow */ - service_run(i, cs, service_mask, service_get(i), 1); + service_run(id, cs, cs->mapped_services, service_get(id), 1); } rte_atomic_store_explicit(&cs->loops, cs->loops + 1, rte_memory_order_relaxed); @@ -519,8 +507,7 @@ service_runner_func(void *arg) /* Switch off this core for all services, to ensure that future * calls to may_be_active() know this core is switched off. */ - for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) - cs->service_active_on_lcore[i] = 0; + rte_bitset_clear_all(cs->service_active_on_lcore, RTE_SERVICE_NUM_MAX); /* Use SEQ CST memory ordering to avoid any re-ordering around * this store, ensuring that once this store is visible, the service @@ -586,7 +573,7 @@ rte_service_lcore_count_services(uint32_t lcore) if (!cs->is_service_core) return -ENOTSUP; - return rte_popcount64(cs->service_mask); + return rte_bitset_count_set(cs->mapped_services, RTE_SERVICE_NUM_MAX); } int32_t @@ -639,25 +626,23 @@ service_update(uint32_t sid, uint32_t lcore, uint32_t *set, uint32_t *enabled) !lcore_states[lcore].is_service_core) return -EINVAL; - uint64_t sid_mask = UINT64_C(1) << sid; if (set) { - uint64_t lcore_mapped = lcore_states[lcore].service_mask & - sid_mask; + uint64_t lcore_mapped = rte_bitset_test(lcore_states[lcore].mapped_services, sid); if (*set && !lcore_mapped) { - lcore_states[lcore].service_mask |= sid_mask; + rte_bitset_set(lcore_states[lcore].mapped_services, sid); rte_atomic_fetch_add_explicit(&rte_services[sid].num_mapped_cores, 1, rte_memory_order_relaxed); } if (!*set && lcore_mapped) { - lcore_states[lcore].service_mask &= ~(sid_mask); + rte_bitset_clear(lcore_states[lcore].mapped_services, sid); rte_atomic_fetch_sub_explicit(&rte_services[sid].num_mapped_cores, 1, rte_memory_order_relaxed); } } if (enabled) - *enabled = !!(lcore_states[lcore].service_mask & (sid_mask)); + *enabled = rte_bitset_test(lcore_states[lcore].mapped_services, sid); return 0; } @@ -699,11 +684,11 @@ set_lcore_state(uint32_t lcore, int32_t state) int32_t rte_service_lcore_reset_all(void) { - /* loop over cores, reset all to mask 0 */ + /* loop over cores, reset all mapped services */ uint32_t i; for (i = 0; i < RTE_MAX_LCORE; i++) { if (lcore_states[i].is_service_core) { - lcore_states[i].service_mask = 0; + rte_bitset_clear_all(lcore_states[i].mapped_services, RTE_SERVICE_NUM_MAX); set_lcore_state(i, ROLE_RTE); /* runstate act as guard variable Use * store-release memory order here to synchronize @@ -731,7 +716,7 @@ rte_service_lcore_add(uint32_t lcore) set_lcore_state(lcore, ROLE_SERVICE); /* ensure that after adding a core the mask and state are defaults */ - lcore_states[lcore].service_mask = 0; + rte_bitset_clear_all(lcore_states[lcore].mapped_services, RTE_SERVICE_NUM_MAX); /* Use store-release memory order here to synchronize with * load-acquire in runstate read functions. */ @@ -814,12 +799,11 @@ rte_service_lcore_stop(uint32_t lcore) uint32_t i; struct core_state *cs = &lcore_states[lcore]; - uint64_t service_mask = cs->service_mask; for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) { - int32_t enabled = service_mask & (UINT64_C(1) << i); - int32_t service_running = rte_service_runstate_get(i); - int32_t only_core = (1 == + bool enabled = rte_bitset_test(cs->mapped_services, i); + bool service_running = rte_service_runstate_get(i); + bool only_core = (1 == rte_atomic_load_explicit(&rte_services[i].num_mapped_cores, rte_memory_order_relaxed)); From patchwork Fri Aug 9 20:14:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Mattias_R=C3=B6nnblom?= X-Patchwork-Id: 143055 X-Patchwork-Delegate: thomas@monjalon.net 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 B36784577D; Fri, 9 Aug 2024 22:24:19 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8627A42DC9; Fri, 9 Aug 2024 22:24:19 +0200 (CEST) Received: from EUR03-AM7-obe.outbound.protection.outlook.com (mail-am7eur03on2042.outbound.protection.outlook.com [40.107.105.42]) by mails.dpdk.org (Postfix) with ESMTP id A439E42DB1 for ; Fri, 9 Aug 2024 22:24:18 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=eQU8LQ+uDlaaej2taZ7Ux/Kst/PyNyvC79F2awjNGcs2d5f/t0YJgifvUBlHcbYTSG/7Npg4xuZzPsWAhxva/2rytz7w2uWv9AlZ+AuGoeUIQl0P6wNCr1y8fLQNgFhU8ArMEw/sT6dOyxXJilDKrGwQq1+JjCgonxMbOB5mXRIvQFGIP2MgRN8uOrdzZxscWFEbQXQM2escf9r0MsyF/Mj2jjLAcssDmDHlGyOY2OCoSDqBYIQyQ/vGZg95I9Gv18zfRHXNJA+Q6sH97rd6/v9OF2fBdCT93Z/CNg/2eNmpBZ/KayzN+0FRMDXym+YXuNBi0yIdMOSUE8QTU6VOzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Y3A2b1xSKMtegzca54Pq1cB/gX7b5Bwyh3sR2D3R9fk=; b=oJ+FU8PJpDOLBsL/i+FYice1Pd0sCGCl/lgnvbwJqgxQwGkZmSkwWWtwuVlzDiG+sgaYOdvVNb03/ZoEusK3qYu5+xTWIqdR3KtnSY+43zePM5lgvQZFsGXfDdnRME1naBnteFb8rMve+55JDnu/RIPfnu71L/8y87JY/oUxYueJLhj0rtAaQG3pKONxW+gHBC6dYVpr8ioVdGUtUL9Zn+R8x+tBnC3iSoIqK35w25a6Jc0UwnT0CyU7irp/zYgU1nlWXc40c3sFDhSXNUCnka8JcfUSenf4izvRcdwbJ+M5Lq/UBL4Hc7Kzt7t0j9shCXZoDvhgXPhREbAaIEn+JQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Y3A2b1xSKMtegzca54Pq1cB/gX7b5Bwyh3sR2D3R9fk=; b=WJj/LE22jnIp2cSYn6RJ1YOh0GhOSH3xA3AQc7HaHwztvXF25TPM0P0MuDgyrzsCmYT4kexoyfY2JnShQlm8Mphynt2pZAJJcjmhERR3NsvCvO4uzC+2LE9iomWqXE+yaEUk9F/uKPrKCvvSS5ia/RmmkslgfQBFyyV+VRN5FbHlI1ALJt4ilu3JmJx4AlvRG58I5cTGp23mJXJnAX44lMRmpqVN7OcUNc+m2/mjhptIhvxXyGYi1rcxbwvoQXPSurrdsPzDC/cruDaa8m9G8VYlZwXPU5L2eBtMyvSmbXWki6MZLRGUNfv8S9CEBYe30ErzMvIOE/g+mDMLz95VCQ== Received: from DUZP191CA0070.EURP191.PROD.OUTLOOK.COM (2603:10a6:10:4fa::20) by PAXPR07MB8891.eurprd07.prod.outlook.com (2603:10a6:102:24a::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.14; Fri, 9 Aug 2024 20:24:16 +0000 Received: from DB5PEPF00014B94.eurprd02.prod.outlook.com (2603:10a6:10:4fa:cafe::24) by DUZP191CA0070.outlook.office365.com (2603:10a6:10:4fa::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.15 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by DB5PEPF00014B94.mail.protection.outlook.com (10.167.8.232) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.8 via Frontend Transport; Fri, 9 Aug 2024 20:24:16 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.60) with Microsoft SMTP Server id 15.2.1544.11; Fri, 9 Aug 2024 22:24:15 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id C31181C0070; Fri, 9 Aug 2024 22:24:15 +0200 (CEST) From: =?utf-8?q?Mattias_R=C3=B6nnblom?= To: CC: , =?utf-8?q?Morten_Br=C3=B8rup?= , Tyler Retzlaff , Stephen Hemminger , Harry van Haaren , =?utf-8?q?Mattias_R=C3=B6nnb?= =?utf-8?q?lom?= Subject: [PATCH 6/6] event/dsw: add support for larger port count Date: Fri, 9 Aug 2024 22:14:40 +0200 Message-ID: <20240809201440.590464-6-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240809201440.590464-1-mattias.ronnblom@ericsson.com> References: <20240505073313.118515-1-mattias.ronnblom@ericsson.com> <20240809201440.590464-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB5PEPF00014B94:EE_|PAXPR07MB8891:EE_ X-MS-Office365-Filtering-Correlation-Id: 47d335c4-23bc-4006-8c5a-08dcb8b13dcf X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|36860700013|1800799024|376014; X-Microsoft-Antispam-Message-Info: =?utf-8?q?y0CjYR91lCCUMQYoKYQaf5QxhQvgxnW?= =?utf-8?q?19cvLHAJE6K05oAoIhkHzHP7UsbFnyAIlIGYe5DFAotxSq/a7PUAsUf8vJXsKQjJO?= =?utf-8?q?+KWgvZGoE/Lw96Y+/XNHLazBz1hyi4g28KYBC1skijS5fPh8dJ5spPCJUA9QrsWN2?= =?utf-8?q?eYR39B/U/LKsZv962opdXpBJzrwaSSuzePBPvSDpdSAPWDbua8QvyQ235C542Zj3O?= =?utf-8?q?kuR8/7vqcg77m4KMuxXykNc/Mo3E8k6v1XinclIFVuclUhmi06LZ4RhZzJfZC0qhl?= =?utf-8?q?kPVgKansKA7xEt9HEQeOkWq30zJ+vv75rfqTD3T/3Nthh6gIOmnqJh6tfXho9uUXD?= =?utf-8?q?pwLd63Ew781f5B+FjIhI57I0yI4/1LjxAyvLZf33u82lonXWqv1MtYtGyoWfUdAnq?= =?utf-8?q?hO0BgP6u70rFW6g48KLcHpedoP98mVlnH9NFE0cbmqmCnBOUmERPUukcpFGoaXYHO?= =?utf-8?q?HSflrAAFOXhQd4XjFpDobJcigQxRN7LNev5k1RFg93odV9SepDyXw+Fms8g4Lb51y?= =?utf-8?q?TA39jQiWGTjUJIeW5XeZEiOAnAd6fhoQK9jTgHb6XjE+OvMxwnAieoqrdtINrx3EZ?= =?utf-8?q?nqBzheEu5Wh+gyf9o79hq7veIcnzRZpHTiI3GO67PnhqA2JYPVYphJDYmEzvTSXR0?= =?utf-8?q?MhV2ENGu0mW8MTrZVyogIqwlHlNE8Sj9ViLO1s+EggKpmec2vSK0DlJG7rwD1NgWp?= =?utf-8?q?hBXgoqZ3d6QZzMBfkDmVkHnw/PKQi8nMGy2U9kO8v1U+t4p4W1U/uoob4A+fD9qso?= =?utf-8?q?JtEntF6bLUgvuDGjQAoUWqDlwl0WTMhvHeHn2hfUXuEx9ckfu2stfEFHnRruUjGgj?= =?utf-8?q?I3VAx7enhTD75zP7RDkEiq78DFE6P7tX16ZhKJ7fsR0N7AcsrjPNeeNCjkPybLkY5?= =?utf-8?q?1HpZcKCxyJdedI5I1i1gHFDme5AcO3yDiMb6cSYlBuxcg462Wmk/gDSlSDxS/7S71?= =?utf-8?q?M1MpPS67vrI9TxgiV3axrlv1zH/RIN7CRaIZhAO7/lUaybieH/vgtZBqovY+bJZNn?= =?utf-8?q?va+MhM8jtezhFaZ4wYOfapqfyvyLu1xPOxGeyfbEvNUwYxTOOhialxUcAqbSrF0MU?= =?utf-8?q?Vn+frVMATtNlqR+BzQbAN5PkyOMsewqmkMgxunjsmkrerQMzJBpxZAyH9ooatqlZ4?= =?utf-8?q?26GvzkOQNI63GXA85tU0Y2UXbDegb/m/sNBKrGnFJb5Sc6RnDAw5PfaEx0hyNe9NA?= =?utf-8?q?aoJD6rfY9ZzHQNNOvUXuU9XmWu8kEbP2an8GE8PQGhYZjMamjKBPLp2mRG4CRAZAP?= =?utf-8?q?SbOKGFn9I+nZWovx5JJV4K5T7M25AKYC49/gfHd/+F02NgL8bJqY8EJi+6CzxxMAp?= =?utf-8?q?SQouzuk4yPxcWUUie7xxMUw8X/EqstfKcw=3D=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(82310400026)(36860700013)(1800799024)(376014); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 20:24:16.4720 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 47d335c4-23bc-4006-8c5a-08dcb8b13dcf X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: DB5PEPF00014B94.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR07MB8891 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 Switch from using an open-coded, single-word bitset to using to represent which event ports are linked to a particular event queue. Besides the cleaner code, this also allow the user to extend the maximum port count beyond 64, by means of changing an "event_dev.h" Signed-off-by: Mattias Rönnblom Acked-by: Tyler Retzlaff --- drivers/event/dsw/dsw_evdev.c | 19 +++++++------------ drivers/event/dsw/dsw_evdev.h | 3 ++- drivers/event/dsw/dsw_event.c | 7 ++++--- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/event/dsw/dsw_evdev.c b/drivers/event/dsw/dsw_evdev.c index 0dea1091e3..961217334e 100644 --- a/drivers/event/dsw/dsw_evdev.c +++ b/drivers/event/dsw/dsw_evdev.c @@ -123,6 +123,7 @@ dsw_queue_setup(struct rte_eventdev *dev, uint8_t queue_id, queue->schedule_type = conf->schedule_type; } + rte_bitset_init(queue->serving_ports, DSW_MAX_PORTS); queue->num_serving_ports = 0; return 0; @@ -149,20 +150,16 @@ dsw_queue_release(struct rte_eventdev *dev __rte_unused, static void queue_add_port(struct dsw_queue *queue, uint16_t port_id) { - uint64_t port_mask = UINT64_C(1) << port_id; - - queue->serving_ports |= port_mask; + rte_bitset_set(queue->serving_ports, port_id); queue->num_serving_ports++; } static bool queue_remove_port(struct dsw_queue *queue, uint16_t port_id) { - uint64_t port_mask = UINT64_C(1) << port_id; - - if (queue->serving_ports & port_mask) { + if (rte_bitset_test(queue->serving_ports, port_id)) { queue->num_serving_ports--; - queue->serving_ports ^= port_mask; + rte_bitset_clear(queue->serving_ports, port_id); return true; } @@ -263,14 +260,12 @@ initial_flow_to_port_assignment(struct dsw_evdev *dsw) struct dsw_queue *queue = &dsw->queues[queue_id]; uint16_t flow_hash; for (flow_hash = 0; flow_hash < DSW_MAX_FLOWS; flow_hash++) { - uint8_t skip = - rte_rand_max(queue->num_serving_ports); + uint8_t skip = rte_rand_max(queue->num_serving_ports); uint8_t port_id; for (port_id = 0;; port_id++) { - uint64_t port_mask = UINT64_C(1) << port_id; - - if (queue->serving_ports & port_mask) { + if (rte_bitset_test(queue->serving_ports, + port_id)) { if (skip == 0) break; skip--; diff --git a/drivers/event/dsw/dsw_evdev.h b/drivers/event/dsw/dsw_evdev.h index c9bf4f8b6b..606c1e9f8a 100644 --- a/drivers/event/dsw/dsw_evdev.h +++ b/drivers/event/dsw/dsw_evdev.h @@ -7,6 +7,7 @@ #include +#include #include #include @@ -237,7 +238,7 @@ struct __rte_cache_aligned dsw_port { struct dsw_queue { uint8_t schedule_type; - uint64_t serving_ports; + RTE_BITSET_DECLARE(serving_ports, DSW_MAX_PORTS); uint16_t num_serving_ports; alignas(RTE_CACHE_LINE_SIZE) uint8_t flow_to_port_map[DSW_MAX_FLOWS]; diff --git a/drivers/event/dsw/dsw_event.c b/drivers/event/dsw/dsw_event.c index 33f741990f..f18c7e8fbc 100644 --- a/drivers/event/dsw/dsw_event.c +++ b/drivers/event/dsw/dsw_event.c @@ -457,9 +457,8 @@ static bool dsw_is_serving_port(struct dsw_evdev *dsw, uint8_t port_id, uint8_t queue_id) { struct dsw_queue *queue = &dsw->queues[queue_id]; - uint64_t port_mask = UINT64_C(1) << port_id; - return queue->serving_ports & port_mask; + return rte_bitset_test(queue->serving_ports, port_id); } static bool @@ -583,7 +582,9 @@ dsw_schedule(struct dsw_evdev *dsw, uint8_t queue_id, uint16_t flow_hash) /* A single-link queue, or atomic/ordered/parallel but * with just a single serving port. */ - port_id = rte_bsf64(queue->serving_ports); + port_id = (uint8_t)rte_bitset_find_first_set( + queue->serving_ports, DSW_MAX_PORTS + ); DSW_LOG_DP(DEBUG, "Event with queue_id %d flow_hash %d is scheduled " "to port %d.\n", queue_id, flow_hash, port_id);