µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
block-pool.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2016-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#if defined(OS_USE_OS_APP_CONFIG_H)
13#include <cmsis-plus/os-app-config.h>
14#endif
15
17#include <cmsis-plus/rtos/os.h>
18
19// ----------------------------------------------------------------------------
20
21#if defined(__clang__)
22#pragma clang diagnostic ignored "-Wc++98-compat"
23#endif
24
25// ----------------------------------------------------------------------------
26
27namespace os
28{
29 namespace memory
30 {
31
32 // ========================================================================
33
35 {
36 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
37 }
38
39#pragma GCC diagnostic push
40#if defined(__clang__)
41#pragma clang diagnostic ignored "-Wunused-parameter"
42#elif defined(__GNUC__)
43#pragma GCC diagnostic ignored "-Wunused-parameter"
44#endif
45
46 void*
47 block_pool::do_allocate (std::size_t bytes, std::size_t alignment)
48 {
49 assert (bytes <= block_size_bytes_);
50
51 if (first_ == nullptr)
52 {
53 return nullptr;
54 }
55
56 void* p = static_cast<void*> (first_);
57 first_ = *(static_cast<void**> (first_));
58
59#pragma GCC diagnostic push
60#if defined(__clang__)
61#pragma clang diagnostic ignored "-Wdeprecated-volatile"
62#elif defined(__GNUC__)
63#pragma GCC diagnostic ignored "-Wvolatile"
64#endif
65 ++count_;
66#pragma GCC diagnostic pop
67
68 // Update statistics.
69 // What is subtracted from free is added to allocated.
71
72#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
73 trace::printf ("%s(%u,%u)=%p,%u @%p %s\n", __func__, bytes, alignment, p,
74 block_size_bytes_, this, name ());
75#endif
76
77 return p;
78 }
79
80 void
81 block_pool::do_deallocate (void* addr, std::size_t bytes,
82 std::size_t alignment) noexcept
83 {
84#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
85 trace::printf ("%s(%p,%u,%u) @%p %s\n", __func__, addr, bytes, alignment,
86 this, name ());
87#endif
88
89#pragma GCC diagnostic push
90#if defined(__clang__)
91#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
92#endif
93 if ((addr < pool_addr_)
94 || (addr >= (static_cast<char*> (pool_addr_)
95 + blocks_ * block_size_bytes_)))
96 {
97 assert (false);
98 return;
99 }
100#pragma GCC diagnostic pop
101
102 // Perform a push_front() on the single linked LIFO list,
103 // i.e. add the block to the beginning of the list.
104
105 // Link previous list to this block; may be null, but it does
106 // not matter.
107 *(static_cast<void**> (addr)) = first_;
108
109 // Now this block is the first in the free list..
110 first_ = addr;
111
112#pragma GCC diagnostic push
113#if defined(__clang__)
114#pragma clang diagnostic ignored "-Wdeprecated-volatile"
115#elif defined(__GNUC__)
116#pragma GCC diagnostic ignored "-Wvolatile"
117#endif
118 --count_;
119#pragma GCC diagnostic pop
120
121 // Update statistics.
122 // What is subtracted from allocated is added to free.
123 internal_decrease_allocated_statistics (block_size_bytes_);
124 }
125
126#pragma GCC diagnostic push
127
128 std::size_t
129 block_pool::do_max_size (void) const noexcept
130 {
131 return block_size_bytes_ * blocks_;
132 }
133
134 void
135 block_pool::do_reset (void) noexcept
136 {
137#if defined(OS_TRACE_LIBCPP_MEMORY_RESOURCE)
138 trace::printf ("%s() @%p %s\n", __func__, this, name ());
139#endif
140 internal_reset_ ();
141 }
142
143 void
145 std::size_t block_size_bytes, void* addr,
146 std::size_t bytes) noexcept
147 {
148 blocks_ = blocks;
149
150 block_size_bytes_
151 = rtos::memory::align_size (block_size_bytes, alignof (void*));
152 assert (block_size_bytes_ >= sizeof (void*));
153
154 assert (addr != nullptr);
155 pool_addr_ = addr;
156
157 std::size_t align_sz = bytes;
158
159 void* res;
160 // Possibly adjust the last two parameters.
161 res = std::align (alignof (void*), blocks * block_size_bytes_,
162 pool_addr_, align_sz);
163
164 // std::align() will fail if it cannot fit the adjusted block size.
165 if (res != nullptr)
166 {
167 assert (res != nullptr);
168 }
169
170 // The extra assert is made redundant by std::align().
171 // assert(blocks * block_size_bytes_ <= align_sz);
172
173 total_bytes_ = blocks_ * block_size_bytes_;
174
175 internal_reset_ ();
176 }
177
178 void
180 {
181 // Construct a linked list of blocks. Store the pointer at
182 // the beginning of each block. Each block
183 // will hold the address of the next free block, or nullptr at the end.
184#pragma GCC diagnostic push
185#if defined(__clang__)
186#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
187#endif
188 char* p = static_cast<char*> (pool_addr_);
189 for (std::size_t i = 1; i < blocks_; ++i)
190 {
191 // Compute the address of the next block;
192 char* pn = p + block_size_bytes_;
193
194 // Make this block point to the next one.
195 *(static_cast<void**> (static_cast<void*> (p))) = pn;
196 // Advance pointer
197 p = pn;
198 }
199#pragma GCC diagnostic pop
200
201 // Mark end of list.
202 *(static_cast<void**> (static_cast<void*> (p))) = nullptr;
203
204 first_ = pool_addr_; // Pointer to first block.
205
206 count_ = 0; // No allocated blocks.
207
208 allocated_bytes_ = 0;
209 max_allocated_bytes_ = 0;
210 free_bytes_ = total_bytes_;
211 allocated_chunks_ = 0;
212 free_chunks_ = blocks_;
213 }
214
215 // ------------------------------------------------------------------------
216 } /* namespace memory */
217} /* namespace os */
218
219// ----------------------------------------------------------------------------
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_(std::size_t blocks, std::size_t block_size_bytes, void *addr, std::size_t bytes) noexcept
Internal function to construct the memory resource object instance.
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 object.
virtual ~block_pool() override
Destruct the memory resource object instance.
virtual void do_reset(void) noexcept override
Implementation of the function to reset the memory manager.
const char * name(void) const
Get object name.
Definition os-decls.h:753
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.
Definition trace.cpp:59
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
System namespace.
Single file µOS++ RTOS definitions.