mem.c
上传用户:yyhongfa
上传日期:2013-01-18
资源大小:267k
文件大小:8k
开发平台:

C/C++

  1. /** @file
  2.  *
  3.  * Dynamic memory manager
  4.  *
  5.  */
  6. /* 
  7.  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  8.  * All rights reserved. 
  9.  * 
  10.  * Redistribution and use in source and binary forms, with or without modification, 
  11.  * are permitted provided that the following conditions are met:
  12.  *
  13.  * 1. Redistributions of source code must retain the above copyright notice,
  14.  *    this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright notice,
  16.  *    this list of conditions and the following disclaimer in the documentation
  17.  *    and/or other materials provided with the distribution.
  18.  * 3. The name of the author may not be used to endorse or promote products
  19.  *    derived from this software without specific prior written permission. 
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  22.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  23.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
  24.  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  25.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  26.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
  29.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
  30.  * OF SUCH DAMAGE.
  31.  *
  32.  * This file is part of the lwIP TCP/IP stack.
  33.  * 
  34.  * Author: Adam Dunkels <adam@sics.se>
  35.  *
  36.  */
  37. #include <string.h>
  38. #include "lwip/arch.h"
  39. #include "lwip/opt.h"
  40. #include "lwip/def.h"
  41. #include "lwip/mem.h"
  42. #include "lwip/sys.h"
  43. #include "lwip/stats.h"
  44. #include "uart.h"
  45. struct mem {
  46.   mem_size_t next, prev;
  47. #if MEM_ALIGNMENT == 1
  48.   u8_t used;
  49. #elif MEM_ALIGNMENT == 2
  50.   u16_t used;
  51. #elif MEM_ALIGNMENT == 4
  52.   u32_t used;
  53. #elif MEM_ALIGNMENT == 8
  54.   u64_t used;
  55. #else
  56. #error "unhandled MEM_ALIGNMENT size"
  57. #endif /* MEM_ALIGNMENT */
  58. }; 
  59. static struct mem *ram_end;
  60. static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];
  61. #define MIN_SIZE 12
  62. #if 0 /* this one does not align correctly for some, resulting in crashes */
  63. #define SIZEOF_STRUCT_MEM (unsigned int)MEM_ALIGN_SIZE(sizeof(struct mem))
  64. #else
  65. #define SIZEOF_STRUCT_MEM (sizeof(struct mem) + 
  66.                           (((sizeof(struct mem) % MEM_ALIGNMENT) == 0)? 0 : 
  67.                           (4 - (sizeof(struct mem) % MEM_ALIGNMENT))))
  68. #endif
  69. static struct mem *lfree;   /* pointer to the lowest free block */
  70. static sys_sem_t mem_sem;
  71. static void
  72. plug_holes(struct mem *mem)
  73. {
  74.   struct mem *nmem;
  75.   struct mem *pmem;
  76.   LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
  77.   LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
  78.   LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
  79.   
  80.   /* plug hole forward */
  81.   LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);
  82.   
  83.   nmem = (struct mem *)&ram[mem->next];
  84.   if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
  85.     if (lfree == nmem) {
  86.       lfree = mem;
  87.     }
  88.     mem->next = nmem->next;
  89.     ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
  90.   }
  91.   /* plug hole backward */
  92.   pmem = (struct mem *)&ram[mem->prev];
  93.   if (pmem != mem && pmem->used == 0) {
  94.     if (lfree == mem) {
  95.       lfree = pmem;
  96.     }
  97.     pmem->next = mem->next;
  98.     ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
  99.   }
  100. }
  101. void
  102. mem_init(void)
  103. {
  104.   struct mem *mem;
  105.   memset(ram, 0, MEM_SIZE);
  106.   mem = (struct mem *)ram;
  107.   mem->next = MEM_SIZE;
  108.   mem->prev = 0;
  109.   mem->used = 0;
  110.   ram_end = (struct mem *)&ram[MEM_SIZE];
  111.   ram_end->used = 1;
  112.   ram_end->next = MEM_SIZE;
  113.   ram_end->prev = MEM_SIZE;
  114.   mem_sem = sys_sem_new(1);
  115.   lfree = (struct mem *)ram;
  116. #if MEM_STATS
  117.   lwip_stats.mem.avail = MEM_SIZE;
  118. #endif /* MEM_STATS */
  119. }
  120. void
  121. mem_free(void *rmem)
  122. {
  123.   struct mem *mem;
  124.   if (rmem == NULL) {
  125.     LWIP_DEBUGF(MEM_DEBUG | DBG_TRACE | 2, ("mem_free(p == NULL) was called.n"));
  126.     return;
  127.   }
  128.   
  129.   sys_sem_wait(mem_sem);
  130.   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
  131.     (u8_t *)rmem < (u8_t *)ram_end);
  132.   
  133.   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
  134.     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memoryn"));
  135. #if MEM_STATS
  136.     ++lwip_stats.mem.err;
  137. #endif /* MEM_STATS */
  138.     sys_sem_signal(mem_sem);
  139.     return;
  140.   }
  141.   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
  142.   LWIP_ASSERT("mem_free: mem->used", mem->used);
  143.   
  144.   mem->used = 0;
  145.   if (mem < lfree) {
  146.     lfree = mem;
  147.   }
  148.   
  149. #if MEM_STATS
  150.   lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
  151.   
  152. #endif /* MEM_STATS */
  153.   plug_holes(mem);
  154.   sys_sem_signal(mem_sem);
  155. }
  156. void *
  157. mem_reallocm(void *rmem, mem_size_t newsize)
  158. {
  159.   void *nmem;
  160.   nmem = mem_malloc(newsize);
  161.   if (nmem == NULL) {
  162.     return mem_realloc(rmem, newsize);
  163.   }
  164.   memcpy(nmem, rmem, newsize);
  165.   mem_free(rmem);
  166.   return nmem;
  167. }
  168. void *
  169. mem_realloc(void *rmem, mem_size_t newsize)
  170. {
  171.   mem_size_t size;
  172.   mem_size_t ptr, ptr2;
  173.   struct mem *mem, *mem2;
  174.     //DEBUG_FUNCTION("mem_realloc()")
  175.   /* Expand the size of the allocated memory region so that we can
  176.      adjust for alignment. */
  177.   if ((newsize % MEM_ALIGNMENT) != 0) {
  178.    newsize += MEM_ALIGNMENT - ((newsize + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
  179.   }
  180.   
  181.   if (newsize > MEM_SIZE) {
  182.     return NULL;
  183.   }
  184.   
  185.   sys_sem_wait(mem_sem);
  186.   
  187.   LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
  188.    (u8_t *)rmem < (u8_t *)ram_end);
  189.   
  190.   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
  191.     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memoryn"));
  192.     return rmem;
  193.   }
  194.   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
  195.   ptr = (u8_t *)mem - ram;
  196.   size = mem->next - ptr - SIZEOF_STRUCT_MEM;
  197. #if MEM_STATS
  198.   lwip_stats.mem.used -= (size - newsize);
  199. #endif /* MEM_STATS */
  200.   
  201.   if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
  202.     ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
  203.     mem2 = (struct mem *)&ram[ptr2];
  204.     mem2->used = 0;
  205.     mem2->next = mem->next;
  206.     mem2->prev = ptr;
  207.     mem->next = ptr2;
  208.     if (mem2->next != MEM_SIZE) {
  209.       ((struct mem *)&ram[mem2->next])->prev = ptr2;
  210.     }
  211.     plug_holes(mem2);
  212.   }
  213.   sys_sem_signal(mem_sem);  
  214.   return rmem;
  215. }
  216. void *
  217. mem_malloc(mem_size_t size)
  218. {
  219.   mem_size_t ptr, ptr2;
  220.   struct mem *mem, *mem2;
  221.   //DEBUG_FUNCTION("mem_malloc()");
  222.   if (size == 0) {
  223.     return NULL;
  224.   }
  225.   /* Expand the size of the allocated memory region so that we can
  226.      adjust for alignment. */
  227.   if ((size % MEM_ALIGNMENT) != 0) {
  228.     size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
  229.   }
  230.   
  231.   if (size > MEM_SIZE) {
  232.      DEBUG_ERR("size > MEM_SIZE");
  233.     return NULL;
  234.   }
  235.   
  236.   sys_sem_wait(mem_sem);
  237.   for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {
  238.     mem = (struct mem *)&ram[ptr];
  239.     if (!mem->used &&
  240.        mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {
  241.       ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
  242.       mem2 = (struct mem *)&ram[ptr2];
  243.       mem2->prev = ptr;      
  244.       mem2->next = mem->next;
  245.       mem->next = ptr2;      
  246.       if (mem2->next != MEM_SIZE) {
  247.         ((struct mem *)&ram[mem2->next])->prev = ptr2;
  248.       }
  249.       
  250.       mem2->used = 0;      
  251.       mem->used = 1;
  252. #if MEM_STATS
  253.       lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
  254.       /*      if (lwip_stats.mem.max < lwip_stats.mem.used) {
  255.         lwip_stats.mem.max = lwip_stats.mem.used;
  256.   } */
  257.       if (lwip_stats.mem.max < ptr2) {
  258.         lwip_stats.mem.max = ptr2;
  259.       }      
  260. #endif /* MEM_STATS */
  261.       if (mem == lfree) {
  262.   /* Find next free block after mem */
  263.         while (lfree->used && lfree != ram_end) {
  264.     lfree = (struct mem *)&ram[lfree->next];
  265.         }
  266.         LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);
  267.       }
  268.       sys_sem_signal(mem_sem);
  269.       LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
  270.        (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
  271.       LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
  272.        (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
  273.       return (u8_t *)mem + SIZEOF_STRUCT_MEM;
  274.     }    
  275.   }
  276.   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytesn", (int)size));
  277. #if MEM_STATS
  278.   ++lwip_stats.mem.err;
  279. #endif /* MEM_STATS */  
  280.   sys_sem_signal(mem_sem);
  281.   DEBUG_ERR("mem_malloc: could not allocate %d bytes");
  282.   return NULL;
  283. }