heap_caps_linux.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdbool.h>
  7. #include <malloc.h>
  8. #include <string.h>
  9. #include "esp_attr.h"
  10. #include "esp_heap_caps.h"
  11. static esp_alloc_failed_hook_t alloc_failed_callback;
  12. static const uint32_t MAGIC_HEAP_SIZE = UINT32_MAX;
  13. esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback)
  14. {
  15. if (callback == NULL) {
  16. return ESP_ERR_INVALID_ARG;
  17. }
  18. alloc_failed_callback = callback;
  19. return ESP_OK;
  20. }
  21. static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const char *function_name)
  22. {
  23. if (alloc_failed_callback) {
  24. alloc_failed_callback(requested_size, caps, function_name);
  25. }
  26. #ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
  27. esp_system_abort("Memory allocation failed");
  28. #endif
  29. }
  30. /*
  31. Routine to allocate a bit of memory with certain capabilities. caps is a bitfield of MALLOC_CAP_* bits.
  32. */
  33. static void *heap_caps_malloc_base( size_t size, uint32_t caps)
  34. {
  35. void *ptr = malloc(size);
  36. if (!ptr && size > 0) {
  37. heap_caps_alloc_failed(size, caps, __func__);
  38. }
  39. return ptr;
  40. }
  41. void *heap_caps_malloc( size_t size, uint32_t caps)
  42. {
  43. return heap_caps_malloc_base(size, caps);
  44. }
  45. void heap_caps_malloc_extmem_enable(size_t limit)
  46. {
  47. (void)limit;
  48. // No distinction between external vs internal memory on linux
  49. }
  50. void *heap_caps_malloc_default( size_t size )
  51. {
  52. return heap_caps_malloc_base(size, MALLOC_CAP_DEFAULT);
  53. }
  54. void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
  55. {
  56. return heap_caps_malloc(size, MALLOC_CAP_DEFAULT);
  57. }
  58. static void *heap_caps_realloc_base( void *ptr, size_t size, uint32_t caps)
  59. {
  60. ptr = realloc(ptr, caps);
  61. if (ptr == NULL && size > 0) {
  62. heap_caps_alloc_failed(size, caps, __func__);
  63. }
  64. return ptr;
  65. }
  66. void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps)
  67. {
  68. return heap_caps_realloc_base(ptr, size, caps);
  69. }
  70. void *heap_caps_realloc_default( void *ptr, size_t size )
  71. {
  72. return heap_caps_realloc_base(ptr, size, MALLOC_CAP_DEFAULT);
  73. }
  74. void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... )
  75. {
  76. return heap_caps_realloc_base(ptr, size, MALLOC_CAP_DEFAULT);
  77. }
  78. void heap_caps_free( void *ptr)
  79. {
  80. free(ptr);
  81. }
  82. static void *heap_caps_calloc_base( size_t n, size_t size, uint32_t caps)
  83. {
  84. size_t size_bytes;
  85. if (__builtin_mul_overflow(n, size, &size_bytes)) {
  86. return NULL;
  87. }
  88. return calloc(n, size);
  89. }
  90. void *heap_caps_calloc( size_t n, size_t size, uint32_t caps)
  91. {
  92. void *ptr = heap_caps_calloc_base(n, size, caps);
  93. if (!ptr && size > 0) {
  94. heap_caps_alloc_failed(size, caps, __func__);
  95. }
  96. return ptr;
  97. }
  98. void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... )
  99. {
  100. return heap_caps_calloc_base(n, size, MALLOC_CAP_DEFAULT);
  101. }
  102. size_t heap_caps_get_total_size(uint32_t caps)
  103. {
  104. return MAGIC_HEAP_SIZE;
  105. }
  106. size_t heap_caps_get_free_size( uint32_t caps )
  107. {
  108. return MAGIC_HEAP_SIZE;
  109. }
  110. size_t heap_caps_get_minimum_free_size( uint32_t caps )
  111. {
  112. return MAGIC_HEAP_SIZE;
  113. }
  114. size_t heap_caps_get_largest_free_block( uint32_t caps )
  115. {
  116. return MAGIC_HEAP_SIZE;
  117. }
  118. void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps )
  119. {
  120. bzero(info, sizeof(multi_heap_info_t));
  121. }
  122. void heap_caps_print_heap_info( uint32_t caps )
  123. {
  124. printf("No heap summary available when building for the linux target");
  125. }
  126. bool heap_caps_check_integrity(uint32_t caps, bool print_errors)
  127. {
  128. return true;
  129. }
  130. bool heap_caps_check_integrity_all(bool print_errors)
  131. {
  132. return heap_caps_check_integrity(MALLOC_CAP_INVALID, print_errors);
  133. }
  134. bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors)
  135. {
  136. return true;
  137. }
  138. void heap_caps_dump(uint32_t caps)
  139. {
  140. }
  141. void heap_caps_dump_all(void)
  142. {
  143. heap_caps_dump(MALLOC_CAP_INVALID);
  144. }
  145. size_t heap_caps_get_allocated_size( void *ptr )
  146. {
  147. return 0;
  148. }
  149. void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps)
  150. {
  151. void *ptr = aligned_alloc(alignment, size);
  152. if (!ptr && size > 0) {
  153. heap_caps_alloc_failed(size, caps, __func__);
  154. }
  155. return ptr;
  156. }
  157. void heap_caps_aligned_free(void *ptr)
  158. {
  159. heap_caps_free(ptr);
  160. }
  161. void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps)
  162. {
  163. size_t size_bytes;
  164. if (__builtin_mul_overflow(n, size, &size_bytes)) {
  165. return NULL;
  166. }
  167. void *ptr = heap_caps_aligned_alloc(alignment, size_bytes, caps);
  168. if (ptr != NULL) {
  169. memset(ptr, 0, size_bytes);
  170. }
  171. return ptr;
  172. }