内存管理: malloc()与free()的一种基于clib标准的实现
2012-05-03 22:12
477 查看
/** * Zero the heap and initialize start, end and lowest-free */ void mem_init(void) { struct mem *mem; LWIP_ASSERT("Sanity check alignment", (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); /* align the heap */ ram = LWIP_MEM_ALIGN(ram_heap); /* initialize the start of the heap */ mem = (struct mem *)ram; mem->next = MEM_SIZE_ALIGNED; mem->prev = 0; mem->used = 0; /* initialize the end of the heap */ ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED]; ram_end->used = 1; ram_end->next = MEM_SIZE_ALIGNED; ram_end->prev = MEM_SIZE_ALIGNED; mem_sem = sys_sem_new(1); /* initialize the lowest-free pointer to the start of the heap */ lfree = (struct mem *)ram; MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); } /** * Adam's mem_malloc() plus solution for bug #17922 * Allocate a block of memory with a minimum of 'size' bytes. * * @param size is the minimum size of the requested block in bytes. * @return pointer to allocated memory or NULL if no free memory was found. * * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). */ void * mem_malloc(mem_size_t size) { mem_size_t ptr, ptr2; struct mem *mem, *mem2; LWIP_MEM_ALLOC_DECL_PROTECT(); if (size == 0) { return NULL; } /* Expand the size of the allocated memory region so that we can adjust for alignment. */ size = LWIP_MEM_ALIGN_SIZE(size); if(size < MIN_SIZE_ALIGNED) { /* every data block must be at least MIN_SIZE_ALIGNED long */ size = MIN_SIZE_ALIGNED; } if (size > MEM_SIZE_ALIGNED) { return NULL; } /* protect the heap from concurrent access */ sys_arch_sem_wait(mem_sem, 0); LWIP_MEM_ALLOC_PROTECT(); /* Scan through the heap searching for a free block that is big enough, * beginning with the lowest free block. */ for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size; ptr = ((struct mem *)&ram[ptr])->next) { mem = (struct mem *)&ram[ptr]; if ((!mem->used) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { /* mem is not used and at least perfect fit is possible: * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') * -> split large block, create empty remainder, * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, * struct mem would fit in but no data between mem2 and mem2->next * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty * region that couldn't hold data, but when mem->next gets freed, * the 2 regions would be combined, resulting in more free memory */ ptr2 = ptr + SIZEOF_STRUCT_MEM + size; /* create mem2 struct */ mem2 = (struct mem *)&ram[ptr2]; mem2->used = 0; mem2->next = mem->next; mem2->prev = ptr; /* and insert it between mem and mem->next */ mem->next = ptr2; mem->used = 1; if (mem2->next != MEM_SIZE_ALIGNED) { ((struct mem *)&ram[mem2->next])->prev = ptr2; } MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); } else { /* (a mem2 struct does no fit into the user data space of mem and mem->next will always * be used at this point: if not we have 2 unused structs in a row, plug_holes should have * take care of this). * -> near fit or excact fit: do not split, no mem2 creation * also can't move mem->next directly behind mem, since mem->next * will always be used at this point! */ mem->used = 1; MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram)); } if (mem == lfree) { /* Find next free block after mem and update lowest free pointer */ while (lfree->used && lfree != ram_end) { LWIP_MEM_ALLOC_UNPROTECT(); /* prevent high interrupt latency... */ LWIP_MEM_ALLOC_PROTECT(); lfree = (struct mem *)&ram[lfree->next]; } } LWIP_MEM_ALLOC_UNPROTECT(); sys_sem_signal(mem_sem); return (u8_t *)mem + SIZEOF_STRUCT_MEM; } } MEM_STATS_INC(err); LWIP_MEM_ALLOC_UNPROTECT(); sys_sem_signal(mem_sem); return NULL; } /** * "Plug holes" by combining adjacent empty struct mems. * After this function is through, there should not exist * one empty struct mem pointing to another empty struct mem. * * @param mem this points to a struct mem which just has been freed * @internal this function is only called by mem_free() and mem_realloc() * * This assumes access to the heap is protected by the calling function * already. */ static void plug_holes(struct mem *mem) { struct mem *nmem; struct mem *pmem; /* plug hole forward */ LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); nmem = (struct mem *)&ram[mem->next]; if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { /* if mem->next is unused and not end of ram, combine mem and mem->next */ if (lfree == nmem) { lfree = mem; } mem->next = nmem->next; ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram; } /* plug hole backward */ pmem = (struct mem *)&ram[mem->prev]; if (pmem != mem && pmem->used == 0) { /* if mem->prev is unused, combine mem and mem->prev */ if (lfree == mem) { lfree = pmem; } pmem->next = mem->next; ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram; } } /** * Put a struct mem back on the heap * * @param rmem is the data portion of a struct mem as returned by a previous * call to mem_malloc() */ void mem_free(void *rmem) { struct mem *mem; LWIP_MEM_FREE_DECL_PROTECT(); if (rmem == NULL) { return; } if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { SYS_ARCH_DECL_PROTECT(lev); /* protect mem stats from concurrent access */ SYS_ARCH_PROTECT(lev); MEM_STATS_INC(illegal); SYS_ARCH_UNPROTECT(lev); return; } /* protect the heap from concurrent access */ LWIP_MEM_FREE_PROTECT(); /* Get the corresponding struct mem ... */ mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); /* ... which has to be in a used state ... */ LWIP_ASSERT("mem_free: mem->used", mem->used); /* ... and is now unused. */ mem->used = 0; if (mem < lfree) { /* the newly freed struct is now the lowest */ lfree = mem; } MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram)); /* finally, see if prev or next are free also */ plug_holes(mem); LWIP_MEM_FREE_UNPROTECT(); }
相关文章推荐
- 内存管理: malloc()与free()的一种基于池表结构的实现
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
- 单片机(不基于os)下如何实现简单的内存管理(malloc,realloc和free函数的重新实现)
- 自己写的STM32 内存管理 实现了malloc,free,remalloc等函数
- C语言内存管理:malloc、calloc、free的实现
- 自己写的STM32 内存管理 实现了malloc,free,remalloc等函数
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
- 自己写的STM32 内存管理 实现了malloc,free,remalloc等函数
- [转载] STL allocator的介绍和一个基于malloc/free的allocator的简单实现
- 单片机(不基于os)下如何实现简单的内存管理(malloc,realloc和free函数的重新实现)
- 自己写的STM32 内存管理 实现了malloc,free,remalloc等函数
- 单片机(不基于os)下如何实现简单的内存管理(malloc,realloc和free函数的重新实现)
- 基于malloc与free函数的实现代码及分析
- 自己写的STM32 内存管理 实现了malloc,free,remalloc等函数
- C语言内存管理:malloc、calloc、free的实现
- 单片机(不基于os)下如何实现简单的内存管理(malloc,realloc和free函数的重新实现)
- [转载] STL allocator的介绍和一个基于malloc/free的allocator的简单实现
- 自己写的STM32 内存管理 实现了malloc,free,remalloc等函数
- 基于malloc与free函数的实现代码及分析
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现