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