⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 2 页
字号:
    SYS_ARCH_DECL_PROTECT(lev);    LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));    /* 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 *)(void *)((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 - (mem_size_t)(((u8_t *)mem - ram)));  /* finally, see if prev or next are free also */  plug_holes(mem);#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT  mem_free_count = 1;#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */  LWIP_MEM_FREE_UNPROTECT();}/** * Shrink memory returned by mem_malloc(). * * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked * @param newsize required size after shrinking (needs to be smaller than or *                equal to the previous size) * @return for compatibility reasons: is always == rmem, at the moment *         or NULL if newsize is > old size, in which case rmem is NOT touched *         or freed! */void *mem_trim(void *rmem, mem_size_t newsize){  mem_size_t size;  mem_size_t ptr, ptr2;  struct mem *mem, *mem2;  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */  LWIP_MEM_FREE_DECL_PROTECT();  /* Expand the size of the allocated memory region so that we can     adjust for alignment. */  newsize = LWIP_MEM_ALIGN_SIZE(newsize);  if(newsize < MIN_SIZE_ALIGNED) {    /* every data block must be at least MIN_SIZE_ALIGNED long */    newsize = MIN_SIZE_ALIGNED;  }  if (newsize > MEM_SIZE_ALIGNED) {    return NULL;  }  LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&   (u8_t *)rmem < (u8_t *)ram_end);  if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {    SYS_ARCH_DECL_PROTECT(lev);    LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));    /* protect mem stats from concurrent access */    SYS_ARCH_PROTECT(lev);    MEM_STATS_INC(illegal);    SYS_ARCH_UNPROTECT(lev);    return rmem;  }  /* Get the corresponding struct mem ... */  mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);  /* ... and its offset pointer */  ptr = (mem_size_t)((u8_t *)mem - ram);  size = mem->next - ptr - SIZEOF_STRUCT_MEM;  LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);  if (newsize > size) {    /* not supported */    return NULL;  }  if (newsize == size) {    /* No change in size, simply return */    return rmem;  }  /* protect the heap from concurrent access */  LWIP_MEM_FREE_PROTECT();  mem2 = (struct mem *)(void *)&ram[mem->next];  if(mem2->used == 0) {    /* The next struct is unused, we can simply move it at little */    mem_size_t next;    /* remember the old next pointer */    next = mem2->next;    /* create new struct mem which is moved directly after the shrinked mem */    ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;    if (lfree == mem2) {      lfree = (struct mem *)(void *)&ram[ptr2];    }    mem2 = (struct mem *)(void *)&ram[ptr2];    mem2->used = 0;    /* restore the next pointer */    mem2->next = next;    /* link it back to mem */    mem2->prev = ptr;    /* link mem to it */    mem->next = ptr2;    /* last thing to restore linked list: as we have moved mem2,     * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not     * the end of the heap */    if (mem2->next != MEM_SIZE_ALIGNED) {      ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;    }    MEM_STATS_DEC_USED(used, (size - newsize));    /* no need to plug holes, we've already done that */  } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {    /* Next struct is used but there's room for another struct mem with     * at least MIN_SIZE_ALIGNED of data.     * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem     * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').     * @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 + newsize;    mem2 = (struct mem *)(void *)&ram[ptr2];    if (mem2 < lfree) {      lfree = mem2;    }    mem2->used = 0;    mem2->next = mem->next;    mem2->prev = ptr;    mem->next = ptr2;    if (mem2->next != MEM_SIZE_ALIGNED) {      ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;    }    MEM_STATS_DEC_USED(used, (size - newsize));    /* the original mem->next is used, so no need to plug holes! */  }  /* else {    next struct mem is used but size between mem and mem2 is not big enough    to create another struct mem    -> don't do anyhting.     -> the remaining space stays unused since it is too small  } */#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT  mem_free_count = 1;#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */  LWIP_MEM_FREE_UNPROTECT();  return rmem;}/** * 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;#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT  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;  }  /* 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_mutex_lock(&mem_mutex);  LWIP_MEM_ALLOC_PROTECT();#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.     */    for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;         ptr = ((struct mem *)(void *)&ram[ptr])->next) {      mem = (struct mem *)(void *)&ram[ptr];#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT      mem_free_count = 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 */      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 *)(void *)&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 *)(void *)&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 - (mem_size_t)((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 *)(void *)&ram[lfree->next];          }          LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));        }        LWIP_MEM_ALLOC_UNPROTECT();        sys_mutex_unlock(&mem_mutex);        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 + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);        LWIP_ASSERT("mem_malloc: sanity check alignment",          (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);        return (u8_t *)mem + SIZEOF_STRUCT_MEM;      }    }#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 | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));  MEM_STATS_INC(err);  LWIP_MEM_ALLOC_UNPROTECT();  sys_mutex_unlock(&mem_mutex);  return NULL;}#endif /* MEM_USE_POOLS *//** * Contiguously allocates enough space for count objects that are size bytes * of memory each and returns a pointer to the allocated memory. * * The allocated memory is filled with bytes of value zero. * * @param count number of objects to allocate * @param size size of the objects to allocate * @return pointer to allocated memory / NULL pointer if there is an error */void *mem_calloc(mem_size_t count, mem_size_t size){  void *p;  /* allocate 'count' objects of size 'size' */  p = mem_malloc(count * size);  if (p) {    /* zero the memory */    memset(p, 0, count * size);  }  return p;}#endif /* !MEM_LIBC_MALLOC */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -