123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- /****************************************************************************
- * include/nuttx/mm/mm.h
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
- #ifndef __INCLUDE_NUTTX_MM_MM_H
- #define __INCLUDE_NUTTX_MM_MM_H
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #include <sys/types.h>
- #include <stdbool.h>
- #include <string.h>
- #include <semaphore.h>
- /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
- /* Configuration ************************************************************/
- /* If the MCU has a small (16-bit) address capability, then we will use
- * a smaller chunk header that contains 16-bit size/offset information.
- * We will also use the smaller header on MCUs with wider addresses if
- * CONFIG_MM_SMALL is selected. This configuration is common with MCUs
- * that have a large FLASH space, but only a tiny internal SRAM.
- */
- #ifdef CONFIG_SMALL_MEMORY
- /* If the MCU has a small addressing capability, then force the smaller
- * chunk header.
- */
- # undef CONFIG_MM_SMALL
- # define CONFIG_MM_SMALL 1
- #endif
- /* Terminology:
- *
- * - Flat Build: In the flat build (CONFIG_BUILD_FLAT=y), there is only a
- * single heap access with the standard allocations (malloc/free). This
- * heap is referred to as the user heap. The kernel logic must
- * initialize this single heap at boot time.
- * - Protected build: In the protected build (CONFIG_BUILD_PROTECTED=y)
- * where an MPU is used to protect a region of otherwise flat memory,
- * there will be two allocators: One that allocates protected (kernel)
- * memory and one that allocates unprotected (user) memory. These are
- * referred to as the kernel and user heaps, respectively. Both must be
- * initialized by the kernel logic at boot time.
- * - Kernel Build: If the architecture has an MMU, then it may support the
- * kernel build (CONFIG_BUILD_KERNEL=y). In this configuration, there
- * is one kernel heap but multiple user heaps: One per task group.
- * However, in this case, the kernel need only be concerned about
- * initializing the single kernel heap here. User heaps will be created
- * as tasks are created.
- *
- * These special definitions are provided:
- *
- * MM_KERNEL_USRHEAP_INIT
- * Special kernel interfaces to the kernel user-heap are required
- * for heap initialization.
- * CONFIG_MM_KERNEL_HEAP
- * The configuration requires a kernel heap that must initialized
- * at boot-up.
- */
- #undef MM_KERNEL_USRHEAP_INIT
- #if !defined(CONFIG_BUILD_KERNEL) && defined(__KERNEL__)
- # define MM_KERNEL_USRHEAP_INIT 1
- #endif
- /* The kernel heap is never accessible from user code */
- #ifndef __KERNEL__
- # undef CONFIG_MM_KERNEL_HEAP
- #endif
- /* Chunk Header Definitions *************************************************/
- /* These definitions define the characteristics of allocator
- *
- * MM_MIN_SHIFT is used to define MM_MIN_CHUNK.
- * MM_MIN_CHUNK - is the smallest physical chunk that can be allocated. It
- * must be at least a large as sizeof(struct mm_freenode_s). Larger values
- * may improve performance slightly, but will waste memory due to
- * quantization losses.
- *
- * MM_MAX_SHIFT is used to define MM_MAX_CHUNK
- * MM_MAX_CHUNK is the largest, contiguous chunk of memory that can be
- * allocated. It can range from 16-bytes to 4Gb. Larger values of
- * MM_MAX_SHIFT can cause larger data structure sizes and, perhaps,
- * minor performance losses.
- */
- #if defined(CONFIG_MM_SMALL) && UINTPTR_MAX <= UINT32_MAX
- /* Two byte offsets; Pointers may be 2 or 4 bytes;
- * sizeof(struct mm_freenode_s) is 8 or 12 bytes.
- * REVISIT: We could do better on machines with 16-bit addressing.
- */
- # define MM_MIN_SHIFT B2C_SHIFT( 4) /* 16 bytes */
- # define MM_MAX_SHIFT B2C_SHIFT(15) /* 32 Kb */
- #elif defined(CONFIG_HAVE_LONG_LONG)
- /* Four byte offsets; Pointers may be 4 or 8 bytes
- * sizeof(struct mm_freenode_s) is 16 or 24 bytes.
- */
- # if UINTPTR_MAX <= UINT32_MAX
- # define MM_MIN_SHIFT B2C_SHIFT( 4) /* 16 bytes */
- # elif UINTPTR_MAX <= UINT64_MAX
- # define MM_MIN_SHIFT B2C_SHIFT( 5) /* 32 bytes */
- # endif
- # define MM_MAX_SHIFT B2C_SHIFT(22) /* 4 Mb */
- #else
- /* Four byte offsets; Pointers must be 4 bytes.
- * sizeof(struct mm_freenode_s) is 16 bytes.
- */
- # define MM_MIN_SHIFT B2C_SHIFT( 4) /* 16 bytes */
- # define MM_MAX_SHIFT B2C_SHIFT(22) /* 4 Mb */
- #endif
- /* All other definitions derive from these two */
- #define MM_MIN_CHUNK (1 << MM_MIN_SHIFT)
- #define MM_MAX_CHUNK (1 << MM_MAX_SHIFT)
- #define MM_NNODES (MM_MAX_SHIFT - MM_MIN_SHIFT + 1)
- #define MM_GRAN_MASK (MM_MIN_CHUNK-1)
- #define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK)
- #define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK)
- /* An allocated chunk is distinguished from a free chunk by bit 31 (or 15)
- * of the 'preceding' chunk size. If set, then this is an allocated chunk.
- */
- #ifdef CONFIG_MM_SMALL
- # define MM_ALLOC_BIT 0x8000
- #else
- # define MM_ALLOC_BIT 0x80000000
- #endif
- #define MM_IS_ALLOCATED(n) \
- ((int)((struct mm_allocnode_s*)(n)->preceding) < 0)
- /****************************************************************************
- * Public Types
- ****************************************************************************/
- /* Determines the size of the chunk size/offset type */
- #ifdef CONFIG_MM_SMALL
- typedef uint16_t mmsize_t;
- # define MMSIZE_MAX UINT16_MAX
- #else
- typedef uint32_t mmsize_t;
- # define MMSIZE_MAX UINT32_MAX
- #endif
- /* This describes an allocated chunk. An allocated chunk is
- * distinguished from a free chunk by bit 15/31 of the 'preceding' chunk
- * size. If set, then this is an allocated chunk.
- */
- struct mm_allocnode_s
- {
- mmsize_t size; /* Size of this chunk */
- mmsize_t preceding; /* Size of the preceding chunk */
- };
- /* What is the size of the allocnode? */
- #ifdef CONFIG_MM_SMALL
- # define SIZEOF_MM_ALLOCNODE B2C(4)
- #else
- # define SIZEOF_MM_ALLOCNODE B2C(8)
- #endif
- #define CHECK_ALLOCNODE_SIZE \
- DEBUGASSERT(sizeof(struct mm_allocnode_s) == SIZEOF_MM_ALLOCNODE)
- /* This describes a free chunk */
- struct mm_freenode_s
- {
- mmsize_t size; /* Size of this chunk */
- mmsize_t preceding; /* Size of the preceding chunk */
- FAR struct mm_freenode_s *flink; /* Supports a doubly linked list */
- FAR struct mm_freenode_s *blink;
- };
- struct mm_delaynode_s
- {
- struct mm_delaynode_s *flink;
- };
- /* What is the size of the freenode? */
- #define MM_PTR_SIZE sizeof(FAR struct mm_freenode_s *)
- #define SIZEOF_MM_FREENODE (SIZEOF_MM_ALLOCNODE + 2*MM_PTR_SIZE)
- #define CHECK_FREENODE_SIZE \
- DEBUGASSERT(sizeof(struct mm_freenode_s) == SIZEOF_MM_FREENODE)
- /* This describes one heap (possibly with multiple regions) */
- struct mm_heap_s
- {
- /* Mutually exclusive access to this data set is enforced with
- * the following un-named semaphore.
- */
- sem_t mm_semaphore;
- pid_t mm_holder;
- int mm_counts_held;
- /* This is the size of the heap provided to mm */
- size_t mm_heapsize;
- /* This is the first and last nodes of the heap */
- FAR struct mm_allocnode_s *mm_heapstart[CONFIG_MM_REGIONS];
- FAR struct mm_allocnode_s *mm_heapend[CONFIG_MM_REGIONS];
- #if CONFIG_MM_REGIONS > 1
- int mm_nregions;
- #endif
- /* All free nodes are maintained in a doubly linked list. This
- * array provides some hooks into the list at various points to
- * speed searches for free nodes.
- */
- struct mm_freenode_s mm_nodelist[MM_NNODES];
- /* Free delay list, for some situation can't do free immdiately */
- struct mm_delaynode_s *mm_delaylist;
- };
- /****************************************************************************
- * Public Data
- ****************************************************************************/
- #undef EXTERN
- #if defined(__cplusplus)
- #define EXTERN extern "C"
- extern "C"
- {
- #else
- #define EXTERN extern
- #endif
- /* User heap structure:
- *
- * - Flat build: In the FLAT build, the user heap structure is a globally
- * accessible variable.
- * - Protected build: The user heap structure is directly available only
- * in user space.
- * - Kernel build: There are multiple heaps, one per process. The heap
- * structure is associated with the address environment and there is
- * no global user heap structure.
- */
- /* In the kernel build, there a multiple user heaps; one for each task
- * group. In this build configuration, the user heap structure lies
- * in a reserved region at the beginning of the .bss/.data address
- * space (CONFIG_ARCH_DATA_VBASE). The size of that region is given by
- * ARCH_DATA_RESERVE_SIZE
- */
- /* In the protected mode, there are two heaps: A kernel heap and a single
- * user heap. In that case the user heap structure lies in the user space
- * (with a reference in the userspace interface).
- */
- #if defined(CONFIG_BUILD_FLAT) || !defined(__KERNEL__)
- /* Otherwise, the user heap data structures are in common .bss */
- EXTERN struct mm_heap_s g_mmheap;
- #endif
- #ifdef CONFIG_MM_KERNEL_HEAP
- /* This is the kernel heap */
- EXTERN struct mm_heap_s g_kmmheap;
- #endif
- /****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
- /* Functions contained in mm_initialize.c ***********************************/
- void mm_initialize(FAR struct mm_heap_s *heap, FAR void *heap_start,
- size_t heap_size);
- void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart,
- size_t heapsize);
- /* Functions contained in umm_initialize.c **********************************/
- void umm_initialize(FAR void *heap_start, size_t heap_size);
- /* Functions contained in kmm_initialize.c **********************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- void kmm_initialize(FAR void *heap_start, size_t heap_size);
- #endif
- /* Functions contained in umm_addregion.c ***********************************/
- void umm_addregion(FAR void *heapstart, size_t heapsize);
- /* Functions contained in kmm_addregion.c ***********************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- void kmm_addregion(FAR void *heapstart, size_t heapsize);
- #endif
- /* Functions contained in mm_sem.c ******************************************/
- void mm_seminitialize(FAR struct mm_heap_s *heap);
- void mm_takesemaphore(FAR struct mm_heap_s *heap);
- int mm_trysemaphore(FAR struct mm_heap_s *heap);
- void mm_givesemaphore(FAR struct mm_heap_s *heap);
- /* Functions contained in umm_sem.c *****************************************/
- int umm_trysemaphore(void);
- void umm_givesemaphore(void);
- /* Functions contained in kmm_sem.c *****************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- int kmm_trysemaphore(void);
- void kmm_givesemaphore(void);
- #endif
- /* Functions contained in mm_malloc.c ***************************************/
- FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size);
- /* Functions contained in kmm_malloc.c **************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- FAR void *kmm_malloc(size_t size);
- #endif
- /* Functions contained in mm_free.c *****************************************/
- void mm_free(FAR struct mm_heap_s *heap, FAR void *mem);
- /* Functions contained in kmm_free.c ****************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- void kmm_free(FAR void *mem);
- #endif
- /* Functions contained in mm_realloc.c **************************************/
- FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
- size_t size);
- /* Functions contained in kmm_realloc.c *************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- FAR void *kmm_realloc(FAR void *oldmem, size_t newsize);
- #endif
- /* Functions contained in mm_calloc.c ***************************************/
- FAR void *mm_calloc(FAR struct mm_heap_s *heap, size_t n, size_t elem_size);
- /* Functions contained in kmm_calloc.c **************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- FAR void *kmm_calloc(size_t n, size_t elem_size);
- #endif
- /* Functions contained in mm_zalloc.c ***************************************/
- FAR void *mm_zalloc(FAR struct mm_heap_s *heap, size_t size);
- /* Functions contained in kmm_zalloc.c **************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- FAR void *kmm_zalloc(size_t size);
- #endif
- /* Functions contained in mm_memalign.c *************************************/
- FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
- size_t size);
- /* Functions contained in kmm_memalign.c ************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- FAR void *kmm_memalign(size_t alignment, size_t size);
- #endif
- /* Functions contained in mm_heapmember.c ***********************************/
- bool mm_heapmember(FAR struct mm_heap_s *heap, FAR void *mem);
- /* Functions contained in mm_uheapmember.c **********************************/
- bool umm_heapmember(FAR void *mem);
- /* Functions contained in kmm_heapmember.c **********************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- bool kmm_heapmember(FAR void *mem);
- #endif
- /* Functions contained in mm_brkaddr.c **************************************/
- FAR void *mm_brkaddr(FAR struct mm_heap_s *heap, int region);
- /* Functions contained in umm_brkaddr.c *************************************/
- FAR void *umm_brkaddr(int region);
- /* Functions contained in kmm_brkaddr.c *************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- FAR void *kmm_brkaddr(int region);
- #endif
- /* Functions contained in mm_sbrk.c *****************************************/
- #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC)
- FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
- uintptr_t maxbreak);
- #endif
- /* Functions contained in kmm_sbrk.c ****************************************/
- #if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_ARCH_ADDRENV) && \
- defined(CONFIG_MM_PGALLOC)
- FAR void *kmm_sbrk(intptr_t incr);
- #endif
- /* Functions contained in mm_extend.c ***************************************/
- void mm_extend(FAR struct mm_heap_s *heap, FAR void *mem, size_t size,
- int region);
- /* Functions contained in umm_extend.c **************************************/
- void umm_extend(FAR void *mem, size_t size, int region);
- /* Functions contained in kmm_extend.c **************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- void kmm_extend(FAR void *mem, size_t size, int region);
- #endif
- /* Functions contained in mm_mallinfo.c *************************************/
- struct mallinfo; /* Forward reference */
- int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info);
- /* Functions contained in kmm_mallinfo.c ************************************/
- #ifdef CONFIG_MM_KERNEL_HEAP
- struct mallinfo kmm_mallinfo(void);
- #endif
- /* Functions contained in mm_shrinkchunk.c **********************************/
- void mm_shrinkchunk(FAR struct mm_heap_s *heap,
- FAR struct mm_allocnode_s *node, size_t size);
- /* Functions contained in mm_addfreechunk.c *********************************/
- void mm_addfreechunk(FAR struct mm_heap_s *heap,
- FAR struct mm_freenode_s *node);
- /* Functions contained in mm_size2ndx.c.c ***********************************/
- int mm_size2ndx(size_t size);
- #undef EXTERN
- #ifdef __cplusplus
- }
- #endif
- #endif /* __INCLUDE_NUTTX_MM_MM_H */
|