µOS++ IIIe Reference  v6.3.15
“Perfekt ist nicht gut genug”
The third edition of µOS++, a POSIX inspired open source system, written in C++.
malloc.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 Liviu Ionescu.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #if defined(__ARM_EABI__) || defined(__DOXYGEN__)
29 
30 // ----------------------------------------------------------------------------
31 
32 #include <cmsis-plus/rtos/os.h>
34 
35 #include <malloc.h>
36 
37 // ----------------------------------------------------------------------------
38 
39 using namespace os;
40 
41 // ----------------------------------------------------------------------------
42 
54 // These library functions were modified to use the application
55 // memory resource and to be thread safe.
94 void*
95 malloc (size_t bytes)
96 {
98 
99  void* mem;
100  {
101  // ----- Begin of critical section --------------------------------------
103 
104  errno = 0;
105  mem = estd::pmr::get_default_resource ()->allocate (bytes);
106  if (mem == nullptr)
107  {
108  errno = ENOMEM;
109  }
110 
111 #if defined(OS_TRACE_LIBC_MALLOC)
112  trace::printf ("::%s(%d)=%p\n", __func__, bytes, mem);
113 #endif
114  // ----- End of critical section ----------------------------------------
115  }
116 
117  return mem;
118 }
119 
161 void*
162 calloc (size_t nelem, size_t elbytes)
163 {
165 
166  errno = 0;
167  if (nelem == 0 || elbytes == 0)
168  {
169  return nullptr;
170  }
171 
172  void* mem;
173  {
174  // ----- Begin of critical section --------------------------------------
176 
177  mem = estd::pmr::get_default_resource ()->allocate (nelem * elbytes);
178 
179 #if defined(OS_TRACE_LIBC_MALLOC)
180  trace::printf ("::%s(%u,%u)=%p\n", __func__, nelem, elbytes, mem);
181 #endif
182  // ----- End of critical section ----------------------------------------
183  }
184 
185  if (mem != nullptr)
186  {
187  memset (mem, 0, nelem * elbytes);
188  }
189  else
190  {
191  errno = ENOMEM;
192  }
193 
194  return mem;
195 }
196 
260 void*
261 realloc (void* ptr, size_t bytes)
262 {
264 
265  void* mem;
266 
267  {
268  // ----- Begin of critical section --------------------------------------
270 
271  errno = 0;
272  if (ptr == nullptr)
273  {
274  mem = estd::pmr::get_default_resource ()->allocate (bytes);
275 #if defined(OS_TRACE_LIBC_MALLOC)
276  trace::printf ("::%s(%p,%u)=%p\n", __func__, ptr, bytes, mem);
277 #endif
278  if (mem == nullptr)
279  {
280  errno = ENOMEM;
281  }
282  return mem;
283  }
284 
285  if (bytes == 0)
286  {
288 #if defined(OS_TRACE_LIBC_MALLOC)
289  trace::printf ("::%s(%p,%u)=0\n", __func__, ptr, bytes);
290 #endif
291  return nullptr;
292  }
293 
294 #if 0
295  /* TODO: There is chance to shrink the chunk if newly requested
296  * size is much small */
297  if (nano_malloc_usable_size (RCALL ptr) >= bytes)
298  return ptr;
299 #endif
300 
301  mem = estd::pmr::get_default_resource ()->allocate (bytes);
302  if (mem != nullptr)
303  {
304  memcpy (mem, ptr, bytes);
306  }
307  else
308  {
309  errno = ENOMEM;
310  }
311 
312 #if defined(OS_TRACE_LIBC_MALLOC)
313  trace::printf ("::%s(%p,%u)=%p", __func__, ptr, bytes, mem);
314 #endif
315  // ----- End of critical section ----------------------------------------
316  }
317 
318  return mem;
319 }
320 
351 void
352 free (void* ptr)
353 {
355 
356  if (ptr == nullptr)
357  {
358  return;
359  }
360 
361  // ----- Begin of critical section ------------------------------------------
363 
364 #if defined(OS_TRACE_LIBC_MALLOC)
365  trace::printf ("::%s(%p)\n", __func__, ptr);
366 #endif
367 
368  // Size unknown, pass 0.
370  // ----- End of critical section --------------------------------------------
371 }
372 
381 // ----------------------------------------------------------------------------
382 // Redirect impure functions to the implementation, to avoid including
383 // weird newlib functions.
388 void*
389 _malloc_r (struct _reent* impure __attribute__((unused)), size_t size)
390 {
391  return malloc (size);
392 }
393 
394 void*
395 _calloc_r (struct _reent* impure __attribute__((unused)), size_t n, size_t elem)
396 {
397  return calloc (n, elem);
398 }
399 
400 void
401 _free_r (struct _reent* impure __attribute__((unused)), void* ptr)
402 {
403  free (ptr);
404 }
405 
406 void*
407 _realloc_r (struct _reent* impure __attribute__((unused)), void* ptr,
408  size_t size)
409 {
410  return realloc (ptr, size);
411 }
412 
417 // ----------------------------------------------------------------------------
418 // Not really implemented, but present here to avoid including
419 // weird newlib functions.
424 #pragma GCC diagnostic push
425 #pragma GCC diagnostic ignored "-Waggregate-return"
426 
427 struct mallinfo
428 _mallinfo_r (struct _reent* impure __attribute__((unused)))
429 {
430  abort ();
431 }
432 
433 #pragma GCC diagnostic pop
434 
435 void
436 _malloc_stats_r (struct _reent* impure __attribute__((unused)))
437 {
438  abort ();
439 }
440 
441 size_t
442 _malloc_usable_size_r (struct _reent* reent __attribute__((unused)),
443  void* ptr __attribute__((unused)))
444 {
445  abort ();
446 }
447 
448 int
449 _mallopt_r (struct _reent* impure __attribute__((unused)),
450  int parameter_number __attribute__((unused)),
451  int parameter_value __attribute__((unused)))
452 {
453  abort ();
454 }
455 
456 void*
457 _memalign_r (struct _reent* impure __attribute__((unused)),
458  size_t align __attribute__((unused)),
459  size_t s __attribute__((unused)))
460 {
461  abort ();
462 }
463 
464 void*
465 _pvalloc_r (struct _reent* impure __attribute__((unused)),
466  size_t s __attribute__((unused)))
467 {
468  abort ();
469 }
470 
471 void*
472 _valloc_r (struct _reent* impure __attribute__((unused)),
473  size_t s __attribute__((unused)))
474 {
475  abort ();
476 }
477 
482 // ----------------------------------------------------------------------------
483 #endif /* defined(__ARM_EABI__) */
484 
memory_resource * get_default_resource(void) noexcept
Get the default application memory manager.
void * malloc(size_t bytes)
Allocate a memory block (non-initialised).
Definition: malloc.cpp:95
System namespace.
void free(void *ptr)
Free the allocated memory block.
Definition: malloc.cpp:352
Scheduler critical section RAII helper.
Definition: os-sched.h:170
void * calloc(size_t nelem, size_t elbytes)
Allocate an array of memory blocks (initialised to zero).
Definition: malloc.cpp:162
Single file µOS++ RTOS definitions.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition: trace.cpp:74
void * allocate(std::size_t bytes, std::size_t alignment=max_align)
Allocate a memory block.
Definition: os-memory.h:1285
void * realloc(void *ptr, size_t bytes)
Reallocate the memory block (non-initialised).
Definition: malloc.cpp:261
void deallocate(void *addr, std::size_t bytes, std::size_t alignment=max_align) noexcept
Deallocate the previously allocated memory block.
Definition: os-memory.h:1307
void abort(void)
Definition: exit.c:52
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition: os-sched.h:1091