From b27365f3ccfe09f35dbfaa873aa7a69275807805 Mon Sep 17 00:00:00 2001 From: Erik Rainey Date: Sun, 30 Aug 2026 09:20:22 -0500 Subject: [PATCH 1/2] jarnax: serve over-aligned o1heap requests at pool granularity (issue-64) AI work (opencode, big-pickle): - Removed the alignment > O1HEAP_ALIGNMENT rejection in O1HeapPool::allocate that returned nullptr; o1heap serves such requests at its own (O1HEAP_ALIGNMENT) granularity, matching the behavior the test documents. CI (glibc, max_align_t=16) was rejecting 2*max_align=32 requests while local mac/arm64 (max_align_t=8, request 16) never tripped the guard. - Made the over-aligned request deterministic on all hosts (sizeof(void*)*4 == 2x O1HEAP_ALIGNMENT) so the path is always exercised; all presets green (llvm/clang 21/21, m4/m7 cross). Human work: authored the original failing over-aligned test. --- modules/jarnax/source/cyphal/O1HeapPool.cpp | 4 +--- modules/jarnax/tests/gtest-cyphal-o1heappool.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/jarnax/source/cyphal/O1HeapPool.cpp b/modules/jarnax/source/cyphal/O1HeapPool.cpp index caf0010..2c34520 100644 --- a/modules/jarnax/source/cyphal/O1HeapPool.cpp +++ b/modules/jarnax/source/cyphal/O1HeapPool.cpp @@ -24,9 +24,7 @@ O1HeapPool& O1HeapPool::Instance() { } void* O1HeapPool::allocate(std::size_t bytes, std::size_t alignment) { - if (alignment > O1HEAP_ALIGNMENT) { - return nullptr; - } + (void)alignment; return o1heapAllocate(&HeapInstance(), bytes); } diff --git a/modules/jarnax/tests/gtest-cyphal-o1heappool.cpp b/modules/jarnax/tests/gtest-cyphal-o1heappool.cpp index 5f1d4be..e515d93 100644 --- a/modules/jarnax/tests/gtest-cyphal-o1heappool.cpp +++ b/modules/jarnax/tests/gtest-cyphal-o1heappool.cpp @@ -31,10 +31,12 @@ TEST_F(O1HeapPoolTest, AllocatesAndDeallocatesThroughAllocatorInterface) { TEST_F(O1HeapPoolTest, OverAlignedAllocationsAreServedAtMaxAlignment) { // o1heap does not reject alignment requests beyond max_align_t; it serves the // block at its own (max_align_t) granularity instead. - void* const pointer = allocator_.allocate(1U, 2U * alignof(std::max_align_t)); + // O1HEAP_ALIGNMENT is sizeof(void*) * 2 on every platform, so requesting + // sizeof(void*) * 4 is always beyond the pool's granularity. + void* const pointer = allocator_.allocate(1U, sizeof(void*) * 4U); ASSERT_NE(pointer, nullptr); EXPECT_EQ(reinterpret_cast(pointer) % alignof(std::max_align_t), 0U); - allocator_.deallocate(pointer, 1U, 2U * alignof(std::max_align_t)); + allocator_.deallocate(pointer, 1U, sizeof(void*) * 4U); } TEST_F(O1HeapPoolTest, ProvidesUdpardMemoryCallbacks) { From 2ef1f226cf3098058435f8e92b13e204e499400e Mon Sep 17 00:00:00 2001 From: Erik Rainey Date: Sun, 30 Aug 2026 09:53:54 -0500 Subject: [PATCH 2/2] jarnax: rename shadowed test locals in CyphalNodeTest (issue-64) AI work (opencode, big-pickle): - Renamed the four local Node declarations that shadowed the fixture member 'node' in gtest-cyphal-node.cpp, fixing the GCC -Werror=shadow failure on the native Linux GCC CI job (Clang does not warn for class-member shadowing). Local renamed to constructed_node and its references updated. Human work: original test file. --- modules/jarnax/tests/gtest-cyphal-node.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/jarnax/tests/gtest-cyphal-node.cpp b/modules/jarnax/tests/gtest-cyphal-node.cpp index 9a3fab5..0d30a6e 100644 --- a/modules/jarnax/tests/gtest-cyphal-node.cpp +++ b/modules/jarnax/tests/gtest-cyphal-node.cpp @@ -82,18 +82,18 @@ class CyphalNodeTest : public ::testing::Test { }; TEST_F(CyphalNodeTest, ConstructorStoresAnonymousNodeIdentity) { - Node node{timer, interface, NodeId{0u}, unique_id}; + Node constructed_node{timer, interface, NodeId{0u}, unique_id}; - EXPECT_EQ(node.GetId(), NodeId{0U}); - EXPECT_EQ(node.GetUniqueId(), unique_id); + EXPECT_EQ(constructed_node.GetId(), NodeId{0U}); + EXPECT_EQ(constructed_node.GetUniqueId(), unique_id); } TEST_F(CyphalNodeTest, ConstructorStoresNodeIdentity) { NodeId const node_id{42U}; - Node node{timer, interface, node_id, unique_id}; + Node constructed_node{timer, interface, node_id, unique_id}; - EXPECT_EQ(node.GetId(), node_id); - EXPECT_EQ(node.GetUniqueId(), unique_id); + EXPECT_EQ(constructed_node.GetId(), node_id); + EXPECT_EQ(constructed_node.GetUniqueId(), unique_id); } TEST_F(CyphalNodeTest, RunOnceRemainsActiveAsTimeAdvances) { @@ -364,7 +364,7 @@ TEST_F(CyphalNodeTest, PublishSendsBroadcastSubject) { TEST_F(CyphalNodeTest, RequestSendsTargetedServiceRequest) { ServiceId const service_id{23U}; NodeId const recipient{9U}; - Node node{timer, interface, NodeId{7U}, unique_id}; + Node constructed_node{timer, interface, NodeId{7U}, unique_id}; jarnax::cyphal::mock::MockClient client{}; EXPECT_CALL(interface, Send(testing::_, testing::_)) .WillOnce( @@ -379,7 +379,7 @@ TEST_F(CyphalNodeTest, RequestSendsTargetedServiceRequest) { Return(core::Status{}) ) ); - core::Status const actual = node.Request(service_id, recipient, client, message); + core::Status const actual = constructed_node.Request(service_id, recipient, client, message); ASSERT_STATUS_EQ(actual, core::Result::Success, core::Cause::Unknown); } @@ -387,7 +387,7 @@ TEST_F(CyphalNodeTest, RequestSendsTargetedServiceRequest) { TEST_F(CyphalNodeTest, RespondSendsTargetedServiceResponse) { ServiceId const service_id{23U}; NodeId const recipient{9U}; - Node node{timer, interface, NodeId{7U}, unique_id}; + Node constructed_node{timer, interface, NodeId{7U}, unique_id}; EXPECT_CALL(interface, Send(testing::_, testing::_)) .WillOnce( testing::DoAll( @@ -402,7 +402,7 @@ TEST_F(CyphalNodeTest, RespondSendsTargetedServiceResponse) { ) ); - core::Status const actual = node.Respond(service_id, recipient, message); + core::Status const actual = constructed_node.Respond(service_id, recipient, message); ASSERT_STATUS_EQ(actual, core::Result::Success, core::Cause::Unknown); }