µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os::memory::first_fit_top Class Reference

Memory resource implementing the first fit, top-down allocation policies, using an existing arena. More...

#include <cmsis-plus/memory/first-fit-top.h>

+ Inheritance diagram for os::memory::first_fit_top:

Public Member Functions

Public Member Functions
void * allocate (std::size_t bytes, std::size_t alignment=max_align)
 Allocate a memory block.
 
void deallocate (void *addr, std::size_t bytes, std::size_t alignment=max_align) noexcept
 Deallocate the previously allocated memory block.
 
bool is_equal (memory_resource const &other) const noexcept
 Compare for equality with another memory_resource.
 
void reset (void) noexcept
 Reset the memory manager to the initial state.
 
bool coalesce (void) noexcept
 Coalesce free blocks.
 
std::size_t max_size (void) const noexcept
 Get the largest value that can be passed to allocate().
 
out_of_memory_handler_t out_of_memory_handler (out_of_memory_handler_t handler)
 Set the out of memory handler.
 
out_of_memory_handler_t out_of_memory_handler (void)
 Get the out of memory handler.
 
std::size_t total_bytes (void)
 Get the total size of managed memory.
 
std::size_t allocated_bytes (void)
 Get the current size of all allocated chunks.
 
std::size_t max_allocated_bytes (void)
 Get the maximum allocated size.
 
std::size_t free_bytes (void)
 Get the current size of all free chunks.
 
std::size_t allocated_chunks (void)
 Get the current number of allocated chunks.
 
std::size_t free_chunks (void)
 Get the current number of free chunks.
 
std::size_t allocations (void)
 Get the number of allocations.
 
std::size_t deallocations (void)
 Get the number of deallocations.
 
void trace_print_statistics (void)
 Print a long message with usage statistics.
 
Public Member Functions
const char * name (void) const
 Get object name.
 

Static Public Attributes

static constexpr std::size_t max_align = alignof (std::max_align_t)
 The largest alignment for the platform. Also default when supplied alignment is not supported.
 

Protected Member Functions

Private Member Functions
void internal_construct_ (void *addr, std::size_t bytes)
 Internal function to construct the memory resource.
 
void internal_reset_ (void) noexcept
 Internal function to reset the memory resource.
 
void * internal_align_ (chunk_t *chunk, std::size_t bytes, std::size_t alignment)
 Internal function to align a chunk.
 
virtual void * do_allocate (std::size_t bytes, std::size_t alignment) override
 Implementation of the memory allocator.
 
virtual void do_deallocate (void *addr, std::size_t bytes, std::size_t alignment) noexcept override
 Implementation of the memory deallocator.
 
virtual std::size_t do_max_size (void) const noexcept override
 Implementation of the function to get max size.
 
virtual void do_reset (void) noexcept override
 Implementation of the function to reset the memory manager.
 
Private Member Functions
virtual bool do_is_equal (memory_resource const &other) const noexcept
 Implementation of the equality comparator.
 
virtual bool do_coalesce (void) noexcept
 Implementation of the function to coalesce free blocks.
 
void internal_increase_allocated_statistics (std::size_t bytes) noexcept
 Update statistics after allocation.
 
void internal_decrease_allocated_statistics (std::size_t bytes) noexcept
 Update statistics after deallocation.
 

Constructors & Destructor

 first_fit_top (void *addr, std::size_t bytes)
 Construct a memory resource object instance.
 
 first_fit_top (const char *name, void *addr, std::size_t bytes)
 Construct a named memory resource object instance.
 
virtual ~first_fit_top () override
 Destruct the memory resource object instance.
 
 first_fit_top ()=default
 Default constructor. Construct a memory resource object instance.
 
 first_fit_top (const char *name)
 Construct a named memory resource object instance.
 

Detailed Description

This memory manager was inspired by the newlib nano implementation of malloc() & free().

Neither allocation nor deallocation are deterministic, but are reasonably fast.

Definition at line 53 of file first-fit-top.h.

Constructor & Destructor Documentation

◆ first_fit_top() [1/4]

os::memory::first_fit_top::first_fit_top ( void *  addr,
std::size_t  bytes 
)
inline
Parameters
[in]addrBegin of allocator arena.
[in]bytesSize of allocator arena, in bytes.

Definition at line 483 of file first-fit-top.h.

484 : first_fit_top{ nullptr, addr, bytes }
485 {
486 }
first_fit_top()=default
Default constructor. Construct a memory resource object instance.

◆ first_fit_top() [2/4]

