GCC Code Coverage Report


Directory: lib/fprime-samd/fprime-samd/
File: Svc/StaticMallocator/StaticMallocator.hpp
Date: 2026-10-20 16:44:20
Exec Total Coverage
Lines: 16 16 100.0%
Functions: 4 4 100.0%
Branches: 9 18 50.0%

Line Branch Exec Source
1 /**
2 * \file
3 * \author A. Tumbar
4 * \brief A MemAllocator implementation class that uses static memory buckets.
5 *
6 * \copyright
7 * Copyright 2026, by the California Institute of Technology.
8 * ALL RIGHTS RESERVED. United States Government Sponsorship
9 * acknowledged.
10 *
11 */
12
13 #ifndef SAMD21_MALLOCALLOCATOR_HPP
14 #define SAMD21_MALLOCALLOCATOR_HPP
15
16 #include <Fw/Types/MemAllocator.hpp>
17 #include <cstddef>
18 #include "Fw/Types/Assert.hpp"
19 #include "config/FwAssertArgTypeAliasAc.h"
20 #include "config/FwEnumStoreTypeAliasAc.h"
21
22 namespace Samd21 {
23
24 //! \brief static memory based memory allocator
25 //!
26 //! This class implements a memory allocator that uses static memory buckets.
27 template <size_t BUCKET_SIZE, FwEnumStoreType IDENT>
28 class StaticMallocator : public Fw::MemAllocator {
29 public:
30 static_assert(BUCKET_SIZE % 8 == 0, "Bucket size must a multiple of 8");
31
32 3 StaticMallocator() = default;
33 6 virtual ~StaticMallocator() = default;
34
35 //! Allocate memory
36 //!
37 //! Allocate memory using malloc(). The identifier is unused and memory is never recoverable.
38 //! malloc() guarantees alignment for any type and so does this allocator. It will not respect smaller alignments.
39 //!
40 //! \param identifier the allocating entity identifier (not used)
41 //! \param size the requested size (not changed)
42 //! \param recoverable - flag to indicate the memory could be recoverable (always set to false)
43 //! \param alignment - alignment requirement for the allocation. Default: maximum alignment defined by C++.
44 //! \return the pointer to memory. Zero if unable to allocate.
45 3 void* allocate(const FwEnumStoreType identifier,
46 FwSizeType& size,
47 bool& recoverable,
48 FwSizeType alignment = alignof(std::max_align_t)) override {
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 FW_ASSERT(identifier == IDENT, static_cast<FwAssertArgType>(identifier), static_cast<FwAssertArgType>(IDENT));
50
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 FW_ASSERT(size <= BUCKET_SIZE, static_cast<FwAssertArgType>(size), static_cast<FwAssertArgType>(BUCKET_SIZE));
51 // `data` is declared alignas(std::max_align_t), so the bound here is exactly the
52 // default argument above. It used to read `alignment <= 8`, which made the DEFAULT
53 // call self-inconsistent on any host where alignof(std::max_align_t) is 16 -- true
54 // of Linux x86-64, where `long double` is 16-byte aligned. Darwin arm64 has it at
55 // 8, so the bug was invisible there and only surfaced when a unit test ran on
56 // Linux. Keep this comparing against the same expression `data` is aligned to.
57
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 FW_ASSERT(alignment <= alignof(std::max_align_t), static_cast<FwAssertArgType>(alignment));
58
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
3 FW_ASSERT(!used);
59
60 3 recoverable = true;
61 3 this->used = true;
62 3 return reinterpret_cast<void*>(this->data);
63 }
64 //! Deallocate memory
65 //!
66 //! Deallocate memory previously allocated by allocate() using free(). The identifier is unused but should still
67 //! match the original call.
68 //!
69 //! \param identifier the memory segment identifier (not used)
70 //! \param ptr the pointer to memory returned by allocate()
71 3 void deallocate(const FwEnumStoreType identifier, void* ptr) override {
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 FW_ASSERT(identifier == IDENT, static_cast<FwAssertArgType>(identifier), static_cast<FwAssertArgType>(IDENT));
73
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
3 FW_ASSERT(used);
74
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 FW_ASSERT(ptr == reinterpret_cast<void*>(this->data));
75 3 this->used = false;
76 3 }
77
78 private:
79 // U64 for 64-bit alignment, and alignas() on top of it so the storage really does
80 // satisfy the alignment this class advertises as its default argument. On the SAMD21
81 // (arm-none-eabi, 32-bit) alignof(std::max_align_t) is 8 and the U64 array is already
82 // 8-aligned, so this costs nothing on target; it only widens the alignment on hosts
83 // where max_align_t is 16, i.e. in unit tests.
84 alignas(std::max_align_t) U64 data[BUCKET_SIZE / 8];
85 bool used = false;
86 };
87
88 } // namespace Samd21
89
90 #endif /* SAMD21_MALLOCALLOCATOR_HPP */
91