In writing DPDK code, one of the often-seen pattern is counting usage of resources - programming a HW block on first/last flow rule, or even just tracking references to software structures. In a lot of cases, a simple usage count is not a good fit because of atomicity/thread safety requirements, but for trivial/already synchronized cases it can be useful.
Add a "usage count" library to EAL to enable such use cases. Signed-off-by: Anatoly Burakov <[email protected]> --- doc/api/doxy-api-index.md | 1 + lib/eal/include/meson.build | 1 + lib/eal/include/rte_usage_count.h | 96 +++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 lib/eal/include/rte_usage_count.h diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 62390f7be3..ab4ff04797 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -177,6 +177,7 @@ The public API headers are grouped by topics: [soring](@ref rte_soring.h), [stack](@ref rte_stack.h), [tailq](@ref rte_tailq.h), + [usage count](@ref rte_usage_count.h), [bitset](@ref rte_bitset.h), [bitmap](@ref rte_bitmap.h) diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build index 67c6a8021a..5ff432051e 100644 --- a/lib/eal/include/meson.build +++ b/lib/eal/include/meson.build @@ -53,6 +53,7 @@ headers += files( 'rte_trace.h', 'rte_trace_point.h', 'rte_trace_point_register.h', + 'rte_usage_count.h', 'rte_uuid.h', 'rte_version.h', ) diff --git a/lib/eal/include/rte_usage_count.h b/lib/eal/include/rte_usage_count.h new file mode 100644 index 0000000000..3056436ba8 --- /dev/null +++ b/lib/eal/include/rte_usage_count.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2026 Intel Corporation + */ + +#ifndef _RTE_USAGE_COUNT_H_ +#define _RTE_USAGE_COUNT_H_ + +/** + * @file + * RTE Usage Counter + * + * Trivial usage (reference) counters intended to express increment/decrement + * sequences with first/last user edge detection, for example "do X on first Y, + * undo X on last Y". + * + * The counters are neither thread-safe nor atomic; callers must provide their + * own serialization. + */ + +#include <stdbool.h> +#include <stdint.h> + +#include <rte_compat.h> +#include <rte_debug.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Usage counter type. + */ +typedef uint32_t rte_usage_count_t; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Claim a usage. + * + * @param counter + * Usage counter to claim. + * @return + * true if this is the first usage, false otherwise. + */ +__rte_experimental +static inline bool +rte_usage_count_claim(rte_usage_count_t *counter) +{ + RTE_ASSERT(*counter != UINT32_MAX); + return (*counter)++ == 0; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Release a usage. + * + * @param counter + * Usage counter to release. Must have at least one usage. + * @return + * true if this was the last usage, false otherwise. + */ +__rte_experimental +static inline bool +rte_usage_count_release(rte_usage_count_t *counter) +{ + RTE_ASSERT(*counter != 0); + return --(*counter) == 0; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Test whether the currently claimed usage is the last one, + * i.e. whether a subsequent release would return true. + * + * @param counter + * Usage counter to test. + * @return + * true if exactly one usage is currently claimed, false otherwise. + */ +__rte_experimental +static inline bool +rte_usage_count_is_last(const rte_usage_count_t *counter) +{ + return *counter == 1; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_USAGE_COUNT_H_ */ -- 2.52.0