os::memory::first_fit_top::first_fit_top ( const char *  name,
void *  addr,
std::size_t  bytes 
)
inline
Parameters
[in]namePointer to name.
[in]addrBegin of allocator arena.
[in]bytesSize of allocator arena, in bytes.

Definition at line 488 of file first-fit-top.h.

490 : rtos::memory::memory_resource{ name }
491 {
492 trace::printf ("%s(%p,%u) @%p %s\n", __func__, addr, bytes, this,
493 this->name ());
494
495 internal_construct_ (addr, bytes);
496 }
void internal_construct_(void *addr, std::size_t bytes)
Internal function to construct the memory resource.
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

References internal_construct_(), and os::trace::printf().

◆ first_fit_top() [3/4]

os::memory::first_fit_top::first_fit_top ( )
protecteddefault

◆ first_fit_top() [4/4]

os::memory::first_fit_top::first_fit_top ( const char *  name)
inlineprotected
Parameters
[in]namePointer to name.

Definition at line 478 of file first-fit-top.h.

479 : rtos::memory::memory_resource{ name }
480 {
481 }

◆ ~first_fit_top()

os::memory::first_fit_top::~first_fit_top ( )
overridevirtual

Definition at line 34 of file first-fit-top.cpp.

35 {
36 trace::printf ("first_fit_top::%s() @%p %s\n", __func__, this, name ());
37 }

References os::rtos::internal::object_named::name(), and os::trace::printf().

Member Function Documentation

◆ allocate()

void * os::rtos::memory::memory_resource::allocate ( std::size_t  bytes,
std::size_t  alignment = max_align 
)
inlineinherited
Parameters
bytesNumber of bytes to allocate.
alignmentAlignment constraint (power of 2).
Returns
Pointer to newly allocated block, or nullptr.

Allocate storage with a size of at least bytes bytes. The returned storage is aligned to the specified alignment if such alignment is supported, and to alignof(std::max_align_t) otherwise.

If the storage of the requested size and alignment cannot be obtained:

  • if the out of memory handler is not set, return nullptr;
  • if the out of memory handler is set, call it and retry.

Equivalent to return do_allocate(bytes, alignment);.

Exceptions
The code itself throws nothing, but if the out of memory handler is set, it may throw a bad_alloc() exception.
See also
do_allocate();

Definition at line 1290 of file os-memory.h.

1291 {
1292 ++allocations_;
1293 return do_allocate (bytes, alignment);
1294 }
virtual void * do_allocate(std::size_t bytes, std::size_t alignment)=0
Implementation of the memory allocator.

References os::rtos::memory::memory_resource::do_allocate().

Referenced by os::estd::pmr::polymorphic_allocator< T >::allocate(), calloc(), malloc(), operator new(), and realloc().

◆ allocated_bytes()

std::size_t os::rtos::memory::memory_resource::allocated_bytes ( void  )
inlineinherited
Parameters
None.
Returns
Number of bytes.

Definition at line 1402 of file os-memory.h.

