µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
lifo.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2016-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#if defined(OS_USE_OS_APP_CONFIG_H)
13#include <cmsis-plus/os-app-config.h>
14#endif
15
17#include <memory>
18
19// ----------------------------------------------------------------------------
20
21#if defined(__clang__)
22#pragma clang diagnostic ignored "-Wc++98-compat"
23#endif
24
25// ----------------------------------------------------------------------------
26
27namespace os
28{
29 namespace memory
30 {
31
32 // ========================================================================
33
35 {
36 trace::printf ("lifo::%s() @%p %s\n", __func__, this, this->name ());
37 }
38
39#pragma GCC diagnostic push
40// Needed because 'alignment' is used only in trace calls.
41#pragma GCC diagnostic ignored "-Wunused-parameter"
42
67 void*
68 lifo::do_allocate (std::size_t bytes, std::size_t alignment)
69 {
70 std::size_t block_padding = calc_block_padding (alignment);
71 std::size_t alloc_size = rtos::memory::align_size (bytes, chunk_align);
72 alloc_size += block_padding;
73 alloc_size += chunk_offset;
74
75 std::size_t block_minchunk = calc_block_minchunk (block_padding);
76 alloc_size = os::rtos::memory::max (alloc_size, block_minchunk);
77
78 chunk_t* chunk = nullptr;
79
80 while (true)
81 {
82 // Allocate only from the first block and only if it is
83 // the really first in the arena; this prevents fragmentation.
84 if (free_list_ == reinterpret_cast<chunk_t*> (arena_addr_))
85 {
86 chunk = free_list_;
87
88 int rem = static_cast<int> (chunk->size - alloc_size);
89 if (rem >= 0)
90 {
91 if ((static_cast<std::size_t> (rem)) >= block_minchunk)
92 {
93 // If the chunk is larger than needed
94 // (at least one more chunk is available);
95 // break it into two chunks and return the top one.
96
97 // Shrink bottom chunk to remaining size.
98 chunk->size = static_cast<std::size_t> (rem);
99
100#pragma GCC diagnostic push
101#pragma GCC diagnostic ignored "-Wcast-align"
102#if defined(__clang__)
103#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
104#endif
105 // Compute where top chunk starts.
106 chunk = reinterpret_cast<chunk_t*> (
107 reinterpret_cast<char*> (chunk) + rem);
108#pragma GCC diagnostic pop
109 chunk->size = alloc_size;
110
111 // Splitting one chunk creates one more chunk.
112 ++free_chunks_;
113 }
114 else
115 {
116 // Found a chunk that is exactly the size or slightly
117 // larger than the requested size; return this chunk.
118
119 // Always at the list head.
120 // The next chunk becomes the first list element.
121 free_list_ = chunk->next;
122
123 // If this was the last chunk, the free list is empty.
124 }
125 }
126 }
127
128 if (chunk != nullptr)
129 {
130 break;
131 }
132
133 if (out_of_memory_handler_ == nullptr)
134 {
135#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
136 trace::printf ("lifo::%s(%u,%u)=0 @%p %s\n", __func__, bytes,
137 alignment, this, this->name ());
138#endif
139
140 return nullptr;
141 }
142
143#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
144 trace::printf ("lifo::%s(%u,%u) @%p %s out of memory\n", __func__,
145 bytes, alignment, this, this->name ());
146#endif
147 out_of_memory_handler_ ();
148
149 // If the handler returned, assume it freed some memory
150 // and try again to allocate.
151 }
152
153 void* aligned_payload = internal_align_ (chunk, bytes, alignment);
154
155#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
156 trace::printf ("lifo::%s(%u,%u)=%p,%u @%p %s\n", __func__, bytes,
157 alignment, aligned_payload, alloc_size, this, name ());
158#endif
159
160 return aligned_payload;
161 }
162
163#pragma GCC diagnostic pop
164
165 // ------------------------------------------------------------------------
166 } /* namespace memory */
167} /* namespace os */
168
169// ----------------------------------------------------------------------------
void * internal_align_(chunk_t *chunk, std::size_t bytes, std::size_t alignment)
Internal function to align a chunk.
virtual ~lifo() override
Destruct the memory resource object instance.
Definition lifo.cpp:34
virtual void * do_allocate(std::size_t bytes, std::size_t alignment) override
Implementation of the memory allocator.
Definition lifo.cpp:68
const char * name(void) const
Get object name.
Definition os-decls.h:753
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
constexpr std::size_t align_size(std::size_t size, std::size_t align) noexcept
Helper function to align size values.
Definition os-memory.h:85
constexpr std::size_t max(std::size_t a, std::size_t b)
Definition os-memory.h:73
System namespace.