mm.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /****************************************************************************
  2. * include/nuttx/mm/mm.h
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. #ifndef __INCLUDE_NUTTX_MM_MM_H
  21. #define __INCLUDE_NUTTX_MM_MM_H
  22. /****************************************************************************
  23. * Included Files
  24. ****************************************************************************/
  25. #include <nuttx/config.h>
  26. #include <sys/types.h>
  27. #include <stdbool.h>
  28. #include <string.h>
  29. #include <semaphore.h>
  30. /****************************************************************************
  31. * Pre-processor Definitions
  32. ****************************************************************************/
  33. /* Configuration ************************************************************/
  34. /* If the MCU has a small (16-bit) address capability, then we will use
  35. * a smaller chunk header that contains 16-bit size/offset information.
  36. * We will also use the smaller header on MCUs with wider addresses if
  37. * CONFIG_MM_SMALL is selected. This configuration is common with MCUs
  38. * that have a large FLASH space, but only a tiny internal SRAM.
  39. */
  40. #ifdef CONFIG_SMALL_MEMORY
  41. /* If the MCU has a small addressing capability, then force the smaller
  42. * chunk header.
  43. */
  44. # undef CONFIG_MM_SMALL
  45. # define CONFIG_MM_SMALL 1
  46. #endif
  47. /* Terminology:
  48. *
  49. * - Flat Build: In the flat build (CONFIG_BUILD_FLAT=y), there is only a
  50. * single heap access with the standard allocations (malloc/free). This
  51. * heap is referred to as the user heap. The kernel logic must
  52. * initialize this single heap at boot time.
  53. * - Protected build: In the protected build (CONFIG_BUILD_PROTECTED=y)
  54. * where an MPU is used to protect a region of otherwise flat memory,
  55. * there will be two allocators: One that allocates protected (kernel)
  56. * memory and one that allocates unprotected (user) memory. These are
  57. * referred to as the kernel and user heaps, respectively. Both must be
  58. * initialized by the kernel logic at boot time.
  59. * - Kernel Build: If the architecture has an MMU, then it may support the
  60. * kernel build (CONFIG_BUILD_KERNEL=y). In this configuration, there
  61. * is one kernel heap but multiple user heaps: One per task group.
  62. * However, in this case, the kernel need only be concerned about
  63. * initializing the single kernel heap here. User heaps will be created
  64. * as tasks are created.
  65. *
  66. * These special definitions are provided:
  67. *
  68. * MM_KERNEL_USRHEAP_INIT
  69. * Special kernel interfaces to the kernel user-heap are required
  70. * for heap initialization.
  71. * CONFIG_MM_KERNEL_HEAP
  72. * The configuration requires a kernel heap that must initialized
  73. * at boot-up.
  74. */
  75. #undef MM_KERNEL_USRHEAP_INIT
  76. #if !defined(CONFIG_BUILD_KERNEL) && defined(__KERNEL__)
  77. # define MM_KERNEL_USRHEAP_INIT 1
  78. #endif
  79. /* The kernel heap is never accessible from user code */
  80. #ifndef __KERNEL__
  81. # undef CONFIG_MM_KERNEL_HEAP
  82. #endif
  83. /* Chunk Header Definitions *************************************************/
  84. /* These definitions define the characteristics of allocator
  85. *
  86. * MM_MIN_SHIFT is used to define MM_MIN_CHUNK.
  87. * MM_MIN_CHUNK - is the smallest physical chunk that can be allocated. It
  88. * must be at least a large as sizeof(struct mm_freenode_s). Larger values
  89. * may improve performance slightly, but will waste memory due to
  90. * quantization losses.
  91. *
  92. * MM_MAX_SHIFT is used to define MM_MAX_CHUNK
  93. * MM_MAX_CHUNK is the largest, contiguous chunk of memory that can be
  94. * allocated. It can range from 16-bytes to 4Gb. Larger values of
  95. * MM_MAX_SHIFT can cause larger data structure sizes and, perhaps,
  96. * minor performance losses.
  97. */
  98. #if defined(CONFIG_MM_SMALL) && UINTPTR_MAX <= UINT32_MAX
  99. /* Two byte offsets; Pointers may be 2 or 4 bytes;
  100. * sizeof(struct mm_freenode_s) is 8 or 12 bytes.
  101. * REVISIT: We could do better on machines with 16-bit addressing.
  102. */
  103. # define MM_MIN_SHIFT B2C_SHIFT( 4) /* 16 bytes */
  104. # define MM_MAX_SHIFT B2C_SHIFT(15) /* 32 Kb */
  105. #elif defined(CONFIG_HAVE_LONG_LONG)
  106. /* Four byte offsets; Pointers may be 4 or 8 bytes
  107. * sizeof(struct mm_freenode_s) is 16 or 24 bytes.
  108. */
  109. # if UINTPTR_MAX <= UINT32_MAX
  110. # define MM_MIN_SHIFT B2C_SHIFT( 4) /* 16 bytes */
  111. # elif UINTPTR_MAX <= UINT64_MAX
  112. # define MM_MIN_SHIFT B2C_SHIFT( 5) /* 32 bytes */
  113. # endif
  114. # define MM_MAX_SHIFT B2C_SHIFT(22) /* 4 Mb */
  115. #else
  116. /* Four byte offsets; Pointers must be 4 bytes.
  117. * sizeof(struct mm_freenode_s) is 16 bytes.
  118. */
  119. # define MM_MIN_SHIFT B2C_SHIFT( 4) /* 16 bytes */
  120. # define MM_MAX_SHIFT B2C_SHIFT(22) /* 4 Mb */
  121. #endif
  122. /* All other definitions derive from these two */
  123. #define MM_MIN_CHUNK (1 << MM_MIN_SHIFT)
  124. #define MM_MAX_CHUNK (1 << MM_MAX_SHIFT)
  125. #define MM_NNODES (MM_MAX_SHIFT - MM_MIN_SHIFT + 1)
  126. #define MM_GRAN_MASK (MM_MIN_CHUNK-1)
  127. #define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK)
  128. #define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK)
  129. /* An allocated chunk is distinguished from a free chunk by bit 31 (or 15)
  130. * of the 'preceding' chunk size. If set, then this is an allocated chunk.
  131. */
  132. #ifdef CONFIG_MM_SMALL
  133. # define MM_ALLOC_BIT 0x8000
  134. #else
  135. # define MM_ALLOC_BIT 0x80000000
  136. #endif
  137. #define MM_IS_ALLOCATED(n) \
  138. ((int)((struct mm_allocnode_s*)(n)->preceding) < 0)
  139. /****************************************************************************
  140. * Public Types
  141. ****************************************************************************/
  142. /* Determines the size of the chunk size/offset type */
  143. #ifdef CONFIG_MM_SMALL
  144. typedef uint16_t mmsize_t;
  145. # define MMSIZE_MAX UINT16_MAX
  146. #else
  147. typedef uint32_t mmsize_t;
  148. # define MMSIZE_MAX UINT32_MAX
  149. #endif
  150. /* This describes an allocated chunk. An allocated chunk is
  151. * distinguished from a free chunk by bit 15/31 of the 'preceding' chunk
  152. * size. If set, then this is an allocated chunk.
  153. */
  154. struct mm_allocnode_s
  155. {
  156. mmsize_t size; /* Size of this chunk */
  157. mmsize_t preceding; /* Size of the preceding chunk */
  158. };
  159. /* What is the size of the allocnode? */
  160. #ifdef CONFIG_MM_SMALL
  161. # define SIZEOF_MM_ALLOCNODE B2C(4)
  162. #else
  163. # define SIZEOF_MM_ALLOCNODE B2C(8)
  164. #endif
  165. #define CHECK_ALLOCNODE_SIZE \
  166. DEBUGASSERT(sizeof(struct mm_allocnode_s) == SIZEOF_MM_ALLOCNODE)
  167. /* This describes a free chunk */
  168. struct mm_freenode_s
  169. {
  170. mmsize_t size; /* Size of this chunk */
  171. mmsize_t preceding; /* Size of the preceding chunk */
  172. FAR struct mm_freenode_s *flink; /* Supports a doubly linked list */
  173. FAR struct mm_freenode_s *blink;
  174. };
  175. struct mm_delaynode_s
  176. {
  177. struct mm_delaynode_s *flink;
  178. };
  179. /* What is the size of the freenode? */
  180. #define MM_PTR_SIZE sizeof(FAR struct mm_freenode_s *)
  181. #define SIZEOF_MM_FREENODE (SIZEOF_MM_ALLOCNODE + 2*MM_PTR_SIZE)
  182. #define CHECK_FREENODE_SIZE \
  183. DEBUGASSERT(sizeof(struct mm_freenode_s) == SIZEOF_MM_FREENODE)
  184. /* This describes one heap (possibly with multiple regions) */
  185. struct mm_heap_s
  186. {
  187. /* Mutually exclusive access to this data set is enforced with
  188. * the following un-named semaphore.
  189. */
  190. sem_t mm_semaphore;
  191. pid_t mm_holder;
  192. int mm_counts_held;
  193. /* This is the size of the heap provided to mm */
  194. size_t mm_heapsize;
  195. /* This is the first and last nodes of the heap */
  196. FAR struct mm_allocnode_s *mm_heapstart[CONFIG_MM_REGIONS];
  197. FAR struct mm_allocnode_s *mm_heapend[CONFIG_MM_REGIONS];
  198. #if CONFIG_MM_REGIONS > 1
  199. int mm_nregions;
  200. #endif
  201. /* All free nodes are maintained in a doubly linked list. This
  202. * array provides some hooks into the list at various points to
  203. * speed searches for free nodes.
  204. */
  205. struct mm_freenode_s mm_nodelist[MM_NNODES];
  206. /* Free delay list, for some situation can't do free immdiately */
  207. struct mm_delaynode_s *mm_delaylist;
  208. };
  209. /****************************************************************************
  210. * Public Data
  211. ****************************************************************************/
  212. #undef EXTERN
  213. #if defined(__cplusplus)
  214. #define EXTERN extern "C"
  215. extern "C"
  216. {
  217. #else
  218. #define EXTERN extern
  219. #endif
  220. /* User heap structure:
  221. *
  222. * - Flat build: In the FLAT build, the user heap structure is a globally
  223. * accessible variable.
  224. * - Protected build: The user heap structure is directly available only
  225. * in user space.
  226. * - Kernel build: There are multiple heaps, one per process. The heap
  227. * structure is associated with the address environment and there is
  228. * no global user heap structure.
  229. */
  230. /* In the kernel build, there a multiple user heaps; one for each task
  231. * group. In this build configuration, the user heap structure lies
  232. * in a reserved region at the beginning of the .bss/.data address
  233. * space (CONFIG_ARCH_DATA_VBASE). The size of that region is given by
  234. * ARCH_DATA_RESERVE_SIZE
  235. */
  236. /* In the protected mode, there are two heaps: A kernel heap and a single
  237. * user heap. In that case the user heap structure lies in the user space
  238. * (with a reference in the userspace interface).
  239. */
  240. #if defined(CONFIG_BUILD_FLAT) || !defined(__KERNEL__)
  241. /* Otherwise, the user heap data structures are in common .bss */
  242. EXTERN struct mm_heap_s g_mmheap;
  243. #endif
  244. #ifdef CONFIG_MM_KERNEL_HEAP
  245. /* This is the kernel heap */
  246. EXTERN struct mm_heap_s g_kmmheap;
  247. #endif
  248. /****************************************************************************
  249. * Public Function Prototypes
  250. ****************************************************************************/
  251. /* Functions contained in mm_initialize.c ***********************************/
  252. void mm_initialize(FAR struct mm_heap_s *heap, FAR void *heap_start,
  253. size_t heap_size);
  254. void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart,
  255. size_t heapsize);
  256. /* Functions contained in umm_initialize.c **********************************/
  257. void umm_initialize(FAR void *heap_start, size_t heap_size);
  258. /* Functions contained in kmm_initialize.c **********************************/
  259. #ifdef CONFIG_MM_KERNEL_HEAP
  260. void kmm_initialize(FAR void *heap_start, size_t heap_size);
  261. #endif
  262. /* Functions contained in umm_addregion.c ***********************************/
  263. void umm_addregion(FAR void *heapstart, size_t heapsize);
  264. /* Functions contained in kmm_addregion.c ***********************************/
  265. #ifdef CONFIG_MM_KERNEL_HEAP
  266. void kmm_addregion(FAR void *heapstart, size_t heapsize);
  267. #endif
  268. /* Functions contained in mm_sem.c ******************************************/
  269. void mm_seminitialize(FAR struct mm_heap_s *heap);
  270. void mm_takesemaphore(FAR struct mm_heap_s *heap);
  271. int mm_trysemaphore(FAR struct mm_heap_s *heap);
  272. void mm_givesemaphore(FAR struct mm_heap_s *heap);
  273. /* Functions contained in umm_sem.c *****************************************/
  274. int umm_trysemaphore(void);
  275. void umm_givesemaphore(void);
  276. /* Functions contained in kmm_sem.c *****************************************/
  277. #ifdef CONFIG_MM_KERNEL_HEAP
  278. int kmm_trysemaphore(void);
  279. void kmm_givesemaphore(void);
  280. #endif
  281. /* Functions contained in mm_malloc.c ***************************************/
  282. FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size);
  283. /* Functions contained in kmm_malloc.c **************************************/
  284. #ifdef CONFIG_MM_KERNEL_HEAP
  285. FAR void *kmm_malloc(size_t size);
  286. #endif
  287. /* Functions contained in mm_free.c *****************************************/
  288. void mm_free(FAR struct mm_heap_s *heap, FAR void *mem);
  289. /* Functions contained in kmm_free.c ****************************************/
  290. #ifdef CONFIG_MM_KERNEL_HEAP
  291. void kmm_free(FAR void *mem);
  292. #endif
  293. /* Functions contained in mm_realloc.c **************************************/
  294. FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
  295. size_t size);
  296. /* Functions contained in kmm_realloc.c *************************************/
  297. #ifdef CONFIG_MM_KERNEL_HEAP
  298. FAR void *kmm_realloc(FAR void *oldmem, size_t newsize);
  299. #endif
  300. /* Functions contained in mm_calloc.c ***************************************/
  301. FAR void *mm_calloc(FAR struct mm_heap_s *heap, size_t n, size_t elem_size);
  302. /* Functions contained in kmm_calloc.c **************************************/
  303. #ifdef CONFIG_MM_KERNEL_HEAP
  304. FAR void *kmm_calloc(size_t n, size_t elem_size);
  305. #endif
  306. /* Functions contained in mm_zalloc.c ***************************************/
  307. FAR void *mm_zalloc(FAR struct mm_heap_s *heap, size_t size);
  308. /* Functions contained in kmm_zalloc.c **************************************/
  309. #ifdef CONFIG_MM_KERNEL_HEAP
  310. FAR void *kmm_zalloc(size_t size);
  311. #endif
  312. /* Functions contained in mm_memalign.c *************************************/
  313. FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
  314. size_t size);
  315. /* Functions contained in kmm_memalign.c ************************************/
  316. #ifdef CONFIG_MM_KERNEL_HEAP
  317. FAR void *kmm_memalign(size_t alignment, size_t size);
  318. #endif
  319. /* Functions contained in mm_heapmember.c ***********************************/
  320. bool mm_heapmember(FAR struct mm_heap_s *heap, FAR void *mem);
  321. /* Functions contained in mm_uheapmember.c **********************************/
  322. bool umm_heapmember(FAR void *mem);
  323. /* Functions contained in kmm_heapmember.c **********************************/
  324. #ifdef CONFIG_MM_KERNEL_HEAP
  325. bool kmm_heapmember(FAR void *mem);
  326. #endif
  327. /* Functions contained in mm_brkaddr.c **************************************/
  328. FAR void *mm_brkaddr(FAR struct mm_heap_s *heap, int region);
  329. /* Functions contained in umm_brkaddr.c *************************************/
  330. FAR void *umm_brkaddr(int region);
  331. /* Functions contained in kmm_brkaddr.c *************************************/
  332. #ifdef CONFIG_MM_KERNEL_HEAP
  333. FAR void *kmm_brkaddr(int region);
  334. #endif
  335. /* Functions contained in mm_sbrk.c *****************************************/
  336. #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC)
  337. FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
  338. uintptr_t maxbreak);
  339. #endif
  340. /* Functions contained in kmm_sbrk.c ****************************************/
  341. #if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_ARCH_ADDRENV) && \
  342. defined(CONFIG_MM_PGALLOC)
  343. FAR void *kmm_sbrk(intptr_t incr);
  344. #endif
  345. /* Functions contained in mm_extend.c ***************************************/
  346. void mm_extend(FAR struct mm_heap_s *heap, FAR void *mem, size_t size,
  347. int region);
  348. /* Functions contained in umm_extend.c **************************************/
  349. void umm_extend(FAR void *mem, size_t size, int region);
  350. /* Functions contained in kmm_extend.c **************************************/
  351. #ifdef CONFIG_MM_KERNEL_HEAP
  352. void kmm_extend(FAR void *mem, size_t size, int region);
  353. #endif
  354. /* Functions contained in mm_mallinfo.c *************************************/
  355. struct mallinfo; /* Forward reference */
  356. int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info);
  357. /* Functions contained in kmm_mallinfo.c ************************************/
  358. #ifdef CONFIG_MM_KERNEL_HEAP
  359. struct mallinfo kmm_mallinfo(void);
  360. #endif
  361. /* Functions contained in mm_shrinkchunk.c **********************************/
  362. void mm_shrinkchunk(FAR struct mm_heap_s *heap,
  363. FAR struct mm_allocnode_s *node, size_t size);
  364. /* Functions contained in mm_addfreechunk.c *********************************/
  365. void mm_addfreechunk(FAR struct mm_heap_s *heap,
  366. FAR struct mm_freenode_s *node);
  367. /* Functions contained in mm_size2ndx.c.c ***********************************/
  368. int mm_size2ndx(size_t size);
  369. #undef EXTERN
  370. #ifdef __cplusplus
  371. }
  372. #endif
  373. #endif /* __INCLUDE_NUTTX_MM_MM_H */