1403 {
1404 return allocated_bytes_;
1405 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ allocated_chunks()

std::size_t os::rtos::memory::memory_resource::allocated_chunks ( void  )
inlineinherited
Parameters
None.
Returns
Number of chunks.

Definition at line 1420 of file os-memory.h.

1421 {
1422 return allocated_chunks_;
1423 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ allocations()

std::size_t os::rtos::memory::memory_resource::allocations ( void  )
inlineinherited
Parameters
None.
Returns
Number of allocations.

Definition at line 1432 of file os-memory.h.

1433 {
1434 return allocations_;
1435 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ coalesce()

bool os::rtos::memory::memory_resource::coalesce ( void  )
inlinenoexceptinherited
Parameters
None.
Return values
trueif the operation freed more memory.
falseif the operation was ineffective.

In case the memory manager does not coalesce during deallocation, traverse the list of free blocks and coalesce.

Return true if the operation was successful and at least one larger block resulted.

See also
do_coalesce();

Definition at line 1365 of file os-memory.h.

1366 {
1367 return do_coalesce ();
1368 }
virtual bool do_coalesce(void) noexcept
Implementation of the function to coalesce free blocks.

◆ deallocate()

void os::rtos::memory::memory_resource::deallocate ( void *  addr,
std::size_t  bytes,
std::size_t  alignment = max_align 
)
inlinenoexceptinherited
Parameters
addrAddress of the block to free.
bytesNumber of bytes to deallocate (may be 0 if unknown).
alignmentAlignment constraint (power of 2).
Returns
Nothing.

Deallocate the storage pointed to by addr. The address shall have been returned by a prior call to allocate() on a memory_resource that compares equal to *this, and the storage it points to shall not yet have been deallocated.

Equivalent to return do_deallocate(p, bytes, alignment);.

Exceptions
Throws nothing.
See also
do_deallocate();

Definition at line 1312 of file os-memory.h.

1314 {
1315 ++deallocations_;
1316 do_deallocate (addr, bytes, alignment);
1317 }
virtual void do_deallocate(void *addr, std::size_t bytes, std::size_t alignment) noexcept=0
Implementation of the memory deallocator.

Referenced by os::estd::pmr::polymorphic_allocator< T >::deallocate(), free(), and realloc().

◆ deallocations()

std::size_t os::rtos::memory::memory_resource::deallocations ( void  )
inlineinherited
Parameters
None.
Returns
Number of deallocations

Definition at line 1438 of file os-memory.h.

1439 {
1440 return deallocations_;
1441 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ do_allocate()

void * os::memory::first_fit_top::do_allocate ( std::size_t  bytes,
std::size_t  alignment 
)
overrideprotectedvirtual
Parameters
[in]bytesNumber of bytes to allocate.
[in]alignmentAlignment constraint (power of 2).
Returns
Pointer to newly allocated block, or nullptr.

The allocator tries to be fast and grasps the first block large enough, possibly splitting large blocks and increasing fragmentation. If the block is only slightly larger (the remaining space is not large enough for a minimum chunk) the block is not split, but left partly unused.

When large blocks are split, the top sub-block is returned; in other words, memory is allocated top-down. This speeds up deallocation for blocks allocated recently.

Exceptions
Throws nothing by itself, but the out of memory handler may throw bad_alloc().

Implements os::rtos::memory::memory_resource.

Reimplemented in os::memory::lifo.

Definition at line 112 of file first-fit-top.cpp.

113 {
114 std::size_t block_padding = calc_block_padding (alignment);
115 std::size_t alloc_size = rtos::memory::align_size (bytes, chunk_align);
116 alloc_size += block_padding;
117 alloc_size += chunk_offset;
118
119 std::size_t block_minchunk = calc_block_minchunk (block_padding);
120 alloc_size = os::rtos::memory::max (alloc_size, block_minchunk);
121
122 chunk_t* chunk;
123
124 while (true)
125 {
126 chunk_t* prev_chunk = free_list_;
127 chunk = prev_chunk;
128
129 while (chunk)
130 {
131 int rem = static_cast<int> (chunk->size - alloc_size);
132 if (rem >= 0)
133 {
134 if ((static_cast<std::size_t> (rem)) >= block_minchunk)
135 {
136 // Found a chunk that is much larger than required size
137 // (at least one more chunk is available);
138 // break it into two chunks and return the second one.
139
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"
145#endif
146 chunk = reinterpret_cast<chunk_t*> (
147 reinterpret_cast<char*> (chunk) + rem);
148#pragma GCC diagnostic pop
149 chunk->size = alloc_size;
150
151 // Splitting one chunk creates one more chunk.
152 ++free_chunks_;
153 }
154 else
155 {
156 // Found a chunk that is exactly the size or slightly
157 // larger than the requested size; return this chunk.
158
159 if (prev_chunk == chunk)
160 {
161 // This implies p==r==free_list, i.e. the list head.
162 // The next chunk becomes the first list element.
163 free_list_ = chunk->next;
164
165 // If this was the last chunk, the free list is
166 // empty.
167 }
168 else
169 {
170 // Normal case. Remove it from the free_list.
171 prev_chunk->next = chunk->next;
172 }
173 }
174 break;
175 }
176 prev_chunk = chunk;
177 chunk = chunk->next;
178 }
179
180 if (chunk != nullptr)
181 {
182 break;
183 }
184
185 if (out_of_memory_handler_ == nullptr)
186 {
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 ());
190#endif
191
192 return nullptr;
193 }
194
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 ());
198#endif
199 out_of_memory_handler_ ();
200
201 // If the handler returned, assume it freed some memory
202 // and try again to allocate.
203 }
204
205 void* aligned_payload = internal_align_ (chunk, bytes, alignment);
206
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,
210 name ());
211#endif
212
213 return aligned_payload;
214 }
void * internal_align_(chunk_t *chunk, std::size_t bytes, std::size_t alignment)
Internal function to align a chunk.
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

References os::rtos::memory::align_size(), internal_align_(), os::rtos::memory::max(), os::rtos::internal::object_named::name(), and os::trace::printf().

◆ do_coalesce()

bool os::rtos::memory::memory_resource::do_coalesce ( void  )
protectedvirtualnoexceptinherited
Parameters
None.
Return values
trueif the operation resulted in larger blocks.
falseif the operation was ineffective.

The default implementation of this virtual function returns false, meaning the operation was ineffective.

Override this function to perform the action.

Standard compliance
Extension to standard.

Definition at line 468 of file os-memory.cpp.

469 {
470 return false;
471 }

◆ do_deallocate()

void os::memory::first_fit_top::do_deallocate ( void *  addr,
std::size_t  bytes,
std::size_t  alignment 
)
overrideprotectedvirtualnoexcept
Parameters
[in]addrAddress of a previously allocated block to free.
[in]bytesNumber of bytes to deallocate (may be 0 if unknown).
[in]alignmentAlignment constraint (power of 2).
Returns
Nothing.

Deallocation is not guaranteed to be deterministic, but if done in strict reverse allocation order, it becomes deterministic, otherwise a traversal of the free list is required, the older the block, the more nodes to traverse (the free list is kept in ascending addresses order).

If the block is already in the free list, issue a trace message, but otherwise ignore the condition.

Exceptions
Throws nothing.

Implements os::rtos::memory::memory_resource.

Definition at line 231 of file first-fit-top.cpp.

233 {
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 ());
237#endif
238
239 // The address must be inside the arena; no exceptions.
240#pragma GCC diagnostic push
241#if defined(__clang__)
242#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
243#endif
244 if ((addr < arena_addr_)
245 || (addr > (static_cast<char*> (arena_addr_) + total_bytes_)))
246 {
247 assert (false);
248 return;
249 }
250#pragma GCC diagnostic pop
251
252#pragma GCC diagnostic push
253#pragma GCC diagnostic ignored "-Wcast-align"
254#if defined(__clang__)
255#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
256#endif
257 // Compute the chunk address from the user address.
258 chunk_t* chunk = reinterpret_cast<chunk_t*> (static_cast<char*> (addr)
259 - chunk_offset);
260
261 // If the block was aligned, the offset appears as size; adjust back.
262 if (static_cast<std::ptrdiff_t> (chunk->size) < 0)
263 {
264 chunk = reinterpret_cast<chunk_t*> (
265 reinterpret_cast<char*> (chunk)
266 + static_cast<std::ptrdiff_t> (chunk->size));
267 }
268#pragma GCC diagnostic pop
269
270 if (bytes)
271 {
272 // If size is known, validate.
273 // (when called from free(), the size is not known).
274 if (bytes + chunk_offset > chunk->size)
275 {
276 assert (false);
277 return;
278 }
279 }
280
281 // Update statistics.
282 // What is subtracted from allocated is added to free.
284
285 // If the free list is empty, create it with the current chunk, alone.
286 if (free_list_ == nullptr)
287 {
288 // Mark the end of the list with a null pointer.
289 chunk->next = nullptr;
290
291 // The chunk becomes the first list element.
292 free_list_ = chunk;
293 assert (free_chunks_ == 1);
294
295 return;
296 }
297
298 // The free list exists; is the chunk before the list head?
299 if (chunk < free_list_)
300 {
301 // Is the chunk *right* before the list head?
302#pragma GCC diagnostic push
303#if defined(__clang__)
304#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
305#endif
306 if (reinterpret_cast<char*> (chunk) + chunk->size
307 == reinterpret_cast<char*> (free_list_))
308 {
309 // Coalesce chunk to the list head.
310 chunk->size += free_list_->size;
311 chunk->next = free_list_->next; // May be nullptr
312
313 // Coalescing means one less chunk.
314 --free_chunks_;
315 }
316 else
317 {
318 // Insert before the list head.
319 chunk->next = free_list_;
320 }
321#pragma GCC diagnostic pop
322 // The chunk becomes the new list head.
323 free_list_ = chunk;
324
325 return;
326 }
327
328 // Walk the free list to find the place to insert,
329 // (the list must be ordered by addresses).
330 // Warning: not deterministic!
331
332 chunk_t* next_chunk = free_list_;
333 chunk_t* prev_chunk;
334 do
335 {
336 prev_chunk = next_chunk;
337 next_chunk = next_chunk->next;
338 }
339 while (next_chunk != nullptr && next_chunk <= chunk);
340
341 // Now prev_chunk <= chunk and either next_chunk == nullptr or
342 // next_chunk > chunk.
343 // Try to merge with chunks immediately before/after it.
344
345#pragma GCC diagnostic push
346#if defined(__clang__)
347#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
348#endif
349 if (reinterpret_cast<char*> (prev_chunk) + prev_chunk->size
350 == reinterpret_cast<char*> (chunk))
351 {
352 // Chunk to be freed is adjacent to a free chunk before it.
353 prev_chunk->size += chunk->size;
354
355 // Coalescing means one less chunk.
356 --free_chunks_;
357
358 // If the merged chunk is also adjacent to the chunk after it,
359 // merge again. Does not match if next_chunk == nullptr.
360 if (reinterpret_cast<char*> (prev_chunk) + prev_chunk->size
361 == reinterpret_cast<char*> (next_chunk))
362 {
363 prev_chunk->size += next_chunk->size;
364 prev_chunk->next = next_chunk->next;
365
366 // Coalescing means one less chunk.
367 --free_chunks_;
368 }
369 }
370 else if (reinterpret_cast<char*> (prev_chunk) + prev_chunk->size
371 > reinterpret_cast<char*> (chunk))
372 {
373 // Already freed.
374
375 // Revert statistics.
376 // What is subtracted from free is added to allocated.
377 allocated_bytes_ += chunk->size;
378 free_bytes_ -= chunk->size;
379 ++allocated_chunks_;
380 --free_chunks_;
381
382 trace::printf ("first_fit_top::%s(%p,%u,%u) @%p %s already freed\n",
383 __func__, addr, bytes, alignment, this, name ());
384
385 return;
386 }
387 // Does not match if next_chunk == nullptr.
388 else if (reinterpret_cast<char*> (chunk) + chunk->size
389 == reinterpret_cast<char*> (next_chunk))
390 {
391 // The chunk to be freed is adjacent to a free chunk after it.
392 chunk->size += next_chunk->size;
393 chunk->next = next_chunk->next; // May be nullptr.
394 prev_chunk->next = chunk;
395
396 // Coalescing means one less chunk.
397 --free_chunks_;
398 }
399 else
400 {
401 // Not adjacent to any chunk. Just insert it.
402 // The result is a new fragment. Not great...
403 chunk->next = next_chunk; // May be nullptr.
404 prev_chunk->next = chunk;
405 }
406 }
void internal_decrease_allocated_statistics(std::size_t bytes) noexcept
Update statistics after deallocation.

