Detailed description of lwip-mem_init and mem_malloc

Source: Internet
Author: User
<PRE name = "code" class = "CPP"> # define mem_alignment 4 // alignment is 4-byte alignment # ifndef lwip_mem_align_size # define lwip_mem_align_size (size) + mem_alignment-1 )&~ (MEM_ALIGNMENT-1) // implement memory alignment for the data space to be allocated # endif # ifndef lwip_mem_align // address alignment, alignment is also 4-byte alignment # define lwip_mem_align (ADDR) (void *) (mem_ptr_t) (ADDR) + mem_alignment-1 )&~ (Mem_ptr_t) (MEM_ALIGNMENT-1) # endif/* mem_size: the size of the heap memory. if the application will Senda lot of data that needs to be copied, this shoshould be set high. */# define mem_size (8*1024) // total heap space. Then, the heap is divided based on the size, and the memory will be allocated, the memory block struct and data are in this space // mem as the memory block struct, next ;, prev is the memory block index struct mem {/** index (-> ram [next]) of the next struct * // Ram is the first address of the heap, equivalent to the first address of the array. The base address of the index is mem_size_t next. // next is the index of the next memory block. /** Index (-> ram [next]) of the next struct */mem_size_t Prev; // Prev is the index of the previous memory block/** 1: this area is used; 0: This area is unused */u8_t used; // indicates that this memory block has been allocated}; static struct mem * ram_end; /** all allocated blocks will be min_size bytes big, at least! * Min_size can be overridden to suit your needs. smaller values save space, * larger values cocould prevent too small blocks to fragment the Ram too much. */# ifndef min_size # define min_size 12 // minimum memory block size limit, which cannot be smaller than 12 # endif/* min_size * // * some alignment macros: we define them here for better source code Layout */# define min_size_aligned lwip_mem_align_size (min_size) // align min_size in 4 bytes, that is, 12 in 4 bytes # define Si Zeof_struct_mem memory (sizeof (struct MEm) // align mem size in 4 bytes # define mem_size_aligned lwip_mem_align_size (mem_size) // align the total heap space in 4 bytes, mem_size is above. For 8*1024 // memory alignment, read my blog: http://blog.csdn.net/lg2lh/article/details/34853883/#* the heap. we need one struct mem at the end and some room for alignment */static u8_t ram_heap [mem_size_aligned + (2 * sizeof_struct_mem) + mem_alignment]; // The actual heap memory, mem_size _ Aligned: The aligned data space is 8192 // The heap memory size is mem_size_aligned + (2 * sizeof_struct_mem) + mem_alignment = 8192 + 2 * Men struct size + 4voidmem_init (void) {struct mem * MEM; // defines a mem struct pointer variable lwip_assert ("sanity check alignment", (sizeof_struct_mem & (MEM_ALIGNMENT-1) = 0 ); /* align the heap */Ram = lwip_mem_align (ram_heap ); // align the first address ram_heap of the heap space with the 4-byte address/* initialize the start of the heap */MEM = (struct mem *) ram; // forcibly convert the first RAM address of the heap to me M struct type, which is used as the first memory block, but the memory block does not use mem-> next = mem_size_aligned; // point the next pointer of the first memory block to the last address of the heap space (mem_size_aligned is 8*1024). The next index will be dynamically adjusted later in mem_malloc, // The actual allocated memory space is mem-> next minus the address of the memory block mem. // The next index of the memory block to be allocated always points to the end of the heap space, it seems that it is not necessarily true, but it is based on the idea. Mem-> Prev = 0; // initialization, because it is the first memory block, so the previous memory block does not exist, so the initialization is 0 mem-> used = 0; // The memory block is not allocated, pending status/* initialize the end of the heap */ram_end = (struct mem *) & ram [mem_size_aligned]; // sample the memory block at the end of a heap space. The memory block points to the last address, marking the allocated block at the end. The ram_end-> used = 1 cannot be reassigned; // This memory block has been allocated ram_end-> next = mem_size_aligned; // because there is no memory block in the future, the next index points to the end, that is, ram_end-> Prev = mem_size_aligned; // I do not know this. mem_sem = sys_sem_new (1);/* initialize the lowest-free Pointer to the start of the heap */lfree = (struct mem *) ram; // initialize the idle pointer. At this time, the first memory block is the idle mem_stats_avail (avail, mem_size_aligned);} void * mem_malloc (mem_size_t size) {mem_size_t PTR, ptr2; struct mem * MEM, * MEM2; # If your u8_t local_mem_free_count = 0; # endif/* lwip_allow_mem_free_from_other_context */lwip_mem_alloc_decl_protect (); If (size = 0) {return NULL;} // siz If e is 0, null allocation is returned. * expand the size of the allocated memory region so that we can adjust for alignment. */size = lwip_mem_align_size (size); // align the data to be allocated in 4 bytes if (size <min_size_aligned) {// if the space to be allocated is smaller than min_size_aligned (12 ), the returned allocated space is also 12, and the minimum allocated space is 12/* every data block must be at least min_size_aligned long */size = min_size_aligned;} If (size> mem_size_aligned) {// if the space to be allocated is greater than mem_size_aligned (8*1024 ), Heap space, return NULL, unable to allocate return NULL;}/* protect the heap from concurrent access */sys_arch_sem_wait (mem_sem, 0); lwip_mem_alloc_protect (); // undefined # If lwip_allow_mem_free_from_other_context/* Run as long as a mem_free disturbed mem_malloc */do {local_mem_free_count = 0; # endif/* lwip_allow_mem_free_from_other_context * // * scan through the heap searching for a free block that is big enough, * beginning With the lowest free block. * // PTR initial value = the difference between the idle memory block address and the first heap memory address. If the PTR + size is less than the total heap space size of 8*1024, you can allocate memory blocks of the corresponding size. The PTR actually allocates the allocated space. The size is the size of the space to be allocated. The two and one must be less than the total space, can be allocated. // after judgment, assign the PTR value to the address (PTR = (u8_t *) lfree-ram; PTR <mem_size_aligned-size; PTR = (struct mem *) & ram [PTR])-> next) {// initialize the memory space to be allocated as the memory block structure mem = (struct mem *) & ram [PTR]; # If lwip_allow_mem_free_from_other_context // mem_free_count = Is Not Defined 0; lwip_mem_alloc_unprotect ();/* allow mem_free to run */lwip_mem_alloc_protect (); If (mem_free_count! = 0) {local_mem_free_count = mem_free_count;} mem_free_count = 0; # endif/* lwip_allow_mem_free_from_other_context * // you will find the allocated memory space by PTR, the mem-> next of the memory block to be allocated always points to the end of the heap space, that is, mem_size_aligned. // Memory block is not used. In this case, Mem is the memory block to be allocated, so mem-> next points to mem_size_aligned, // The remaining allocated space (mem_size_aligned-allocated space-MEM struct size) it must be greater than the size of the space to be allocated. 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 * // remaining allocated space (mem_size_aligned-allocated space-2 * mem struct size-12) // The memory size must be greater than the size of the space to be allocated. 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-(P Tr + (2 * sizeof_struct_mem) = size, * struct mem wocould fit in but no data between MEM2 and MEM2-> next * @ todo we cocould leave out min_size_aligned. we wocould create an empty * region that couldn't hold data, but when mem-> next gets freed, * the 2 regions wocould be combined, resulting in more free memory * // ptr2 points to the new memory space to be allocated ptr2 = PTR + sizeof_struct_mem + size;/* Create MEM2 struct * // MEM2 is the new memory to be allocated Block Structure MEM2 = (struct mem *) & ram [ptr2]; // The new memory block MEM2 is not used MEM2-> used = 0; // The next index of the new memory block MEM2 points to the end of the heap space, that is, mem_size_aligned MEM2-> next = mem-> next; // The new memory block Prev index is the module index we are allocating this time, that is, PTR MEM2-> Prev = PTR; /* and insert it between MEM and mem-> next * // locate the next index of the memory block allocated this time and point it to the index of the new module to be allocated, no longer point to the last mem-> next = ptr2; mem-> used = 1; // This memory block is used // All I analyzed previously are new memory blocks to be allocated. The next index should always point to the last part of the heap space. I have determined it here, there may be situations that do not point to the end. // The specific reasons have not been analyzed. If the next index of the new memory block to be allocated does not point to the end, you need to point the prev index of the memory block to // its own ptr2. If (MEM2-> next! = Mem_size_aligned) {(struct mem *) & ram [MEM2-> next])-> Prev = ptr2;} mem_stats_inc_used (used, (size + sizeof_struct_mem ));} else {// if the corresponding if condition is not met, You can directly allocate and modify the memory block without directing to the next memory block to be allocated, because there is no space to reallocate/* (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 shoshould have * Take Care Of This ). *-> near F It 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) {// point the idle pointer index to the new memory block index ram [lfree-> next], ptr2/* 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_assert ("mem_malloc :! Lfree-> used ", (lfree = ram_end) | (! Lfree-> used);} lwip_mem_alloc_unprotect (); sys_sem_signal (mem_sem); lwip_assert ("mem_malloc: allocated memory not above ram_end. ", (mem_ptr_t) MEm + sizeof_struct_mem + size <= (mem_ptr_t) ram_end); lwip_assert (" mem_malloc: allocated memory properly aligned. ", (mem_ptr_t) MEm + Memory) % mem_alignment = 0); lwip_assert (" mem_malloc: sanity check alignment ", (mem_ptr_t) MEm) & (mem_alig NMENT-1) = 0); Return (u8_t *) MEm + sizeof_struct_mem; // return the allocation result, that is, the first address of the allocated memory block data space. }}# If lwip_allow_mem_free_from_other_context/* If we got interrupted by a mem_free, try again */} while (local_mem_free_count! = 0); # endif/* lwip_allow_mem_free_from_other_context */lwip_debugf (mem_debug | 2, ("mem_malloc: cocould not allocate %" s16_f "bytes \ n", (s16_t) size )); mem_stats_inc (ERR); lwip_mem_alloc_unprotect (); sys_sem_signal (mem_sem); return NULL ;}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.