dataMemory.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * This file is part of the PikaPython project.
  3. * http://github.com/pikastech/pikapython
  4. *
  5. * MIT License
  6. *
  7. * Copyright (c) 2021 lyon liang6516@outlook.com
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. */
  27. #define __DATA_MEMORY_CLASS_IMPLEMENT__
  28. #include "dataMemory.h"
  29. #include "PikaPlatform.h"
  30. volatile PikaMemInfo g_PikaMemInfo = {0};
  31. void* pikaMalloc(uint32_t size) {
  32. /* pika memory lock */
  33. if (0 != pika_is_locked_pikaMemory()) {
  34. pika_platform_wait();
  35. }
  36. //! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment
  37. #if PIKA_ARG_ALIGN_ENABLE
  38. /* force alignment to avoid unaligned access */
  39. size = mem_align(size);
  40. #endif
  41. g_PikaMemInfo.heapUsed += size;
  42. if (g_PikaMemInfo.heapUsedMax < g_PikaMemInfo.heapUsed) {
  43. g_PikaMemInfo.heapUsedMax = g_PikaMemInfo.heapUsed;
  44. }
  45. pika_platform_disable_irq_handle();
  46. void* mem = pika_user_malloc(size);
  47. pika_platform_enable_irq_handle();
  48. if (NULL == mem) {
  49. pika_platform_printf(
  50. "Error: No heap space! Please reset the device.\r\n");
  51. while (1) {
  52. }
  53. }
  54. return mem;
  55. }
  56. void pikaFree(void* mem, uint32_t size) {
  57. pika_assert(mem != NULL);
  58. if (0 != pika_is_locked_pikaMemory()) {
  59. pika_platform_wait();
  60. }
  61. //! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment
  62. #if PIKA_ARG_ALIGN_ENABLE
  63. /* force alignment to avoid unaligned access */
  64. size = mem_align(size);
  65. #endif
  66. pika_platform_disable_irq_handle();
  67. pika_user_free(mem, size);
  68. pika_platform_enable_irq_handle();
  69. g_PikaMemInfo.heapUsed -= size;
  70. }
  71. uint32_t pikaMemNow(void) {
  72. return g_PikaMemInfo.heapUsed;
  73. // return 0;
  74. }
  75. uint32_t pikaMemMax(void) {
  76. return g_PikaMemInfo.heapUsedMax;
  77. }
  78. void pikaMemMaxReset(void) {
  79. g_PikaMemInfo.heapUsedMax = 0;
  80. }
  81. #if PIKA_POOL_ENABLE
  82. uint32_t pool_getBlockIndex_byMemSize(Pool* pool, uint32_t size) {
  83. if (0 == size) {
  84. return 0;
  85. }
  86. return (size - 1) / pool->aline + 1;
  87. }
  88. uint32_t pool_aline(Pool* pool, uint32_t size) {
  89. return pool_getBlockIndex_byMemSize(pool, size) * pool->aline;
  90. }
  91. Pool pool_init(uint32_t size, uint8_t aline) {
  92. Pool pool;
  93. pool.aline = aline;
  94. uint32_t block_size = pool_getBlockIndex_byMemSize(&pool, size);
  95. pool.size = pool_aline(&pool, size);
  96. pool.bitmap = bitmap_init(block_size);
  97. pool.mem = pika_platform_malloc(pool_aline(&pool, pool.size));
  98. pool.first_free_block = 0;
  99. pool.purl_free_block_start = 0;
  100. pool.inited = pika_true;
  101. return pool;
  102. }
  103. void pool_deinit(Pool* pool) {
  104. pika_platform_free(pool->mem);
  105. pool->mem = NULL;
  106. bitmap_deinit(pool->bitmap);
  107. }
  108. void* pool_getBytes_byBlockIndex(Pool* pool, uint32_t block_index) {
  109. return pool->mem + block_index * pool->aline;
  110. }
  111. uint32_t pool_getBlockIndex_byMem(Pool* pool, void* mem) {
  112. uint32_t mem_size = (uintptr_t)mem - (uintptr_t)pool->mem;
  113. return pool_getBlockIndex_byMemSize(pool, mem_size);
  114. }
  115. void pool_printBlocks(Pool* pool, uint32_t size_min, uint32_t size_max) {
  116. uint32_t block_index_min = pool_getBlockIndex_byMemSize(pool, size_min);
  117. uint32_t block_index_max = pool_getBlockIndex_byMemSize(pool, size_max);
  118. pika_platform_printf("[bitmap]\r\n");
  119. uint8_t is_end = 0;
  120. for (uint32_t i = block_index_min; i < block_index_max; i += 16) {
  121. if (is_end) {
  122. break;
  123. }
  124. pika_platform_printf("0x%x\t: 0x%d", i * pool->aline,
  125. (i + 15) * pool->aline);
  126. for (uint32_t j = i; j < i + 16; j += 4) {
  127. if (is_end) {
  128. break;
  129. }
  130. for (uint32_t k = j; k < j + 4; k++) {
  131. if (k >= block_index_max) {
  132. is_end = 1;
  133. break;
  134. }
  135. pika_platform_printf("%d", bitmap_get(pool->bitmap, k));
  136. }
  137. pika_platform_printf(" ");
  138. }
  139. pika_platform_printf("\r\n");
  140. }
  141. }
  142. void* pool_malloc(Pool* pool, uint32_t size) {
  143. uint32_t block_index_max = pool_getBlockIndex_byMemSize(pool, pool->size);
  144. uint32_t block_num_need = pool_getBlockIndex_byMemSize(pool, size);
  145. uint32_t block_num_found = 0;
  146. uint8_t found_first_free = 0;
  147. uint32_t block_index;
  148. /* high speed malloc */
  149. block_index = pool->purl_free_block_start + block_num_need - 1;
  150. if (block_index < block_index_max) {
  151. goto found;
  152. }
  153. /* low speed malloc */
  154. for (block_index = pool->first_free_block;
  155. block_index < pool->purl_free_block_start; block_index++) {
  156. /* 8 bit is not free */
  157. uint8_t bitmap_byte = bitmap_getByte(pool->bitmap, block_index);
  158. if (0xFF == bitmap_byte) {
  159. block_index = 8 * (block_index / 8) + 7;
  160. block_num_found = 0;
  161. continue;
  162. }
  163. /* found a free block */
  164. if (0 == bitmap_get(pool->bitmap, block_index)) {
  165. /* save the first free */
  166. if (!found_first_free) {
  167. pool->first_free_block = block_index;
  168. found_first_free = 1;
  169. }
  170. block_num_found++;
  171. } else {
  172. /* a used block appeared, find again */
  173. block_num_found = 0;
  174. }
  175. /* found all request blocks */
  176. if (block_num_found >= block_num_need) {
  177. goto found;
  178. }
  179. }
  180. /* malloc for purl free blocks */
  181. block_index = pool->purl_free_block_start + block_num_need - 1;
  182. if (block_index < block_index_max) {
  183. goto found;
  184. }
  185. /* no found */
  186. return NULL;
  187. found:
  188. /* set 1 for found blocks */
  189. for (uint32_t i = 0; i < block_num_need; i++) {
  190. bitmap_set(pool->bitmap, block_index - i, 1);
  191. }
  192. /* save last used block */
  193. if (block_index >= pool->purl_free_block_start) {
  194. pool->purl_free_block_start = block_index + 1;
  195. }
  196. /* return mem by block index */
  197. return pool_getBytes_byBlockIndex(pool, block_index - block_num_need + 1);
  198. }
  199. void pool_free(Pool* pool, void* mem, uint32_t size) {
  200. uint32_t block_num = pool_getBlockIndex_byMemSize(pool, size);
  201. uint32_t block_index = pool_getBlockIndex_byMem(pool, mem);
  202. for (uint32_t i = 0; i < block_num; i++) {
  203. bitmap_set(pool->bitmap, block_index + i, 0);
  204. }
  205. /* save min free block index to add speed */
  206. if (block_index < pool->first_free_block) {
  207. pool->first_free_block = block_index;
  208. }
  209. /* save last free block index to add speed */
  210. uint32_t block_end = block_index + block_num - 1;
  211. if (block_end == pool->purl_free_block_start - 1) {
  212. uint32_t first_pure_free_block = block_index;
  213. /* back to first used block */
  214. if (0 != first_pure_free_block) {
  215. while (0 == bitmap_get(pool->bitmap, first_pure_free_block - 1)) {
  216. first_pure_free_block--;
  217. if (0 == first_pure_free_block) {
  218. break;
  219. }
  220. }
  221. }
  222. pool->purl_free_block_start = first_pure_free_block;
  223. }
  224. return;
  225. }
  226. BitMap bitmap_init(uint32_t size) {
  227. BitMap mem_bit_map =
  228. (BitMap)pika_platform_malloc(((size - 1) / 8 + 1) * sizeof(char));
  229. if (mem_bit_map == NULL) {
  230. return NULL;
  231. }
  232. uint32_t size_mem_bit_map = (size - 1) / 8 + 1;
  233. pika_platform_memset(mem_bit_map, 0x0, size_mem_bit_map);
  234. return mem_bit_map;
  235. }
  236. void bitmap_set(BitMap bitmap, uint32_t index, uint8_t bit) {
  237. uint32_t index_byte = index / 8;
  238. uint8_t index_bit = index % 8;
  239. uint8_t x = (0x1 << index_bit);
  240. /* set 1 */
  241. if (bit) {
  242. bitmap[index_byte] |= x;
  243. return;
  244. }
  245. /* set 0 */
  246. bitmap[index_byte] &= ~x;
  247. return;
  248. }
  249. uint8_t bitmap_getByte(BitMap bitmap, uint32_t index) {
  250. uint32_t index_byte = (index) / 8;
  251. uint8_t byte;
  252. byte = bitmap[index_byte];
  253. return byte;
  254. }
  255. uint8_t bitmap_get(BitMap bitmap, uint32_t index) {
  256. uint32_t index_byte = (index) / 8;
  257. uint8_t index_bit = (index) % 8;
  258. uint8_t x = (0x1 << index_bit);
  259. uint8_t bit;
  260. bit = bitmap[index_byte] & x;
  261. return bit > 0 ? 1 : 0;
  262. }
  263. void bitmap_deinit(BitMap bitmap) {
  264. pika_platform_free(bitmap);
  265. }
  266. Pool pikaPool = {0};
  267. void* pika_user_malloc(size_t size) {
  268. return pool_malloc(&pikaPool, size);
  269. }
  270. void pika_user_free(void* ptrm, size_t size) {
  271. pool_free(&pikaPool, ptrm, size);
  272. }
  273. #endif
  274. void mem_pool_init(void) {
  275. #if PIKA_POOL_ENABLE
  276. if (!pikaPool.inited) {
  277. pikaPool = pool_init(PIKA_POOL_SIZE, PIKA_POOL_ALIGN);
  278. }
  279. #endif
  280. }
  281. void _mem_cache_deinit(void) {
  282. #if PIKA_ARG_CACHE_ENABLE
  283. while (g_PikaMemInfo.cache_pool_top) {
  284. pika_user_free(
  285. g_PikaMemInfo.cache_pool[g_PikaMemInfo.cache_pool_top - 1], 0);
  286. g_PikaMemInfo.cache_pool_top--;
  287. }
  288. #endif
  289. }
  290. void mem_pool_deinit(void) {
  291. _mem_cache_deinit();
  292. #if PIKA_POOL_ENABLE
  293. pool_deinit(&pikaPool);
  294. #endif
  295. }