References os::trace::printf().

◆ do_is_equal()

bool os::rtos::memory::memory_resource::do_is_equal ( memory_resource const &  other) const
protectedvirtualnoexceptinherited
Parameters
otherReference to another memory_resource.
Return values
trueThe memory_resource objects are equal.
falseThe memory_resource objects are not equal.

Compares *this for equality with other. Two memory_resources compare equal if and only if memory allocated from one memory_resource can be deallocated from the other and vice versa.

The most-derived type of other may not match the most derived type of *this. A derived class implementation therefore must typically check whether the most derived types of *this and other match using dynamic_cast, and immediately return false if the cast fails.

Exceptions
Throws nothing.

Definition at line 419 of file os-memory.cpp.

421 {
422 return &other == this;
423 }

◆ do_max_size()

std::size_t os::memory::first_fit_top::do_max_size ( void  ) const
overrideprotectedvirtualnoexcept
Parameters
None.
Returns
Integer with size in bytes, or 0 if unknown.

Reimplemented from os::rtos::memory::memory_resource.

Definition at line 410 of file first-fit-top.cpp.

411 {
412 return total_bytes_;
413 }

◆ do_reset()

void os::memory::first_fit_top::do_reset ( void  )
overrideprotectedvirtualnoexcept
Parameters
None.
Returns
Nothing.

