00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "lwip/arch.h"
00048 #include "lwip/opt.h"
00049 #include "lwip/def.h"
00050 #include "lwip/mem.h"
00051
00052 #include "lwip/sys.h"
00053
00054 #include "lwip/stats.h"
00055
00056 struct mem {
00057 mem_size_t next, prev;
00058 #if MEM_ALIGNMENT == 1
00059 u8_t used;
00060 #elif MEM_ALIGNMENT == 2
00061 u16_t used;
00062 #elif MEM_ALIGNMENT == 4
00063 u32_t used;
00064 #else
00065 #error "unhandled MEM_ALIGNMENT size"
00066 #endif
00067 };
00068
00069 static struct mem *ram_end;
00070 static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];
00071
00072 #define MIN_SIZE 12
00073 #define SIZEOF_STRUCT_MEM MEM_ALIGN_SIZE(sizeof(struct mem))
00074
00075
00076
00077
00078
00079 static struct mem *lfree;
00080
00081 static sys_sem_t mem_sem;
00082
00083
00084 static void
00085 plug_holes(struct mem *mem)
00086 {
00087 struct mem *nmem;
00088 struct mem *pmem;
00089
00090 LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
00091 LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
00092 LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
00093
00094
00095 LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);
00096
00097 nmem = (struct mem *)&ram[mem->next];
00098 if(mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
00099 if(lfree == nmem) {
00100 lfree = mem;
00101 }
00102 mem->next = nmem->next;
00103 ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
00104 }
00105
00106
00107 pmem = (struct mem *)&ram[mem->prev];
00108 if(pmem != mem && pmem->used == 0) {
00109 if(lfree == mem) {
00110 lfree = pmem;
00111 }
00112 pmem->next = mem->next;
00113 ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
00114 }
00115
00116 }
00117
00118 void
00119 mem_init(void)
00120 {
00121 struct mem *mem;
00122
00123 memset(ram, 0, MEM_SIZE);
00124 mem = (struct mem *)ram;
00125 mem->next = MEM_SIZE;
00126 mem->prev = 0;
00127 mem->used = 0;
00128 ram_end = (struct mem *)&ram[MEM_SIZE];
00129 ram_end->used = 1;
00130 ram_end->next = MEM_SIZE;
00131 ram_end->prev = MEM_SIZE;
00132
00133 mem_sem = sys_sem_new(1);
00134
00135 lfree = (struct mem *)ram;
00136
00137 #ifdef MEM_STATS
00138 lwip_stats.mem.avail = MEM_SIZE;
00139 #endif
00140 }
00141
00142 void
00143 mem_free(void *rmem)
00144 {
00145 struct mem *mem;
00146
00147 if(rmem == NULL) {
00148 return;
00149 }
00150
00151 sys_sem_wait(mem_sem);
00152
00153 LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
00154 (u8_t *)rmem < (u8_t *)ram_end);
00155
00156
00157 if((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
00158 DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
00159 #ifdef MEM_STATS
00160 ++lwip_stats.mem.err;
00161 #endif
00162 return;
00163 }
00164 mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
00165
00166 LWIP_ASSERT("mem_free: mem->used", mem->used);
00167
00168 mem->used = 0;
00169
00170 if(mem < lfree) {
00171 lfree = mem;
00172 }
00173
00174 #ifdef MEM_STATS
00175 lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram) - SIZEOF_STRUCT_MEM;
00176
00177 #endif
00178 plug_holes(mem);
00179 sys_sem_signal(mem_sem);
00180 }
00181
00182 void *
00183 mem_reallocm(void *rmem, mem_size_t newsize)
00184 {
00185 void *nmem;
00186 nmem = mem_malloc(newsize);
00187 if(nmem == NULL) {
00188 return mem_realloc(rmem, newsize);
00189 }
00190 memcpy(nmem, rmem, newsize);
00191 mem_free(rmem);
00192 return nmem;
00193 }
00194
00195 void *
00196 mem_realloc(void *rmem, mem_size_t newsize)
00197 {
00198 mem_size_t size;
00199 mem_size_t ptr, ptr2;
00200 struct mem *mem, *mem2;
00201
00202
00203
00204 if((newsize % MEM_ALIGNMENT) != 0) {
00205 newsize += MEM_ALIGNMENT - ((newsize + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
00206 }
00207
00208 if(newsize > MEM_SIZE) {
00209 return NULL;
00210 }
00211
00212 sys_sem_wait(mem_sem);
00213
00214 LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
00215 (u8_t *)rmem < (u8_t *)ram_end);
00216
00217 if((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
00218 DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
00219 return rmem;
00220 }
00221 mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
00222
00223 ptr = (u8_t *)mem - ram;
00224
00225 size = mem->next - ptr - SIZEOF_STRUCT_MEM;
00226 #ifdef MEM_STATS
00227 lwip_stats.mem.used -= (size - newsize);
00228 #endif
00229
00230 if(newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
00231 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
00232 mem2 = (struct mem *)&ram[ptr2];
00233 mem2->used = 0;
00234 mem2->next = mem->next;
00235 mem2->prev = ptr;
00236 mem->next = ptr2;
00237 if(mem2->next != MEM_SIZE) {
00238 ((struct mem *)&ram[mem2->next])->prev = ptr2;
00239 }
00240
00241 plug_holes(mem2);
00242 }
00243 sys_sem_signal(mem_sem);
00244 return rmem;
00245 }
00246
00247 void *
00248 mem_malloc(mem_size_t size)
00249 {
00250 mem_size_t ptr, ptr2;
00251 struct mem *mem, *mem2;
00252
00253 if(size == 0) {
00254 return NULL;
00255 }
00256
00257
00258
00259 if((size % MEM_ALIGNMENT) != 0) {
00260 size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
00261 }
00262
00263 if(size > MEM_SIZE) {
00264 return NULL;
00265 }
00266
00267 sys_sem_wait(mem_sem);
00268
00269 for(ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {
00270 mem = (struct mem *)&ram[ptr];
00271 if(!mem->used &&
00272 mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {
00273 ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
00274 mem2 = (struct mem *)&ram[ptr2];
00275
00276 mem2->prev = ptr;
00277 mem2->next = mem->next;
00278 mem->next = ptr2;
00279 if(mem2->next != MEM_SIZE) {
00280 ((struct mem *)&ram[mem2->next])->prev = ptr2;
00281 }
00282
00283 mem2->used = 0;
00284 mem->used = 1;
00285 #ifdef MEM_STATS
00286 lwip_stats.mem.used += size;
00287
00288
00289
00290 if(lwip_stats.mem.max < ptr2) {
00291 lwip_stats.mem.max = ptr2;
00292 }
00293 #endif
00294
00295 if(mem == lfree) {
00296
00297 while(lfree->used && lfree != ram_end) {
00298 lfree = (struct mem *)&ram[lfree->next];
00299 }
00300 LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);
00301 }
00302 sys_sem_signal(mem_sem);
00303 LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
00304 (u32_t)mem + SIZEOF_STRUCT_MEM + size <= (u32_t)ram_end);
00305 LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
00306 (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
00307 return (u8_t *)mem + SIZEOF_STRUCT_MEM;
00308 }
00309 }
00310 DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
00311 #ifdef MEM_STATS
00312 ++lwip_stats.mem.err;
00313 #endif
00314 sys_sem_signal(mem_sem);
00315 return NULL;
00316 }
00317