34#pragma clang diagnostic ignored "-Wc++98-compat"
54 assert(bytes > chunk_minsize);
62 res = std::align (chunk_align, chunk_minsize, arena_addr_, total_bytes_);
66 assert(res !=
nullptr);
68 assert((total_bytes_ % chunk_align) == 0);
77 chunk_t* chunk =
reinterpret_cast<chunk_t*
> (arena_addr_);
79 chunk->size = total_bytes_;
81 chunk->next =
nullptr;
84 max_allocated_bytes_ = 0;
85 free_bytes_ = total_bytes_;
86 allocated_chunks_ = 0;
96#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
97 trace::printf (
"first_fit_top::%s() @%p %s\n", __func__,
this, name ());
103#pragma GCC diagnostic push
105#pragma GCC diagnostic ignored "-Wunused-parameter"
126 std::size_t block_padding = calc_block_padding (alignment);
128 alloc_size += block_padding;
129 alloc_size += chunk_offset;
131 std::size_t block_minchunk = calc_block_minchunk (block_padding);
138 chunk_t* prev_chunk = free_list_;
143 int rem =
static_cast<int> (chunk->size - alloc_size);
146 if ((
static_cast<std::size_t
> (rem)) >= block_minchunk)
152 chunk->size =
static_cast<std::size_t
> (rem);
154 reinterpret_cast<chunk_t *
> (
reinterpret_cast<char *
> (chunk)
156 chunk->size = alloc_size;
166 if (prev_chunk == chunk)
170 free_list_ = chunk->next;
177 prev_chunk->next = chunk->next;
186 if (chunk !=
nullptr)
191 if (out_of_memory_handler_ ==
nullptr)
193#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
194 trace::printf (
"first_fit_top::%s(%u,%u)=0 @%p %s\n", __func__,
195 bytes, alignment,
this,
name ());
201#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
202 trace::printf (
"first_fit_top::%s(%u,%u) @%p %s out of memory\n",
203 __func__, bytes, alignment,
this,
name ());
205 out_of_memory_handler_ ();
213#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
214 trace::printf (
"first_fit_top::%s(%u,%u)=%p,%u @%p %s\n", __func__, bytes,
215 alignment, aligned_payload, alloc_size,
this,
name ());
218 return aligned_payload;
237 std::size_t alignment)
noexcept
239#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
240 trace::printf (
"first_fit_top::%s(%p,%u,%u) @%p %s\n", __func__, addr,
241 bytes, alignment,
this, name ());
245 if ((addr < arena_addr_)
246 || (addr > (
static_cast<char*
> (arena_addr_) + total_bytes_)))
253 chunk_t* chunk =
reinterpret_cast<chunk_t *
> (
static_cast<char *
> (addr)
257 if (
static_cast<std::ptrdiff_t
> (chunk->size) < 0)
259 chunk =
reinterpret_cast<chunk_t *
> (
reinterpret_cast<char *
> (chunk)
260 +
static_cast<std::ptrdiff_t
> (chunk->size));
267 if (bytes + chunk_offset > chunk->size)
276 internal_decrease_allocated_statistics (chunk->size);
279 if (free_list_ ==
nullptr)
282 chunk->next =
nullptr;
286 assert(free_chunks_ == 1);
292 if (chunk < free_list_)
295 if (
reinterpret_cast<char *
> (chunk) + chunk->size
296 ==
reinterpret_cast<char *
> (free_list_))
299 chunk->size += free_list_->size;
300 chunk->next = free_list_->next;
308 chunk->next = free_list_;
320 chunk_t* next_chunk = free_list_;
324 prev_chunk = next_chunk;
325 next_chunk = next_chunk->next;
327 while (next_chunk !=
nullptr && next_chunk <= chunk);
333 if (
reinterpret_cast<char *
> (prev_chunk) + prev_chunk->size
334 ==
reinterpret_cast<char *
> (chunk))
337 prev_chunk->size += chunk->size;
344 if (
reinterpret_cast<char *
> (prev_chunk) + prev_chunk->size
345 ==
reinterpret_cast<char *
> (next_chunk))
347 prev_chunk->size += next_chunk->size;
348 prev_chunk->next = next_chunk->next;
354 else if (
reinterpret_cast<char *
> (prev_chunk) + prev_chunk->size
355 >
reinterpret_cast<char *
> (chunk))
361 allocated_bytes_ += chunk->size;
362 free_bytes_ -= chunk->size;
366 trace::printf (
"first_fit_top::%s(%p,%u,%u) @%p %s already freed\n",
367 __func__, addr, bytes, alignment,
this, name ());
372 else if (
reinterpret_cast<char *
> (chunk) + chunk->size
373 ==
reinterpret_cast<char *
> (next_chunk))
376 chunk->size += next_chunk->size;
377 chunk->next = next_chunk->next;
378 prev_chunk->next = chunk;
387 chunk->next = next_chunk;
388 prev_chunk->next = chunk;
400 std::size_t alignment)
407 char* payload =
reinterpret_cast<char *
> (chunk) + chunk_offset;
410 void* aligned_payload = payload;
411 std::size_t aligned_size = chunk->size - chunk_offset;
414 res = std::align (alignment, bytes, aligned_payload, aligned_size);
417 assert(res !=
nullptr);
421 std::ptrdiff_t offset =
static_cast<char *
> (aligned_payload) - payload;
428 reinterpret_cast<chunk_t *
> (
static_cast<char *
> (aligned_payload)
430 adj_chunk->size =
static_cast<std::size_t
> (-offset);
434 (
reinterpret_cast<uintptr_t
> (aligned_payload) & (alignment - 1))
437 return aligned_payload;
440#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)