Reimplemented from os::rtos::memory::memory_resource.

Definition at line 82 of file first-fit-top.cpp.

83 {
84#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
85 trace::printf ("first_fit_top::%s() @%p %s\n", __func__, this, name ());
86#endif
87
89 }
void internal_reset_(void) noexcept
Internal function to reset the memory resource.

References os::trace::printf().

◆ free_bytes()

std::size_t os::rtos::memory::memory_resource::free_bytes ( void  )
inlineinherited
Parameters
None.
Returns
Number of bytes.

Definition at line 1414 of file os-memory.h.

1415 {
1416 return free_bytes_;
1417 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ free_chunks()

std::size_t os::rtos::memory::memory_resource::free_chunks ( void  )
inlineinherited
Parameters
None.
Returns
Number of chunks.

Definition at line 1426 of file os-memory.h.

1427 {
1428 return free_chunks_;
1429 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ internal_align_()

void * os::memory::first_fit_top::internal_align_ ( chunk_t *  chunk,
std::size_t  bytes,
std::size_t  alignment 
)
protected
Parameters
[in]chunkPointer to chunk.
[in]bytesBytes to allocate.
[in]alignmentPower of two.
Returns
Pointer to aligned payload.

Definition at line 416 of file first-fit-top.cpp.

418 {
419 // Update statistics.
420 // The value subtracted from free is added to allocated.
422
423 // Compute pointer to payload area.
424#pragma GCC diagnostic push
425#if defined(__clang__)
426#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
427#endif
428 char* payload = reinterpret_cast<char*> (chunk) + chunk_offset;
429#pragma GCC diagnostic pop
430
431 // Align it to user provided alignment.
432 void* aligned_payload = payload;
433 std::size_t aligned_size = chunk->size - chunk_offset;
434
435 void* res;
436 res = std::align (alignment, bytes, aligned_payload, aligned_size);
437 if (res == nullptr)
438 {
439 assert (res != nullptr);
440 }
441
442 // Compute the possible alignment offset.
443 std::ptrdiff_t offset = static_cast<char*> (aligned_payload) - payload;
444 if (offset)
445 {
446 // If non-zero, store it in the gap left by alignment in the
447 // chunk header.
448
449#pragma GCC diagnostic push
450#pragma GCC diagnostic ignored "-Wcast-align"
451#if defined(__clang__)
452#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
453#endif
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
458 }
459
460 assert ((reinterpret_cast<uintptr_t> (aligned_payload) & (alignment - 1))
461 == 0);
462
463 return aligned_payload;
464 }
void internal_increase_allocated_statistics(std::size_t bytes) noexcept
Update statistics after allocation.

References os::rtos::memory::memory_resource::internal_increase_allocated_statistics().

Referenced by do_allocate(), and os::memory::lifo::do_allocate().

◆ internal_construct_()

void os::memory::first_fit_top::internal_construct_ ( void *  addr,
std::size_t  bytes 
)
protected
Parameters
[in]addrBegin of allocator arena.
[in]bytesSize of allocator arena, in bytes.
Returns
Nothing.

Definition at line 40 of file first-fit-top.cpp.

41 {
42 assert (bytes > chunk_minsize);
43
44 arena_addr_ = addr;
45 total_bytes_ = bytes;
46
47 // Align address for first chunk.
48 void* res;
49 // Possibly adjust the last two parameters.
50 res = std::align (chunk_align, chunk_minsize, arena_addr_, total_bytes_);
51 // std::align() will fail if it cannot fit the min chunk.
52 if (res == nullptr)
53 {
54 assert (res != nullptr);
55 }
56 assert ((total_bytes_ % chunk_align) == 0);
57
59 }

References internal_reset_().

Referenced by first_fit_top(), os::memory::first_fit_top_allocated< A >::first_fit_top_allocated(), os::memory::first_fit_top_inclusive< N >::first_fit_top_inclusive(), os::memory::lifo_allocated< A >::lifo_allocated(), and os::memory::lifo_inclusive< N >::lifo_inclusive().

◆ internal_decrease_allocated_statistics()

void os::rtos::memory::memory_resource::internal_decrease_allocated_statistics ( std::size_t  bytes)
protectednoexceptinherited
Parameters
[in]bytesNumber of deallocated bytes.
Returns
Nothing.

Definition at line 490 of file os-memory.cpp.

492 {
493 // Update statistics.
494 // What is subtracted from allocated is added to free.
495 allocated_bytes_ -= bytes;
496 free_bytes_ += bytes;
497 --allocated_chunks_;
498 ++free_chunks_;
499 }

◆ internal_increase_allocated_statistics()

void os::rtos::memory::memory_resource::internal_increase_allocated_statistics ( std::size_t  bytes)
protectednoexceptinherited
Parameters
[in]bytesNumber of allocated bytes.
Returns
Nothing.

Definition at line 474 of file os-memory.cpp.

476 {
477 // Update statistics.
478 // What is subtracted from free is added to allocated.
479 allocated_bytes_ += bytes;
480 if (allocated_bytes_ > max_allocated_bytes_)
481 {
482 max_allocated_bytes_ = allocated_bytes_;
483 }
484 free_bytes_ -= bytes;
485 ++allocated_chunks_;
486 --free_chunks_;
487 }

Referenced by os::memory::block_pool::do_allocate(), and internal_align_().

◆ internal_reset_()

void os::memory::first_fit_top::internal_reset_ ( void  )
protectednoexcept
Parameters
None.

Definition at line 62 of file first-fit-top.cpp.

63 {
64 // Fill it with the first chunk.
65 chunk_t* chunk = reinterpret_cast<chunk_t*> (arena_addr_);
66 // Entire arena is a big free chunk.
67 chunk->size = total_bytes_;
68 // Mark the end of the list with a null pointer.
69 chunk->next = nullptr;
70
71 allocated_bytes_ = 0;
72 max_allocated_bytes_ = 0;
73 free_bytes_ = total_bytes_;
74 allocated_chunks_ = 0;
75 free_chunks_ = 1;
76
77 // Remember first chunk as list head.
78 free_list_ = chunk;
79 }

Referenced by internal_construct_().

◆ is_equal()

bool os::rtos::memory::memory_resource::is_equal ( memory_resource const &  other) const
inlinenoexceptinherited
Parameters
otherReference to another memory_resource.
Return values
trueThe memory_resource objects are equal.
falseThe memory_resource objects are not equal.

Compare *this for equality with other. Two memory_resources compare equal if and only if memory allocated from one memory_resource can be deallocated from the other and vice versa.

Exceptions
Throws nothing.
See also
do_is_equal();

Definition at line 1331 of file os-memory.h.

1332 {
1333 return do_is_equal (other);
1334 }
virtual bool do_is_equal(memory_resource const &other) const noexcept
Implementation of the equality comparator.

◆ max_allocated_bytes()

std::size_t os::rtos::memory::memory_resource::max_allocated_bytes ( void  )
inlineinherited
Parameters
None.
Returns
Number of bytes.

Definition at line 1408 of file os-memory.h.

1409 {
1410 return max_allocated_bytes_;
1411 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ max_size()

std::size_t os::rtos::memory::memory_resource::max_size ( void  ) const
inlinenoexceptinherited
Parameters
None.
Returns
Number of bytes or 0 if unknown.
See also
do_max_size();

Definition at line 1340 of file os-memory.h.

1341 {
1342 return do_max_size ();
1343 }
virtual std::size_t do_max_size(void) const noexcept
Implementation of the function to get max size.

◆ name()

const char * os::rtos::internal::object_named::name ( void  ) const
inlineinherited
Parameters
None.
Returns
A null terminated string.

All objects return a non-null string; anonymous objects return "-".

Note
Can be invoked from Interrupt Service Routines.

Definition at line 753 of file os-decls.h.

754 {
755 return name_;
756 }

Referenced by os::memory::lifo::lifo(), os::memory::malloc_memory_resource::malloc_memory_resource(), os::rtos::message_queue_typed< T, Allocator >::message_queue_typed(), os::memory::block_pool::~block_pool(), os::rtos::event_flags::~event_flags(), ~first_fit_top(), os::memory::lifo::~lifo(), os::memory::malloc_memory_resource::~malloc_memory_resource(), os::rtos::memory_pool::~memory_pool(), os::rtos::message_queue::~message_queue(), os::rtos::mutex::~mutex(), os::rtos::semaphore::~semaphore(), os::rtos::thread::~thread(), os::rtos::timer::~timer(), os::rtos::memory_pool::alloc(), os::rtos::thread::cancel(), os::rtos::event_flags::clear(), os::rtos::mutex::consistent(), os::rtos::thread::detach(), os::memory::new_delete_memory_resource::do_allocate(), os::memory::block_pool::do_allocate(), do_allocate(), os::memory::lifo::do_allocate(), os::memory::malloc_memory_resource::do_allocate(), os::rtos::thread::flags_raise(), os::rtos::memory_pool::free(), os::rtos::event_flags::get(), os::rtos::thread::interrupt(), os::rtos::thread::join(), os::rtos::thread::kill(), os::rtos::internal::terminated_threads_list::link(), os::rtos::mutex::lock(), os::rtos::memory::memory_resource::out_of_memory_handler(), os::rtos::semaphore::post(), os::rtos::mutex::prio_ceiling(), os::rtos::mutex::prio_ceiling(), os::rtos::thread::priority(), os::rtos::thread::priority_inherited(), os::rtos::event_flags::raise(), os::rtos::message_queue::receive(), os::rtos::memory_pool::reset(), os::rtos::message_queue::reset(), os::rtos::mutex::reset(), os::rtos::semaphore::reset(), os::rtos::thread::resume(), os::rtos::message_queue::send(), os::rtos::clock::sleep_for(), os::rtos::timer::start(), os::rtos::timer::stop(), os::rtos::memory_pool::timed_alloc(), os::rtos::mutex::timed_lock(), os::rtos::message_queue::timed_receive(), os::rtos::message_queue::timed_send(), os::rtos::semaphore::timed_wait(), os::rtos::event_flags::timed_wait(), os::rtos::memory::memory_resource::trace_print_statistics(), os::rtos::memory_pool::try_alloc(), os::rtos::mutex::try_lock(), os::rtos::message_queue::try_receive(), os::rtos::message_queue::try_send(), os::rtos::event_flags::try_wait(), os::rtos::semaphore::try_wait(), os::rtos::internal::ready_threads_list::unlink_head(), os::rtos::mutex::unlock(), os::rtos::event_flags::wait(), os::rtos::semaphore::wait(), and os::rtos::event_flags::waiting().

◆ out_of_memory_handler() [1/2]

out_of_memory_handler_t os::rtos::memory::memory_resource::out_of_memory_handler ( out_of_memory_handler_t  handler)
inlineinherited
Parameters
handlerPointer to new handler.
Returns
Pointer to old handler.
Standard compliance
Extension to standard.

Definition at line 1375 of file os-memory.h.

1376 {
1377 trace::printf ("%s(%p) @%p %s\n", __func__, handler, this, name ());
1378
1379 out_of_memory_handler_t tmp = out_of_memory_handler_;
1380 out_of_memory_handler_ = handler;
1381
1382 return tmp;
1383 }
void(*)(void) out_of_memory_handler_t
Type of out of memory handler.
Definition os-memory.h:141

References os::rtos::internal::object_named::name(), and os::trace::printf().

Referenced by os_startup_initialize_free_store().

◆ out_of_memory_handler() [2/2]

out_of_memory_handler_t os::rtos::memory::memory_resource::out_of_memory_handler ( void  )
inlineinherited
Parameters
None.
Returns
Pointer to existing handler.
Standard compliance
Extension to standard.

Definition at line 1390 of file os-memory.h.

1391 {
1392 return out_of_memory_handler_;
1393 }

◆ reset()

void os::rtos::memory::memory_resource::reset ( void  )
inlinenoexceptinherited
Parameters
None.
Returns
Nothing.
See also
do_reset();

Definition at line 1349 of file os-memory.h.

1350 {
1351 do_reset ();
1352 }
virtual void do_reset(void) noexcept
Implementation of the function to reset the memory manager.

◆ total_bytes()

std::size_t os::rtos::memory::memory_resource::total_bytes ( void  )
inlineinherited
Returns
Number of bytes.

Definition at line 1396 of file os-memory.h.

1397 {
1398 return total_bytes_;
1399 }

Referenced by os::rtos::memory::memory_resource::trace_print_statistics().

◆ trace_print_statistics()

void os::rtos::memory::memory_resource::trace_print_statistics ( void  )
inlineinherited
Parameters
None.
Returns
Nothing.

Definition at line 1444 of file os-memory.h.

1445 {
1446#if defined(TRACE)
1447 trace::printf ("Memory '%s' @%p: \n"
1448 "\ttotal: %u bytes, \n"
1449 "\tallocated: %u bytes in %u chunk(s), \n"
1450 "\tfree: %u bytes in %u chunk(s), \n"
1451 "\tmax: %u bytes, \n"
1452 "\tcalls: %u allocs, %u deallocs\n",
1453 name (), this, total_bytes (), allocated_bytes (),
1456 deallocations ());
1457#endif /* defined(TRACE) */
1458 }
std::size_t allocated_chunks(void)
Get the current number of allocated chunks.
Definition os-memory.h:1420
std::size_t allocated_bytes(void)
Get the current size of all allocated chunks.
Definition os-memory.h:1402
std::size_t max_allocated_bytes(void)
Get the maximum allocated size.
Definition os-memory.h:1408
std::size_t allocations(void)
Get the number of allocations.
Definition os-memory.h:1432
std::size_t total_bytes(void)
Get the total size of managed memory.
Definition os-memory.h:1396
std::size_t deallocations(void)
Get the number of deallocations.
Definition os-memory.h:1438
std::size_t free_chunks(void)
Get the current number of free chunks.
Definition os-memory.h:1426
std::size_t free_bytes(void)
Get the current size of all free chunks.
Definition os-memory.h:1414

References os::rtos::memory::memory_resource::allocated_bytes(), os::rtos::memory::memory_resource::allocated_chunks(), os::rtos::memory::memory_resource::allocations(), os::rtos::memory::memory_resource::deallocations(), os::rtos::memory::memory_resource::free_bytes(), os::rtos::memory::memory_resource::free_chunks(), os::rtos::memory::memory_resource::max_allocated_bytes(), os::rtos::internal::object_named::name(), os::trace::printf(), and os::rtos::memory::memory_resource::total_bytes().

Referenced by os_terminate_goodbye().

Member Data Documentation

◆ max_align

constexpr std::size_t os::rtos::memory::memory_resource::max_align = alignof (std::max_align_t)
staticconstexprinherited

Definition at line 166 of file os-memory.h.


The documentation for this class was generated from the following files: