From 068b8009350c505f8ddd5244aac719f02e89d890 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Tue, 16 Jun 2026 17:39:18 +0200 Subject: [PATCH 1/3] fixed page-fault accumulator and removed non-deducible converting constructor Signed-off-by: Alejandro Hernandez Cordero --- rttest/src/rttest.cpp | 11 ++++++----- tlsf_cpp/include/tlsf_cpp/tlsf.hpp | 15 ++++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/rttest/src/rttest.cpp b/rttest/src/rttest.cpp index ade1d18..972d7c8 100644 --- a/rttest/src/rttest.cpp +++ b/rttest/src/rttest.cpp @@ -201,19 +201,20 @@ Rttest * get_rttest_thread_instance(pthread_t thread_id) uint64_t rttest_parse_size_units(char * optarg) { - uint64_t ret; + uint64_t ret = 0; std::string input(optarg); std::vector tokens = {"gb", "mb", "kb", "b"}; for (size_t i = 0; i < 4; ++i) { size_t idx = input.find(tokens[i]); if (idx != std::string::npos) { - ret = std::stoll(input.substr(0, idx)) * std::pow(2, (3 - i) * 10); + // gb/mb/kb/b -> shift by 30/20/10/0 bits (exact, integer) + ret = std::stoull(input.substr(0, idx)) << ((3 - i) * 10); break; } if (i == 3) { // Default units are megabytes - ret = std::stoll(input) * std::pow(2, 20); + ret = std::stoull(input) << 20; } } return ret; @@ -767,11 +768,11 @@ int Rttest::calculate_statistics(struct rttest_results * output) output->minor_pagefaults = std::accumulate( this->sample_buffer.minor_pagefaults.begin(), - this->sample_buffer.minor_pagefaults.end(), 0); + this->sample_buffer.minor_pagefaults.end(), size_t{}); output->major_pagefaults = std::accumulate( this->sample_buffer.major_pagefaults.begin(), - this->sample_buffer.major_pagefaults.end(), 0); + this->sample_buffer.major_pagefaults.end(), size_t{}); return 0; } diff --git a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp index 2ea720c..e00aaa9 100644 --- a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp +++ b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp @@ -43,15 +43,12 @@ struct tlsf_heap_allocator initialize(DefaultPoolSize); } - // Needed for std::allocator_traits - template - tlsf_heap_allocator(const tlsf_heap_allocator & alloc) - : memory_pool(alloc.memory_pool), pool_size(alloc.pool_size) - { - } - - template - tlsf_heap_allocator(const tlsf_heap_allocator & alloc) + // Needed for std::allocator_traits. + // Converting constructor across both element type (U) and pool size + // (OtherPoolSize). Both template parameters are deduced from the argument, + // so this single overload covers every rebind/conversion case. + template + tlsf_heap_allocator(const tlsf_heap_allocator & alloc) : memory_pool(alloc.memory_pool), pool_size(alloc.pool_size) { } From 8211ffd82afe0eb50f9e32674d8b42a5798f1c27 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Tue, 16 Jun 2026 17:46:45 +0200 Subject: [PATCH 2/3] Modernize rttest and tlsf_cpp for C++20 Signed-off-by: Alejandro Hernandez Cordero --- rttest/src/rttest.cpp | 47 +++++++++++++++--------------- tlsf_cpp/include/tlsf_cpp/tlsf.hpp | 32 +++----------------- 2 files changed, 28 insertions(+), 51 deletions(-) diff --git a/rttest/src/rttest.cpp b/rttest/src/rttest.cpp index 972d7c8..3a9466c 100644 --- a/rttest/src/rttest.cpp +++ b/rttest/src/rttest.cpp @@ -25,10 +25,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -193,10 +193,11 @@ int Rttest::record_jitter( Rttest * get_rttest_thread_instance(pthread_t thread_id) { - if (rttest_instance_map.count(thread_id) == 0) { - return NULL; + auto it = rttest_instance_map.find(thread_id); + if (it == rttest_instance_map.end()) { + return nullptr; } - return &rttest_instance_map[thread_id]; + return &it->second; } uint64_t rttest_parse_size_units(char * optarg) @@ -353,7 +354,7 @@ int rttest_init_new_thread() fprintf(stderr, "rttest instance for %lu already exists!\n", thread_id); return -1; } - if (initial_thread_id == 0 || rttest_instance_map.count(initial_thread_id) == 0) { + if (initial_thread_id == 0 || !rttest_instance_map.contains(initial_thread_id)) { return -1; } rttest_instance_map[thread_id].set_params( @@ -833,24 +834,24 @@ int rttest_get_sample_at(const size_t iteration, int64_t * sample) std::string Rttest::results_to_string(char * name) { - std::stringstream sstring; - - sstring << std::fixed << "rttest statistics"; - if (name != NULL) { - sstring << " for " << name << ":" << std::endl; - } else { - sstring << ":" << std::endl; - } - sstring << " - Minor pagefaults: " << results.minor_pagefaults << std::endl; - sstring << " - Major pagefaults: " << results.major_pagefaults << std::endl; - sstring << " Latency (time after deadline was missed):" << std::endl; - sstring << " - Min: " << results.min_latency << " ns" << std::endl; - sstring << " - Max: " << results.max_latency << " ns" << std::endl; - sstring << " - Mean: " << results.mean_latency << " ns" << std::endl; - sstring << " - Standard deviation: " << results.latency_stddev << std::endl; - sstring << std::endl; - - return sstring.str(); + // {:f} preserves the std::fixed (6 decimal places) formatting of the + // floating-point latency fields used by the previous stringstream version. + return std::format( + "rttest statistics{}:\n" + " - Minor pagefaults: {}\n" + " - Major pagefaults: {}\n" + " Latency (time after deadline was missed):\n" + " - Min: {} ns\n" + " - Max: {} ns\n" + " - Mean: {:f} ns\n" + " - Standard deviation: {:f}\n\n", + name != nullptr ? std::format(" for {}", name) : std::string{}, + results.minor_pagefaults, + results.major_pagefaults, + results.min_latency, + results.max_latency, + results.mean_latency, + results.latency_stddev); } int rttest_finish() diff --git a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp index e00aaa9..e3140e9 100644 --- a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp +++ b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp @@ -117,25 +117,10 @@ struct tlsf_heap_allocator size_t pool_size; }; -// Needed for std::allocator_traits -template -constexpr bool operator==( - const tlsf_heap_allocator & a, - const tlsf_heap_allocator & b) noexcept -{ - return a.memory_pool == b.memory_pool; -} - -// Needed for std::allocator_traits -template -constexpr bool operator!=( - const tlsf_heap_allocator & a, - const tlsf_heap_allocator & b) noexcept -{ - return a.memory_pool != b.memory_pool; -} - -template +// Needed for std::allocator_traits. +// Single symmetric overload covering any element types and pool sizes; +// C++20 synthesizes operator!= from this operator==. +template constexpr bool operator==( const tlsf_heap_allocator & a, const tlsf_heap_allocator & b) noexcept @@ -143,14 +128,5 @@ constexpr bool operator==( return a.memory_pool == b.memory_pool; } -// Needed for std::allocator_traits -template -constexpr bool operator!=( - const tlsf_heap_allocator & a, - const tlsf_heap_allocator & b) noexcept -{ - return a.memory_pool != b.memory_pool; -} - #endif // TLSF_CPP__TLSF_HPP_ From d2d6d7cca94e699c728bba423e7eba12488bfec5 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Tue, 16 Jun 2026 17:58:08 +0200 Subject: [PATCH 3/3] Modernize rttest and tlsf_cpp for C++20 part 2 Signed-off-by: Alejandro Hernandez Cordero --- rttest/include/rttest/utils.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/rttest/include/rttest/utils.hpp b/rttest/include/rttest/utils.hpp index 2ca3be9..0683325 100644 --- a/rttest/include/rttest/utils.hpp +++ b/rttest/include/rttest/utils.hpp @@ -18,9 +18,10 @@ #include #include -#define NSEC_PER_SEC 1000000000 +// Typed compile-time constant replacing the former object-like macro. +static constexpr int64_t NSEC_PER_SEC = 1000000000; -static inline bool timespec_gt( +static constexpr bool timespec_gt( const struct timespec * t1, const struct timespec * t2) { @@ -33,7 +34,7 @@ static inline bool timespec_gt( return t1->tv_nsec > t2->tv_nsec; } -static inline void normalize_timespec(struct timespec * t) +static constexpr void normalize_timespec(struct timespec * t) { // TODO(jacquelinekay) improve while (t->tv_nsec >= NSEC_PER_SEC) { @@ -42,7 +43,7 @@ static inline void normalize_timespec(struct timespec * t) } } -static inline void add_timespecs( +static constexpr void add_timespecs( const struct timespec * t1, const struct timespec * t2, struct timespec * dst) @@ -52,7 +53,7 @@ static inline void add_timespecs( normalize_timespec(dst); } -static inline bool subtract_timespecs( +static constexpr bool subtract_timespecs( const struct timespec * t1, const struct timespec * t2, struct timespec * dst) @@ -68,12 +69,12 @@ static inline bool subtract_timespecs( return true; } -static inline uint64_t timespec_to_uint64(const struct timespec * t) +static constexpr uint64_t timespec_to_uint64(const struct timespec * t) { return static_cast(t->tv_sec) * NSEC_PER_SEC + static_cast(t->tv_nsec); } -static inline void uint64_to_timespec(const uint64_t input, struct timespec * t) +static constexpr void uint64_to_timespec(const uint64_t input, struct timespec * t) { uint64_t nsecs = input % NSEC_PER_SEC; uint64_t secs = (input - nsecs) / NSEC_PER_SEC; @@ -81,7 +82,7 @@ static inline void uint64_to_timespec(const uint64_t input, struct timespec * t) t->tv_nsec = static_cast(nsecs); // NOLINT for C type long } -static inline void multiply_timespec( +static constexpr void multiply_timespec( const struct timespec * t, const uint32_t i, struct timespec * result) {