13#if defined(OS_USE_OS_APP_CONFIG_H)
14#include <cmsis-plus/os-app-config.h>
23#pragma clang diagnostic ignored "-Wc++98-compat"
43 assert(bytes > chunk_minsize);
51 res = std::align (chunk_align, chunk_minsize, arena_addr_, total_bytes_);
55 assert(res !=
nullptr);
57 assert((total_bytes_ % chunk_align) == 0);
66 chunk_t* chunk =
reinterpret_cast<chunk_t*
> (arena_addr_);
68 chunk->size = total_bytes_;
70 chunk->next =
nullptr;
73 max_allocated_bytes_ = 0;
74 free_bytes_ = total_bytes_;
75 allocated_chunks_ = 0;
85#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
86 trace::printf (
"first_fit_top::%s() @%p %s\n", __func__,
this, name ());
92#pragma GCC diagnostic push
94#pragma GCC diagnostic ignored "-Wunused-parameter"
115 std::size_t block_padding = calc_block_padding (alignment);
117 alloc_size += block_padding;
118 alloc_size += chunk_offset;
120 std::size_t block_minchunk = calc_block_minchunk (block_padding);
127 chunk_t* prev_chunk = free_list_;
132 int rem =
static_cast<int> (chunk->size - alloc_size);
135 if ((
static_cast<std::size_t
> (rem)) >= block_minchunk)
141 chunk->size =
static_cast<std::size_t
> (rem);
142#pragma GCC diagnostic push
143#pragma GCC diagnostic ignored "-Wcast-align"
145 reinterpret_cast<chunk_t *
> (
reinterpret_cast<char *
> (chunk)
147#pragma GCC diagnostic pop
148 chunk->size = alloc_size;
158 if (prev_chunk == chunk)
162 free_list_ = chunk->next;
169 prev_chunk->next = chunk->next;
178 if (chunk !=
nullptr)
183 if (out_of_memory_handler_ ==
nullptr)
185#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
186 trace::printf (
"first_fit_top::%s(%u,%u)=0 @%p %s\n", __func__,
187 bytes, alignment,
this,
name ());
193#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
194 trace::printf (
"first_fit_top::%s(%u,%u) @%p %s out of memory\n",
195 __func__, bytes, alignment,
this,
name ());
197 out_of_memory_handler_ ();
205#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
206 trace::printf (
"first_fit_top::%s(%u,%u)=%p,%u @%p %s\n", __func__, bytes,
207 alignment, aligned_payload, alloc_size,
this,
name ());
210 return aligned_payload;
229 std::size_t alignment)
noexcept
231#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
232 trace::printf (
"first_fit_top::%s(%p,%u,%u) @%p %s\n", __func__, addr,
233 bytes, alignment,
this, name ());
237 if ((addr < arena_addr_)
238 || (addr > (
static_cast<char*
> (arena_addr_) + total_bytes_)))
244#pragma GCC diagnostic push
245#pragma GCC diagnostic ignored "-Wcast-align"
247 chunk_t* chunk =
reinterpret_cast<chunk_t *
> (
static_cast<char *
> (addr)
251 if (
static_cast<std::ptrdiff_t
> (chunk->size) < 0)
253 chunk =
reinterpret_cast<chunk_t *
> (
reinterpret_cast<char *
> (chunk)
254 +
static_cast<std::ptrdiff_t
> (chunk->size));
256#pragma GCC diagnostic pop
262 if (bytes + chunk_offset > chunk->size)
271 internal_decrease_allocated_statistics (chunk->size);
274 if (free_list_ ==
nullptr)
277 chunk->next =
nullptr;
281 assert(free_chunks_ == 1);
287 if (chunk < free_list_)
290 if (
reinterpret_cast<char *
> (chunk) + chunk->size
291 ==
reinterpret_cast<char *
> (free_list_))
294 chunk->size += free_list_->size;
295 chunk->next = free_list_->next;
303 chunk->next = free_list_;
315 chunk_t* next_chunk = free_list_;
319 prev_chunk = next_chunk;
320 next_chunk = next_chunk->next;
322 while (next_chunk !=
nullptr && next_chunk <= chunk);
328 if (
reinterpret_cast<char *
> (prev_chunk) + prev_chunk->size
329 ==
reinterpret_cast<char *
> (chunk))
332 prev_chunk->size += chunk->size;
339 if (
reinterpret_cast<char *
> (prev_chunk) + prev_chunk->size
340 ==
reinterpret_cast<char *
> (next_chunk))
342 prev_chunk->size += next_chunk->size;
343 prev_chunk->next = next_chunk->next;
349 else if (
reinterpret_cast<char *
> (prev_chunk) + prev_chunk->size
350 >
reinterpret_cast<char *
> (chunk))
356 allocated_bytes_ += chunk->size;
357 free_bytes_ -= chunk->size;
361 trace::printf (
"first_fit_top::%s(%p,%u,%u) @%p %s already freed\n",
362 __func__, addr, bytes, alignment,
this, name ());
367 else if (
reinterpret_cast<char *
> (chunk) + chunk->size
368 ==
reinterpret_cast<char *
> (next_chunk))
371 chunk->size += next_chunk->size;
372 chunk->next = next_chunk->next;
373 prev_chunk->next = chunk;
382 chunk->next = next_chunk;
383 prev_chunk->next = chunk;
395 std::size_t alignment)
402 char* payload =
reinterpret_cast<char *
> (chunk) + chunk_offset;
405 void* aligned_payload = payload;
406 std::size_t aligned_size = chunk->size - chunk_offset;
409 res = std::align (alignment, bytes, aligned_payload, aligned_size);
412 assert(res !=
nullptr);
416 std::ptrdiff_t offset =
static_cast<char *
> (aligned_payload) - payload;
422#pragma GCC diagnostic push
423#pragma GCC diagnostic ignored "-Wcast-align"
425 reinterpret_cast<chunk_t *
> (
static_cast<char *
> (aligned_payload)
427 adj_chunk->size =
static_cast<std::size_t
> (-offset);
428#pragma GCC diagnostic pop
432 (
reinterpret_cast<uintptr_t
> (aligned_payload) & (alignment - 1))
435 return aligned_payload;
438#pragma GCC diagnostic pop
virtual ~first_fit_top() override
Destruct the memory resource object instance.
virtual void do_reset(void) noexcept override
Implementation of the function to reset the memory manager.
void * internal_align_(chunk_t *chunk, std::size_t bytes, std::size_t alignment)
Internal function to align a chunk.
virtual void do_deallocate(void *addr, std::size_t bytes, std::size_t alignment) noexcept override
Implementation of the memory deallocator.
void internal_reset_(void) noexcept
Internal function to reset the memory resource.
virtual void * do_allocate(std::size_t bytes, std::size_t alignment) override
Implementation of the memory allocator.
virtual std::size_t do_max_size(void) const noexcept override
Implementation of the function to get max size.
void internal_construct_(void *addr, std::size_t bytes)
Internal function to construct the memory resource.
const char * name(void) const
Get object name.
void internal_increase_allocated_statistics(std::size_t bytes) noexcept
Update statistics after allocation.
int printf(const char *format,...)
Write a formatted string to the trace device.
constexpr std::size_t align_size(std::size_t size, std::size_t align) noexcept
Helper function to align size values.
constexpr std::size_t max(std::size_t a, std::size_t b)