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/5] 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/5] 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/5] 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) { From 3dbe33380c112ff6da2c2e2874cbe32ebaee3576 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Wed, 17 Jun 2026 13:13:49 +0200 Subject: [PATCH 4/5] replacing NULL with nullptr and atoi with from_chars Signed-off-by: Alejandro Hernandez Cordero --- rttest/src/rttest.cpp | 24 +++++++++++++--------- tlsf_cpp/include/tlsf_cpp/tlsf.hpp | 32 ++++++++++++++++-------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/rttest/src/rttest.cpp b/rttest/src/rttest.cpp index 3a9466c..bc503df 100644 --- a/rttest/src/rttest.cpp +++ b/rttest/src/rttest.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -250,7 +251,8 @@ int Rttest::read_args(int argc, char ** argv) switch (c) { case 'i': { - int arg = atoi(optarg); + int arg = 0; + std::from_chars(optarg, optarg + strlen(optarg), arg); if (arg < 0) { iterations = 0; } else { @@ -280,8 +282,12 @@ int Rttest::read_args(int argc, char ** argv) } break; case 't': - sched_priority = atoi(optarg); - break; + { + int prio = 0; + std::from_chars(optarg, optarg + strlen(optarg), prio); + sched_priority = prio; + break; + } case 's': { std::string input(optarg); @@ -328,7 +334,7 @@ int Rttest::read_args(int argc, char ** argv) int rttest_get_params(struct rttest_params * params_in) { - if (params_in == NULL) { + if (params_in == nullptr) { return -1; } @@ -557,7 +563,7 @@ int Rttest::spin_once( struct timespec wakeup_time, current_time; multiply_timespec(update_period, i, &wakeup_time); add_timespecs(start_time, &wakeup_time, &wakeup_time); - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wakeup_time, NULL); + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wakeup_time, nullptr); clock_gettime(CLOCK_MONOTONIC, ¤t_time); this->record_jitter(&wakeup_time, ¤t_time, i); @@ -751,7 +757,7 @@ int Rttest::accumulate_statistics(size_t iteration) int Rttest::calculate_statistics(struct rttest_results * output) { - if (output == NULL) { + if (output == nullptr) { fprintf(stderr, "Need to allocate rttest_results struct\n"); return -1; } @@ -789,7 +795,7 @@ int rttest_calculate_statistics(struct rttest_results * results) int rttest_get_statistics(struct rttest_results * output) { - if (output == NULL) { + if (output == nullptr) { return -1; } @@ -826,7 +832,7 @@ int rttest_get_sample_at(const size_t iteration, int64_t * sample) if (!thread_rttest_instance) { return -1; } - if (sample == NULL) { + if (sample == nullptr) { return -1; } return thread_rttest_instance->get_sample_at(iteration, *sample); @@ -908,7 +914,7 @@ int Rttest::write_results_file(char * filename) fprintf(stderr, "No sample buffer was saved, not writing results\n"); return -1; } - if (filename == NULL) { + if (filename == nullptr) { fprintf(stderr, "No results filename given, not writing results\n"); return -1; } diff --git a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp index e3140e9..e963cd8 100644 --- a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp +++ b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp @@ -90,21 +90,23 @@ struct tlsf_heap_allocator rcl_allocator_t get_rcl_allocator() { - rcl_allocator_t allocator = rcl_get_default_allocator(); - allocator.allocate = [](size_t size, void * state) -> void * { - return malloc_ex(size, state); - }; - allocator.deallocate = [](void * ptr, void * state) { - free_ex(ptr, state); - }; - allocator.reallocate = [](void * ptr, size_t size, void * state) -> void * { - return realloc_ex(ptr, size, state); - }; - allocator.zero_allocate = [](size_t n, size_t size, void * state) -> void * { - return calloc_ex(n, size, state); - }; - allocator.state = memory_pool; - return allocator; + // Designated initializers must follow rcl_allocator_t's declaration order: + // allocate, deallocate, reallocate, zero_allocate, state. + return rcl_allocator_t{ + .allocate = [](size_t size, void * state) -> void * { + return malloc_ex(size, state); + }, + .deallocate = [](void * ptr, void * state) { + free_ex(ptr, state); + }, + .reallocate = [](void * ptr, size_t size, void * state) -> void * { + return realloc_ex(ptr, size, state); + }, + .zero_allocate = [](size_t n, size_t size, void * state) -> void * { + return calloc_ex(n, size, state); + }, + .state = memory_pool, + }; } template From 77a9eec51b4da4971dab4b1db25d57e3394645d3 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Wed, 17 Jun 2026 13:26:07 +0200 Subject: [PATCH 5/5] using instead of typedef Signed-off-by: Alejandro Hernandez Cordero --- tlsf_cpp/include/tlsf_cpp/tlsf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp index e963cd8..1ef0071 100644 --- a/tlsf_cpp/include/tlsf_cpp/tlsf.hpp +++ b/tlsf_cpp/include/tlsf_cpp/tlsf.hpp @@ -112,7 +112,7 @@ struct tlsf_heap_allocator template struct rebind { - typedef tlsf_heap_allocator other; + using other = tlsf_heap_allocator; }; char * memory_pool;