12#if defined(OS_USE_OS_APP_CONFIG_H)
13#include <cmsis-plus/os-app-config.h>
22#pragma clang diagnostic ignored "-Wc++98-compat"
42 assert (bytes > chunk_minsize);
50 res = std::align (chunk_align, chunk_minsize, arena_addr_, total_bytes_);
54 assert (res !=
nullptr);
56 assert ((total_bytes_ % chunk_align) == 0);
65 chunk_t* chunk =
reinterpret_cast<chunk_t*
> (arena_addr_);
67 chunk->size = total_bytes_;
69 chunk->next =
nullptr;
72 max_allocated_bytes_ = 0;
73 free_bytes_ = total_bytes_;
74 allocated_chunks_ = 0;
84#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
85 trace::printf (
"first_fit_top::%s() @%p %s\n", __func__,
this, name ());
91#pragma GCC diagnostic push
93#pragma GCC diagnostic ignored "-Wunused-parameter"
114 std::size_t block_padding = calc_block_padding (alignment);
116 alloc_size += block_padding;
117 alloc_size += chunk_offset;
119 std::size_t block_minchunk = calc_block_minchunk (block_padding);
126 chunk_t* prev_chunk = free_list_;
131 int rem =
static_cast<int> (chunk->size - alloc_size);
134 if ((
static_cast<std::size_t
> (rem)) >= block_minchunk)
140 chunk->size =
static_cast<std::size_t
> (rem);
141#pragma GCC diagnostic push
142#pragma GCC diagnostic ignored "-Wcast-align"
143#if defined(__clang__)
144#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
146 chunk =
reinterpret_cast<chunk_t*
> (
147 reinterpret_cast<char*
> (chunk) + rem);
148#pragma GCC diagnostic pop
149 chunk->size = alloc_size;
159 if (prev_chunk == chunk)
163 free_list_ = chunk->next;
171 prev_chunk->next = chunk->next;
180 if (chunk !=
nullptr)
185 if (out_of_memory_handler_ ==
nullptr)
187#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
188 trace::printf (
"first_fit_top::%s(%u,%u)=0 @%p %s\n", __func__,
189 bytes, alignment,
this,
name ());
195#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
196 trace::printf (
"first_fit_top::%s(%u,%u) @%p %s out of memory\n",
197 __func__, bytes, alignment,
this,
name ());
199 out_of_memory_handler_ ();
207#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
208 trace::printf (
"first_fit_top::%s(%u,%u)=%p,%u @%p %s\n", __func__,
209 bytes, alignment, aligned_payload, alloc_size,
this,
213 return aligned_payload;
232 std::size_t alignment)
noexcept
234#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
235 trace::printf (
"first_fit_top::%s(%p,%u,%u) @%p %s\n", __func__, addr,
236 bytes, alignment,
this, name ());
240#pragma GCC diagnostic push
241#if defined(__clang__)
242#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
244 if ((addr < arena_addr_)
245 || (addr > (
static_cast<char*
> (arena_addr_) + total_bytes_)))
250#pragma GCC diagnostic pop
252#pragma GCC diagnostic push
253#pragma GCC diagnostic ignored "-Wcast-align"
254#if defined(__clang__)
255#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
258 chunk_t* chunk =
reinterpret_cast<chunk_t*
> (
static_cast<char*
> (addr)
262 if (
static_cast<std::ptrdiff_t
> (chunk->size) < 0)
264 chunk =
reinterpret_cast<chunk_t*
> (
265 reinterpret_cast<char*
> (chunk)
266 +
static_cast<std::ptrdiff_t
> (chunk->size));
268#pragma GCC diagnostic pop
274 if (bytes + chunk_offset > chunk->size)
283 internal_decrease_allocated_statistics (chunk->size);
286 if (free_list_ ==
nullptr)
289 chunk->next =
nullptr;
293 assert (free_chunks_ == 1);
299 if (chunk < free_list_)
302#pragma GCC diagnostic push
303#if defined(__clang__)
304#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
306 if (
reinterpret_cast<char*
> (chunk) + chunk->size
307 ==
reinterpret_cast<char*
> (free_list_))
310 chunk->size += free_list_->size;
311 chunk->next = free_list_->next;
319 chunk->next = free_list_;
321#pragma GCC diagnostic pop
332 chunk_t* next_chunk = free_list_;
336 prev_chunk = next_chunk;
337 next_chunk = next_chunk->next;
339 while (next_chunk !=
nullptr && next_chunk <= chunk);
345#pragma GCC diagnostic push
346#if defined(__clang__)
347#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
349 if (
reinterpret_cast<char*
> (prev_chunk) + prev_chunk->size
350 ==
reinterpret_cast<char*
> (chunk))
353 prev_chunk->size += chunk->size;
360 if (
reinterpret_cast<char*
> (prev_chunk) + prev_chunk->size
361 ==
reinterpret_cast<char*
> (next_chunk))
363 prev_chunk->size += next_chunk->size;
364 prev_chunk->next = next_chunk->next;
370 else if (
reinterpret_cast<char*
> (prev_chunk) + prev_chunk->size
371 >
reinterpret_cast<char*
> (chunk))
377 allocated_bytes_ += chunk->size;
378 free_bytes_ -= chunk->size;
382 trace::printf (
"first_fit_top::%s(%p,%u,%u) @%p %s already freed\n",
383 __func__, addr, bytes, alignment,
this, name ());
388 else if (
reinterpret_cast<char*
> (chunk) + chunk->size
389 ==
reinterpret_cast<char*
> (next_chunk))
392 chunk->size += next_chunk->size;
393 chunk->next = next_chunk->next;
394 prev_chunk->next = chunk;
403 chunk->next = next_chunk;
404 prev_chunk->next = chunk;
407#pragma GCC diagnostic pop
417 std::size_t alignment)
424#pragma GCC diagnostic push
425#if defined(__clang__)
426#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
428 char* payload =
reinterpret_cast<char*
> (chunk) + chunk_offset;
429#pragma GCC diagnostic pop
432 void* aligned_payload = payload;
433 std::size_t aligned_size = chunk->size - chunk_offset;
436 res = std::align (alignment, bytes, aligned_payload, aligned_size);
439 assert (res !=
nullptr);
443 std::ptrdiff_t offset =
static_cast<char*
> (aligned_payload) - payload;
449#pragma GCC diagnostic push
450#pragma GCC diagnostic ignored "-Wcast-align"
451#if defined(__clang__)
452#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
454 chunk_t* adj_chunk =
reinterpret_cast<chunk_t*
> (
455 static_cast<char*
> (aligned_payload) - chunk_offset);
456 adj_chunk->size =
static_cast<std::size_t
> (-offset);
457#pragma GCC diagnostic pop
460 assert ((
reinterpret_cast<uintptr_t
> (aligned_payload) & (alignment - 1))
463 return aligned_payload;
466#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)