1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_allocator-design: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker================ 4*61c4878aSAndroid Build Coastguard WorkerDesign & roadmap 5*61c4878aSAndroid Build Coastguard Worker================ 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_allocator 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker----------------------- 10*61c4878aSAndroid Build Coastguard WorkerDesign of pw::Allocator 11*61c4878aSAndroid Build Coastguard Worker----------------------- 12*61c4878aSAndroid Build Coastguard WorkerTraditionally, most embedded firmware have laid out their systems’ memory usage 13*61c4878aSAndroid Build Coastguard Workerstatically, with every component’s buffers and resources set at compile time. As 14*61c4878aSAndroid Build Coastguard Workersystems grow larger and more complex, dynamic allocation provides increasing 15*61c4878aSAndroid Build Coastguard Workeropportunities to simplify code and improve memory usage by enabling sharing and 16*61c4878aSAndroid Build Coastguard Workereliminating large reservations. 17*61c4878aSAndroid Build Coastguard Worker 18*61c4878aSAndroid Build Coastguard WorkerAs a result, ``pw_allocator`` seeks to make dynamic allocation possible without 19*61c4878aSAndroid Build Coastguard Workersacrificing too much of the control over memory usage that embedded developers 20*61c4878aSAndroid Build Coastguard Workerare accustomed to and need. The fundamental design goals of ``pw_allocator`` are 21*61c4878aSAndroid Build Coastguard Workerfor allocators to be: 22*61c4878aSAndroid Build Coastguard Worker 23*61c4878aSAndroid Build Coastguard Worker- Familiar: The interface and its usage should resemble that of C++17's 24*61c4878aSAndroid Build Coastguard Worker `std::pmr::polymorphic_allocator`_ type. 25*61c4878aSAndroid Build Coastguard Worker- Flexible: A diverse set of allocation strategies should be implementable 26*61c4878aSAndroid Build Coastguard Worker using allocators. 27*61c4878aSAndroid Build Coastguard Worker- Composable: Allocators should be able to combine and use other allocators. 28*61c4878aSAndroid Build Coastguard Worker- Extensible: Downstream projects should be able to provide their own allocator 29*61c4878aSAndroid Build Coastguard Worker implementations, and easily integrate them with Pigweed's. 30*61c4878aSAndroid Build Coastguard Worker- Cost-effective: Projects should be able to include only the allocator 31*61c4878aSAndroid Build Coastguard Worker behaviors they desire. 32*61c4878aSAndroid Build Coastguard Worker- Observable: Allocators should provide tools and data to reveal how memory is 33*61c4878aSAndroid Build Coastguard Worker being used. 34*61c4878aSAndroid Build Coastguard Worker- Correcting: Allocators should include features to help uncover 35*61c4878aSAndroid Build Coastguard Worker `memory defects`_ including heap corruption, leaks, use-after-frees, etc. 36*61c4878aSAndroid Build Coastguard Worker 37*61c4878aSAndroid Build Coastguard Worker.. _module-pw_allocator-design-differences-with-polymorphic-allocators: 38*61c4878aSAndroid Build Coastguard Worker 39*61c4878aSAndroid Build Coastguard WorkerDifferences with C++ polymorphic allocators 40*61c4878aSAndroid Build Coastguard Worker=========================================== 41*61c4878aSAndroid Build Coastguard WorkerC++17 introduced the ``<memory_resource>`` header with support for polymorphic 42*61c4878aSAndroid Build Coastguard Workermemory resources (PMR), i.e. allocators. This library defines many allocator 43*61c4878aSAndroid Build Coastguard Workerinterfaces similar to those in ``pw_allocator``. 44*61c4878aSAndroid Build Coastguard Worker 45*61c4878aSAndroid Build Coastguard WorkerPigweed has decided to keep ``pw_allocator`` distinct from PMR primarily because 46*61c4878aSAndroid Build Coastguard Workerthe latter's interface requires the use of C++ language features prohibited by 47*61c4878aSAndroid Build Coastguard WorkerPigweed. In PMR, allocators are expected to throw an exception in the case of 48*61c4878aSAndroid Build Coastguard Workerfailure, and equality comparisons require runtime type identification (RTTI). 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard WorkerEven so, ``pw_allocator`` has taken inspiration from the design of PMR, 51*61c4878aSAndroid Build Coastguard Workerincorporating many of its ideas. :ref:`module-pw_allocator-api-allocator` in 52*61c4878aSAndroid Build Coastguard Workerparticular is similar to `std::pmr::memory_resource`_. 53*61c4878aSAndroid Build Coastguard Worker 54*61c4878aSAndroid Build Coastguard WorkerThis similarity is most evident in the PMR adapter class, 55*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_allocator-api-pmr_allocator`. This adapter allows any 56*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_allocator-api-allocator` to be used as a 57*61c4878aSAndroid Build Coastguard Worker`std::pmr::polymorphic_allocator`_ with any standard library that 58*61c4878aSAndroid Build Coastguard Worker`can use an allocator`_. Refer to the guides on how to 59*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_allocator-use-standard-library-containers`. 60*61c4878aSAndroid Build Coastguard Worker 61*61c4878aSAndroid Build Coastguard Worker.. _module-pw_allocator-design-forwarding: 62*61c4878aSAndroid Build Coastguard Worker 63*61c4878aSAndroid Build Coastguard WorkerForwarding allocator concept 64*61c4878aSAndroid Build Coastguard Worker============================ 65*61c4878aSAndroid Build Coastguard WorkerIn addition to concrete allocator implementations, the design of 66*61c4878aSAndroid Build Coastguard Worker``pw_allocator`` also encourages the use of "forwarding" allocators. These are 67*61c4878aSAndroid Build Coastguard Workerimplementations of the :ref:`module-pw_allocator-api-allocator` interface that 68*61c4878aSAndroid Build Coastguard Workerdon't allocate memory directly and instead rely on other allocators while 69*61c4878aSAndroid Build Coastguard Workerproviding some additional behavior. 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard WorkerFor example, the :ref:`module-pw_allocator-api-allocator` records various 72*61c4878aSAndroid Build Coastguard Workermetrics such as the peak number of bytes allocated and the number of failed 73*61c4878aSAndroid Build Coastguard Workerallocation requests. It wraps another allocator which is used to actually 74*61c4878aSAndroid Build Coastguard Workerperform dynamic allocation. It implements the allocator API, and so it can be 75*61c4878aSAndroid Build Coastguard Workerpassed into any routines that use dependency injection by taking a generic 76*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_allocator-api-allocator` parameter. 77*61c4878aSAndroid Build Coastguard Worker 78*61c4878aSAndroid Build Coastguard WorkerThese "forwarding" allocators are not completely free. At a miniumum, they 79*61c4878aSAndroid Build Coastguard Workerrepresent an extra virtual indirection, and an extra function call, albeit one 80*61c4878aSAndroid Build Coastguard Workerthat can often be inlined. Additional behavior-specific code or state adds to 81*61c4878aSAndroid Build Coastguard Workertheir cost in terms of code size and performance. Even so, these "forwarding" 82*61c4878aSAndroid Build Coastguard Workerallocators can provide savings relative to a "`golden hammer`_"-style allocator 83*61c4878aSAndroid Build Coastguard Workerthat combined all of their features and more. By decomposing allocators into 84*61c4878aSAndroid Build Coastguard Workerorthogonal behaviors, implementers can choose to pay for only those that they 85*61c4878aSAndroid Build Coastguard Workerwant. 86*61c4878aSAndroid Build Coastguard Worker 87*61c4878aSAndroid Build Coastguard Worker----------------------------- 88*61c4878aSAndroid Build Coastguard WorkerDesign of allocator utilities 89*61c4878aSAndroid Build Coastguard Worker----------------------------- 90*61c4878aSAndroid Build Coastguard WorkerIn addtion to providing allocator implementations themselves, ``pw_allocator`` 91*61c4878aSAndroid Build Coastguard Workerincludes some foundational classes that can be used to implement allocators. 92*61c4878aSAndroid Build Coastguard Worker 93*61c4878aSAndroid Build Coastguard Worker.. _module-pw_allocator-design-block: 94*61c4878aSAndroid Build Coastguard Worker 95*61c4878aSAndroid Build Coastguard Workerpw::allocator::Block 96*61c4878aSAndroid Build Coastguard Worker==================== 97*61c4878aSAndroid Build Coastguard WorkerSeveral allocators make use of allocation metadata stored inline with the 98*61c4878aSAndroid Build Coastguard Workerallocations themselves. Often referred to as a "header", this metadata 99*61c4878aSAndroid Build Coastguard Workerimmediately precedes the pointer to usable space returned by the allocator. This 100*61c4878aSAndroid Build Coastguard Workerheader allows allocations to be variably sized, and converts allocation into a 101*61c4878aSAndroid Build Coastguard Worker`bin packing problem`_. An allocator that uses headers has a miniumum alignment 102*61c4878aSAndroid Build Coastguard Workermatching that of the header type itself. 103*61c4878aSAndroid Build Coastguard Worker 104*61c4878aSAndroid Build Coastguard WorkerFor ``pw_allocator``, the most common way to store this header is as a 105*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_allocator-api-block`. This class is used to construct a 106*61c4878aSAndroid Build Coastguard Workerdoubly-linked list of subsequences of the allocator's memory region. It was 107*61c4878aSAndroid Build Coastguard Workerdesigned with the following features: 108*61c4878aSAndroid Build Coastguard Worker 109*61c4878aSAndroid Build Coastguard Worker- **Templated offset types**: Rather than use pointers to the next and previous 110*61c4878aSAndroid Build Coastguard Worker blocks, ``Block`` uses offsets of a templated unsigned integral type. This 111*61c4878aSAndroid Build Coastguard Worker saves a few bits that can be used for other purposes, since the blocks are 112*61c4878aSAndroid Build Coastguard Worker always aligned to the block header. It also gives callers the ability to 113*61c4878aSAndroid Build Coastguard Worker reduce the size of the headers if the allocator's memory region is 114*61c4878aSAndroid Build Coastguard Worker sufficently small, e.g. a type of ``uint16_t`` could be used if the region 115*61c4878aSAndroid Build Coastguard Worker could hold no more than 65536 block headers. 116*61c4878aSAndroid Build Coastguard Worker- **Splitting and merging**: This class centralizes the logic for splitting 117*61c4878aSAndroid Build Coastguard Worker memory regions into smaller pieces. Usable sub-blocks can either be split from 118*61c4878aSAndroid Build Coastguard Worker the beginning or end of a block. Additionally, blocks from either end can be 119*61c4878aSAndroid Build Coastguard Worker split at specified alignment boundaries. This class also provides the logic 120*61c4878aSAndroid Build Coastguard Worker for merging blocks back together. Together, these methods provide the 121*61c4878aSAndroid Build Coastguard Worker invariant that a free block is only ever adjacent to blocks in use. 122*61c4878aSAndroid Build Coastguard Worker- **Validation and poisoning**: On every deallocation, blocks validate their 123*61c4878aSAndroid Build Coastguard Worker metadata against their neighbors. A block can fail to be validated if it or 124*61c4878aSAndroid Build Coastguard Worker its neighbors have had their headers overwritten. In this case, it's unsafe to 125*61c4878aSAndroid Build Coastguard Worker continue to use this memory and the block code will assert in order make you 126*61c4878aSAndroid Build Coastguard Worker aware of the problem. Additionally, blocks can "paint" their memory with a 127*61c4878aSAndroid Build Coastguard Worker known poison pattern that's checked whenever the memory is next allocated. If 128*61c4878aSAndroid Build Coastguard Worker the check fails, then some code has written to unallocated memory. Again, the 129*61c4878aSAndroid Build Coastguard Worker block code will assert to alert you of a "use-after-free" condition. 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard Worker.. tip:: 132*61c4878aSAndroid Build Coastguard Worker In the case of memory corruption, the validation routines themsleves may 133*61c4878aSAndroid Build Coastguard Worker crash while attempting to inspect block headers. These crashes are not 134*61c4878aSAndroid Build Coastguard Worker exploitable from a security perspective, but lack the diagnostic information 135*61c4878aSAndroid Build Coastguard Worker from the usual ``PW_CHECK`` macro. Examining a stack trace may be helpful in 136*61c4878aSAndroid Build Coastguard Worker determining why validation failed. 137*61c4878aSAndroid Build Coastguard Worker 138*61c4878aSAndroid Build Coastguard Worker.. _module-pw_allocator-design-metrics: 139*61c4878aSAndroid Build Coastguard Worker 140*61c4878aSAndroid Build Coastguard WorkerAllocator metrics 141*61c4878aSAndroid Build Coastguard Worker================= 142*61c4878aSAndroid Build Coastguard WorkerA common desire for a project using dynamic memory is to clearly understand how 143*61c4878aSAndroid Build Coastguard Workermuch memory is being allocated. However, each tracked metric adds code size, 144*61c4878aSAndroid Build Coastguard Workermemory overhead, and a per-call performance cost. As a result, ``pw_allocator`` 145*61c4878aSAndroid Build Coastguard Workeris design to allow allocator implementers to select just the metrics they're 146*61c4878aSAndroid Build Coastguard Workerinterested in. 147*61c4878aSAndroid Build Coastguard Worker 148*61c4878aSAndroid Build Coastguard WorkerIn particular, the :ref:`module-pw_allocator-api-metrics_adapter` uses 149*61c4878aSAndroid Build Coastguard Workerper-metric type traits generated by ``PW_ALLOCATOR_METRICS_DECLARE`` to 150*61c4878aSAndroid Build Coastguard Workerconditionally include the code to update the metrics that are included in its 151*61c4878aSAndroid Build Coastguard Worker``MetricsType`` template parameter type. A suitable ``MetricType`` struct can be 152*61c4878aSAndroid Build Coastguard Workercreated using the ``PW_ALLOCATOR_METRICS_ENABLE`` macro, which will only create 153*61c4878aSAndroid Build Coastguard Workerfields for the enabled metrics. 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard WorkerUsing these macros prevents unwanted metrics from increasing either the code 156*61c4878aSAndroid Build Coastguard Workersize or object size of the metrics adapter, and by extension, 157*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_allocator-api-tracking_allocator`. 158*61c4878aSAndroid Build Coastguard Worker 159*61c4878aSAndroid Build Coastguard Worker------- 160*61c4878aSAndroid Build Coastguard WorkerRoadmap 161*61c4878aSAndroid Build Coastguard Worker------- 162*61c4878aSAndroid Build Coastguard WorkerWhile the :ref:`module-pw_allocator-api-allocator` interface is almost stable, 163*61c4878aSAndroid Build Coastguard Workerthere are some outstanding features the Pigweed team would like to add to 164*61c4878aSAndroid Build Coastguard Worker``pw_allocator``: 165*61c4878aSAndroid Build Coastguard Worker 166*61c4878aSAndroid Build Coastguard Worker- **Asynchronous allocators**: Determine whether these should be provided, and 167*61c4878aSAndroid Build Coastguard Worker if so, add them. 168*61c4878aSAndroid Build Coastguard Worker- **Additional smart pointers**: Determine if pointers like ``std::shared_ptr``, 169*61c4878aSAndroid Build Coastguard Worker etc., are needed, and if so, add them. 170*61c4878aSAndroid Build Coastguard Worker- **Dynamic containers**: Provide the concept of allocator equality without 171*61c4878aSAndroid Build Coastguard Worker using RTTI or ``typeid``. This would allow dynamic containers with their own 172*61c4878aSAndroid Build Coastguard Worker allocators. 173*61c4878aSAndroid Build Coastguard Worker- **Default allocators**: Integrate ``pw_allocator`` into the monolithic 174*61c4878aSAndroid Build Coastguard Worker ``pw_system`` as a starting point for projects. 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard WorkerFound a bug? Got a feature request? Please create a new issue in our `tracker`_! 177*61c4878aSAndroid Build Coastguard Worker 178*61c4878aSAndroid Build Coastguard WorkerWant to discuss allocators in real-time with the Pigweed team? Head over to our 179*61c4878aSAndroid Build Coastguard Worker`Discord`_! 180*61c4878aSAndroid Build Coastguard Worker 181*61c4878aSAndroid Build Coastguard Worker.. _memory defects: https://en.wikipedia.org/wiki/Memory_corruption 182*61c4878aSAndroid Build Coastguard Worker.. _golden hammer: https://en.wikipedia.org/wiki/Law_of_the_instrument#Computer_programming 183*61c4878aSAndroid Build Coastguard Worker.. _bin packing problem: https://en.wikipedia.org/wiki/Bin_packing_problem 184*61c4878aSAndroid Build Coastguard Worker.. _std::pmr::memory_resource: https://en.cppreference.com/w/cpp/memory/memory_resource 185*61c4878aSAndroid Build Coastguard Worker.. _std::pmr::polymorphic_allocator: https://en.cppreference.com/w/cpp/memory/polymorphic_allocator 186*61c4878aSAndroid Build Coastguard Worker.. _can use an allocator: https://en.cppreference.com/w/cpp/memory/uses_allocator 187*61c4878aSAndroid Build Coastguard Worker.. _tracker: https://pwbug.dev 188*61c4878aSAndroid Build Coastguard Worker.. _Discord: https://discord.gg/M9NSeTA 189