Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1 #pragma diag_remark 177
segundo 0:ac1725ba162c 2 /**
segundo 0:ac1725ba162c 3 * @file
segundo 0:ac1725ba162c 4 * Dynamic memory manager
segundo 0:ac1725ba162c 5 *
segundo 0:ac1725ba162c 6 * This is a lightweight replacement for the standard C library malloc().
segundo 0:ac1725ba162c 7 *
segundo 0:ac1725ba162c 8 * If you want to use the standard C library malloc() instead, define
segundo 0:ac1725ba162c 9 * MEM_LIBC_MALLOC to 1 in your lwipopts.h
segundo 0:ac1725ba162c 10 *
segundo 0:ac1725ba162c 11 * To let mem_malloc() use pools (prevents fragmentation and is much faster than
segundo 0:ac1725ba162c 12 * a heap but might waste some memory), define MEM_USE_POOLS to 1, define
segundo 0:ac1725ba162c 13 * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list
segundo 0:ac1725ba162c 14 * of pools like this (more pools can be added between _START and _END):
segundo 0:ac1725ba162c 15 *
segundo 0:ac1725ba162c 16 * Define three pools with sizes 256, 512, and 1512 bytes
segundo 0:ac1725ba162c 17 * LWIP_MALLOC_MEMPOOL_START
segundo 0:ac1725ba162c 18 * LWIP_MALLOC_MEMPOOL(20, 256)
segundo 0:ac1725ba162c 19 * LWIP_MALLOC_MEMPOOL(10, 512)
segundo 0:ac1725ba162c 20 * LWIP_MALLOC_MEMPOOL(5, 1512)
segundo 0:ac1725ba162c 21 * LWIP_MALLOC_MEMPOOL_END
segundo 0:ac1725ba162c 22 */
segundo 0:ac1725ba162c 23
segundo 0:ac1725ba162c 24 /*
segundo 0:ac1725ba162c 25 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
segundo 0:ac1725ba162c 26 * All rights reserved.
segundo 0:ac1725ba162c 27 *
segundo 0:ac1725ba162c 28 * Redistribution and use in source and binary forms, with or without modification,
segundo 0:ac1725ba162c 29 * are permitted provided that the following conditions are met:
segundo 0:ac1725ba162c 30 *
segundo 0:ac1725ba162c 31 * 1. Redistributions of source code must retain the above copyright notice,
segundo 0:ac1725ba162c 32 * this list of conditions and the following disclaimer.
segundo 0:ac1725ba162c 33 * 2. Redistributions in binary form must reproduce the above copyright notice,
segundo 0:ac1725ba162c 34 * this list of conditions and the following disclaimer in the documentation
segundo 0:ac1725ba162c 35 * and/or other materials provided with the distribution.
segundo 0:ac1725ba162c 36 * 3. The name of the author may not be used to endorse or promote products
segundo 0:ac1725ba162c 37 * derived from this software without specific prior written permission.
segundo 0:ac1725ba162c 38 *
segundo 0:ac1725ba162c 39 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
segundo 0:ac1725ba162c 40 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
segundo 0:ac1725ba162c 41 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
segundo 0:ac1725ba162c 42 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
segundo 0:ac1725ba162c 43 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
segundo 0:ac1725ba162c 44 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
segundo 0:ac1725ba162c 45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
segundo 0:ac1725ba162c 46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
segundo 0:ac1725ba162c 47 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
segundo 0:ac1725ba162c 48 * OF SUCH DAMAGE.
segundo 0:ac1725ba162c 49 *
segundo 0:ac1725ba162c 50 * This file is part of the lwIP TCP/IP stack.
segundo 0:ac1725ba162c 51 *
segundo 0:ac1725ba162c 52 * Author: Adam Dunkels <adam@sics.se>
segundo 0:ac1725ba162c 53 * Simon Goldschmidt
segundo 0:ac1725ba162c 54 *
segundo 0:ac1725ba162c 55 */
segundo 0:ac1725ba162c 56
segundo 0:ac1725ba162c 57 #include "lwip/opt.h"
segundo 0:ac1725ba162c 58
segundo 0:ac1725ba162c 59 #if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */
segundo 0:ac1725ba162c 60
segundo 0:ac1725ba162c 61 #include "lwip/def.h"
segundo 0:ac1725ba162c 62 #include "lwip/mem.h"
segundo 0:ac1725ba162c 63 #include "lwip/sys.h"
segundo 0:ac1725ba162c 64 #include "lwip/stats.h"
segundo 0:ac1725ba162c 65 #include "lwip/err.h"
segundo 0:ac1725ba162c 66
segundo 0:ac1725ba162c 67 #include <string.h>
segundo 0:ac1725ba162c 68
segundo 0:ac1725ba162c 69 #if MEM_USE_POOLS
segundo 0:ac1725ba162c 70 /* lwIP head implemented with different sized pools */
segundo 0:ac1725ba162c 71
segundo 0:ac1725ba162c 72 /**
segundo 0:ac1725ba162c 73 * Allocate memory: determine the smallest pool that is big enough
segundo 0:ac1725ba162c 74 * to contain an element of 'size' and get an element from that pool.
segundo 0:ac1725ba162c 75 *
segundo 0:ac1725ba162c 76 * @param size the size in bytes of the memory needed
segundo 0:ac1725ba162c 77 * @return a pointer to the allocated memory or NULL if the pool is empty
segundo 0:ac1725ba162c 78 */
segundo 0:ac1725ba162c 79 void *
segundo 0:ac1725ba162c 80 mem_malloc(mem_size_t size)
segundo 0:ac1725ba162c 81 {
segundo 0:ac1725ba162c 82 struct memp_malloc_helper *element;
segundo 0:ac1725ba162c 83 memp_t poolnr;
segundo 0:ac1725ba162c 84 mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
segundo 0:ac1725ba162c 85
segundo 0:ac1725ba162c 86 for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
segundo 0:ac1725ba162c 87 #if MEM_USE_POOLS_TRY_BIGGER_POOL
segundo 0:ac1725ba162c 88 again:
segundo 0:ac1725ba162c 89 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
segundo 0:ac1725ba162c 90 /* is this pool big enough to hold an element of the required size
segundo 0:ac1725ba162c 91 plus a struct memp_malloc_helper that saves the pool this element came from? */
segundo 0:ac1725ba162c 92 if (required_size <= memp_sizes[poolnr]) {
segundo 0:ac1725ba162c 93 break;
segundo 0:ac1725ba162c 94 }
segundo 0:ac1725ba162c 95 }
segundo 0:ac1725ba162c 96 if (poolnr > MEMP_POOL_LAST) {
segundo 0:ac1725ba162c 97 LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
segundo 0:ac1725ba162c 98 return NULL;
segundo 0:ac1725ba162c 99 }
segundo 0:ac1725ba162c 100 element = (struct memp_malloc_helper*)memp_malloc(poolnr);
segundo 0:ac1725ba162c 101 if (element == NULL) {
segundo 0:ac1725ba162c 102 /* No need to DEBUGF or ASSERT: This error is already
segundo 0:ac1725ba162c 103 taken care of in memp.c */
segundo 0:ac1725ba162c 104 #if MEM_USE_POOLS_TRY_BIGGER_POOL
segundo 0:ac1725ba162c 105 /** Try a bigger pool if this one is empty! */
segundo 0:ac1725ba162c 106 if (poolnr < MEMP_POOL_LAST) {
segundo 0:ac1725ba162c 107 poolnr++;
segundo 0:ac1725ba162c 108 goto again;
segundo 0:ac1725ba162c 109 }
segundo 0:ac1725ba162c 110 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
segundo 0:ac1725ba162c 111 return NULL;
segundo 0:ac1725ba162c 112 }
segundo 0:ac1725ba162c 113
segundo 0:ac1725ba162c 114 /* save the pool number this element came from */
segundo 0:ac1725ba162c 115 element->poolnr = poolnr;
segundo 0:ac1725ba162c 116 /* and return a pointer to the memory directly after the struct memp_malloc_helper */
segundo 0:ac1725ba162c 117 element++;
segundo 0:ac1725ba162c 118
segundo 0:ac1725ba162c 119 return element;
segundo 0:ac1725ba162c 120 }
segundo 0:ac1725ba162c 121
segundo 0:ac1725ba162c 122 /**
segundo 0:ac1725ba162c 123 * Free memory previously allocated by mem_malloc. Loads the pool number
segundo 0:ac1725ba162c 124 * and calls memp_free with that pool number to put the element back into
segundo 0:ac1725ba162c 125 * its pool
segundo 0:ac1725ba162c 126 *
segundo 0:ac1725ba162c 127 * @param rmem the memory element to free
segundo 0:ac1725ba162c 128 */
segundo 0:ac1725ba162c 129 void
segundo 0:ac1725ba162c 130 mem_free(void *rmem)
segundo 0:ac1725ba162c 131 {
segundo 0:ac1725ba162c 132 struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
segundo 0:ac1725ba162c 133
segundo 0:ac1725ba162c 134 LWIP_ASSERT("rmem != NULL", (rmem != NULL));
segundo 0:ac1725ba162c 135 LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
segundo 0:ac1725ba162c 136
segundo 0:ac1725ba162c 137 /* get the original struct memp_malloc_helper */
segundo 0:ac1725ba162c 138 hmem--;
segundo 0:ac1725ba162c 139
segundo 0:ac1725ba162c 140 LWIP_ASSERT("hmem != NULL", (hmem != NULL));
segundo 0:ac1725ba162c 141 LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
segundo 0:ac1725ba162c 142 LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
segundo 0:ac1725ba162c 143
segundo 0:ac1725ba162c 144 /* and put it in the pool we saved earlier */
segundo 0:ac1725ba162c 145 memp_free(hmem->poolnr, hmem);
segundo 0:ac1725ba162c 146 }
segundo 0:ac1725ba162c 147
segundo 0:ac1725ba162c 148 #else /* MEM_USE_POOLS */
segundo 0:ac1725ba162c 149 /* lwIP replacement for your libc malloc() */
segundo 0:ac1725ba162c 150
segundo 0:ac1725ba162c 151 /**
segundo 0:ac1725ba162c 152 * The heap is made up as a list of structs of this type.
segundo 0:ac1725ba162c 153 * This does not have to be aligned since for getting its size,
segundo 0:ac1725ba162c 154 * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes.
segundo 0:ac1725ba162c 155 */
segundo 0:ac1725ba162c 156 struct mem {
segundo 0:ac1725ba162c 157 /** index (-> ram[next]) of the next struct */
segundo 0:ac1725ba162c 158 mem_size_t next;
segundo 0:ac1725ba162c 159 /** index (-> ram[prev]) of the previous struct */
segundo 0:ac1725ba162c 160 mem_size_t prev;
segundo 0:ac1725ba162c 161 /** 1: this area is used; 0: this area is unused */
segundo 0:ac1725ba162c 162 u8_t used;
segundo 0:ac1725ba162c 163 };
segundo 0:ac1725ba162c 164
segundo 0:ac1725ba162c 165 /** All allocated blocks will be MIN_SIZE bytes big, at least!
segundo 0:ac1725ba162c 166 * MIN_SIZE can be overridden to suit your needs. Smaller values save space,
segundo 0:ac1725ba162c 167 * larger values could prevent too small blocks to fragment the RAM too much. */
segundo 0:ac1725ba162c 168 #ifndef MIN_SIZE
segundo 0:ac1725ba162c 169 #define MIN_SIZE 12
segundo 0:ac1725ba162c 170 #endif /* MIN_SIZE */
segundo 0:ac1725ba162c 171 /* some alignment macros: we define them here for better source code layout */
segundo 0:ac1725ba162c 172 #define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
segundo 0:ac1725ba162c 173 #define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
segundo 0:ac1725ba162c 174 #define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
segundo 0:ac1725ba162c 175
segundo 0:ac1725ba162c 176 /** If you want to relocate the heap to external memory, simply define
segundo 0:ac1725ba162c 177 * LWIP_RAM_HEAP_POINTER as a void-pointer to that location.
segundo 0:ac1725ba162c 178 * If so, make sure the memory at that location is big enough (see below on
segundo 0:ac1725ba162c 179 * how that space is calculated). */
segundo 0:ac1725ba162c 180 #ifndef LWIP_RAM_HEAP_POINTER
segundo 0:ac1725ba162c 181 /** the heap. we need one struct mem at the end and some room for alignment */
segundo 0:ac1725ba162c 182 u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT] MEM_POSITION;
segundo 0:ac1725ba162c 183 #define LWIP_RAM_HEAP_POINTER ram_heap
segundo 0:ac1725ba162c 184 #endif /* LWIP_RAM_HEAP_POINTER */
segundo 0:ac1725ba162c 185
segundo 0:ac1725ba162c 186 /** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */
segundo 0:ac1725ba162c 187 static u8_t *ram;
segundo 0:ac1725ba162c 188 /** the last entry, always unused! */
segundo 0:ac1725ba162c 189 static struct mem *ram_end;
segundo 0:ac1725ba162c 190 /** pointer to the lowest free block, this is used for faster search */
segundo 0:ac1725ba162c 191 static struct mem *lfree;
segundo 0:ac1725ba162c 192
segundo 0:ac1725ba162c 193 /** concurrent access protection */
segundo 0:ac1725ba162c 194 static sys_mutex_t mem_mutex;
segundo 0:ac1725ba162c 195
segundo 0:ac1725ba162c 196 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 197
segundo 0:ac1725ba162c 198 static volatile u8_t mem_free_count;
segundo 0:ac1725ba162c 199
segundo 0:ac1725ba162c 200 /* Allow mem_free from other (e.g. interrupt) context */
segundo 0:ac1725ba162c 201 #define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free)
segundo 0:ac1725ba162c 202 #define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free)
segundo 0:ac1725ba162c 203 #define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free)
segundo 0:ac1725ba162c 204 #define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
segundo 0:ac1725ba162c 205 #define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc)
segundo 0:ac1725ba162c 206 #define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc)
segundo 0:ac1725ba162c 207
segundo 0:ac1725ba162c 208 #else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 209
segundo 0:ac1725ba162c 210 /* Protect the heap only by using a semaphore */
segundo 0:ac1725ba162c 211 #define LWIP_MEM_FREE_DECL_PROTECT()
segundo 0:ac1725ba162c 212 #define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex)
segundo 0:ac1725ba162c 213 #define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex)
segundo 0:ac1725ba162c 214 /* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
segundo 0:ac1725ba162c 215 #define LWIP_MEM_ALLOC_DECL_PROTECT()
segundo 0:ac1725ba162c 216 #define LWIP_MEM_ALLOC_PROTECT()
segundo 0:ac1725ba162c 217 #define LWIP_MEM_ALLOC_UNPROTECT()
segundo 0:ac1725ba162c 218
segundo 0:ac1725ba162c 219 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 220
segundo 0:ac1725ba162c 221
segundo 0:ac1725ba162c 222 /**
segundo 0:ac1725ba162c 223 * "Plug holes" by combining adjacent empty struct mems.
segundo 0:ac1725ba162c 224 * After this function is through, there should not exist
segundo 0:ac1725ba162c 225 * one empty struct mem pointing to another empty struct mem.
segundo 0:ac1725ba162c 226 *
segundo 0:ac1725ba162c 227 * @param mem this points to a struct mem which just has been freed
segundo 0:ac1725ba162c 228 * @internal this function is only called by mem_free() and mem_trim()
segundo 0:ac1725ba162c 229 *
segundo 0:ac1725ba162c 230 * This assumes access to the heap is protected by the calling function
segundo 0:ac1725ba162c 231 * already.
segundo 0:ac1725ba162c 232 */
segundo 0:ac1725ba162c 233 static void
segundo 0:ac1725ba162c 234 plug_holes(struct mem *mem)
segundo 0:ac1725ba162c 235 {
segundo 0:ac1725ba162c 236 struct mem *nmem;
segundo 0:ac1725ba162c 237 struct mem *pmem;
segundo 0:ac1725ba162c 238
segundo 0:ac1725ba162c 239 LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
segundo 0:ac1725ba162c 240 LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
segundo 0:ac1725ba162c 241 LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
segundo 0:ac1725ba162c 242
segundo 0:ac1725ba162c 243 /* plug hole forward */
segundo 0:ac1725ba162c 244 LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
segundo 0:ac1725ba162c 245
segundo 0:ac1725ba162c 246 nmem = (struct mem *)(void *)&ram[mem->next];
segundo 0:ac1725ba162c 247 if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
segundo 0:ac1725ba162c 248 /* if mem->next is unused and not end of ram, combine mem and mem->next */
segundo 0:ac1725ba162c 249 if (lfree == nmem) {
segundo 0:ac1725ba162c 250 lfree = mem;
segundo 0:ac1725ba162c 251 }
segundo 0:ac1725ba162c 252 mem->next = nmem->next;
segundo 0:ac1725ba162c 253 ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
segundo 0:ac1725ba162c 254 }
segundo 0:ac1725ba162c 255
segundo 0:ac1725ba162c 256 /* plug hole backward */
segundo 0:ac1725ba162c 257 pmem = (struct mem *)(void *)&ram[mem->prev];
segundo 0:ac1725ba162c 258 if (pmem != mem && pmem->used == 0) {
segundo 0:ac1725ba162c 259 /* if mem->prev is unused, combine mem and mem->prev */
segundo 0:ac1725ba162c 260 if (lfree == mem) {
segundo 0:ac1725ba162c 261 lfree = pmem;
segundo 0:ac1725ba162c 262 }
segundo 0:ac1725ba162c 263 pmem->next = mem->next;
segundo 0:ac1725ba162c 264 ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
segundo 0:ac1725ba162c 265 }
segundo 0:ac1725ba162c 266 }
segundo 0:ac1725ba162c 267
segundo 0:ac1725ba162c 268 /**
segundo 0:ac1725ba162c 269 * Zero the heap and initialize start, end and lowest-free
segundo 0:ac1725ba162c 270 */
segundo 0:ac1725ba162c 271 void
segundo 0:ac1725ba162c 272 mem_init(void)
segundo 0:ac1725ba162c 273 {
segundo 0:ac1725ba162c 274 struct mem *mem;
segundo 0:ac1725ba162c 275
segundo 0:ac1725ba162c 276 LWIP_ASSERT("Sanity check alignment",
segundo 0:ac1725ba162c 277 (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
segundo 0:ac1725ba162c 278
segundo 0:ac1725ba162c 279 /* align the heap */
segundo 0:ac1725ba162c 280 ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
segundo 0:ac1725ba162c 281 /* initialize the start of the heap */
segundo 0:ac1725ba162c 282 mem = (struct mem *)(void *)ram;
segundo 0:ac1725ba162c 283 mem->next = MEM_SIZE_ALIGNED;
segundo 0:ac1725ba162c 284 mem->prev = 0;
segundo 0:ac1725ba162c 285 mem->used = 0;
segundo 0:ac1725ba162c 286 /* initialize the end of the heap */
segundo 0:ac1725ba162c 287 ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
segundo 0:ac1725ba162c 288 ram_end->used = 1;
segundo 0:ac1725ba162c 289 ram_end->next = MEM_SIZE_ALIGNED;
segundo 0:ac1725ba162c 290 ram_end->prev = MEM_SIZE_ALIGNED;
segundo 0:ac1725ba162c 291
segundo 0:ac1725ba162c 292 /* initialize the lowest-free pointer to the start of the heap */
segundo 0:ac1725ba162c 293 lfree = (struct mem *)(void *)ram;
segundo 0:ac1725ba162c 294
segundo 0:ac1725ba162c 295 MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
segundo 0:ac1725ba162c 296
segundo 0:ac1725ba162c 297 if(sys_mutex_new(&mem_mutex) != ERR_OK) {
segundo 0:ac1725ba162c 298 LWIP_ASSERT("failed to create mem_mutex", 0);
segundo 0:ac1725ba162c 299 }
segundo 0:ac1725ba162c 300 }
segundo 0:ac1725ba162c 301
segundo 0:ac1725ba162c 302 /**
segundo 0:ac1725ba162c 303 * Put a struct mem back on the heap
segundo 0:ac1725ba162c 304 *
segundo 0:ac1725ba162c 305 * @param rmem is the data portion of a struct mem as returned by a previous
segundo 0:ac1725ba162c 306 * call to mem_malloc()
segundo 0:ac1725ba162c 307 */
segundo 0:ac1725ba162c 308 void
segundo 0:ac1725ba162c 309 mem_free(void *rmem)
segundo 0:ac1725ba162c 310 {
segundo 0:ac1725ba162c 311 struct mem *mem;
segundo 0:ac1725ba162c 312 LWIP_MEM_FREE_DECL_PROTECT();
segundo 0:ac1725ba162c 313
segundo 0:ac1725ba162c 314 if (rmem == NULL) {
segundo 0:ac1725ba162c 315 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
segundo 0:ac1725ba162c 316 return;
segundo 0:ac1725ba162c 317 }
segundo 0:ac1725ba162c 318 LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
segundo 0:ac1725ba162c 319
segundo 0:ac1725ba162c 320 LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
segundo 0:ac1725ba162c 321 (u8_t *)rmem < (u8_t *)ram_end);
segundo 0:ac1725ba162c 322
segundo 0:ac1725ba162c 323 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
segundo 0:ac1725ba162c 324 SYS_ARCH_DECL_PROTECT(lev);
segundo 0:ac1725ba162c 325 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
segundo 0:ac1725ba162c 326 /* protect mem stats from concurrent access */
segundo 0:ac1725ba162c 327 SYS_ARCH_PROTECT(lev);
segundo 0:ac1725ba162c 328 MEM_STATS_INC(illegal);
segundo 0:ac1725ba162c 329 SYS_ARCH_UNPROTECT(lev);
segundo 0:ac1725ba162c 330 return;
segundo 0:ac1725ba162c 331 }
segundo 0:ac1725ba162c 332 /* protect the heap from concurrent access */
segundo 0:ac1725ba162c 333 LWIP_MEM_FREE_PROTECT();
segundo 0:ac1725ba162c 334 /* Get the corresponding struct mem ... */
segundo 0:ac1725ba162c 335 mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
segundo 0:ac1725ba162c 336 /* ... which has to be in a used state ... */
segundo 0:ac1725ba162c 337 LWIP_ASSERT("mem_free: mem->used", mem->used);
segundo 0:ac1725ba162c 338 /* ... and is now unused. */
segundo 0:ac1725ba162c 339 mem->used = 0;
segundo 0:ac1725ba162c 340
segundo 0:ac1725ba162c 341 if (mem < lfree) {
segundo 0:ac1725ba162c 342 /* the newly freed struct is now the lowest */
segundo 0:ac1725ba162c 343 lfree = mem;
segundo 0:ac1725ba162c 344 }
segundo 0:ac1725ba162c 345
segundo 0:ac1725ba162c 346 MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
segundo 0:ac1725ba162c 347
segundo 0:ac1725ba162c 348 /* finally, see if prev or next are free also */
segundo 0:ac1725ba162c 349 plug_holes(mem);
segundo 0:ac1725ba162c 350 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 351 mem_free_count = 1;
segundo 0:ac1725ba162c 352 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 353 LWIP_MEM_FREE_UNPROTECT();
segundo 0:ac1725ba162c 354 }
segundo 0:ac1725ba162c 355
segundo 0:ac1725ba162c 356 /**
segundo 0:ac1725ba162c 357 * Shrink memory returned by mem_malloc().
segundo 0:ac1725ba162c 358 *
segundo 0:ac1725ba162c 359 * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked
segundo 0:ac1725ba162c 360 * @param newsize required size after shrinking (needs to be smaller than or
segundo 0:ac1725ba162c 361 * equal to the previous size)
segundo 0:ac1725ba162c 362 * @return for compatibility reasons: is always == rmem, at the moment
segundo 0:ac1725ba162c 363 * or NULL if newsize is > old size, in which case rmem is NOT touched
segundo 0:ac1725ba162c 364 * or freed!
segundo 0:ac1725ba162c 365 */
segundo 0:ac1725ba162c 366 void *
segundo 0:ac1725ba162c 367 mem_trim(void *rmem, mem_size_t newsize)
segundo 0:ac1725ba162c 368 {
segundo 0:ac1725ba162c 369 mem_size_t size;
segundo 0:ac1725ba162c 370 mem_size_t ptr, ptr2;
segundo 0:ac1725ba162c 371 struct mem *mem, *mem2;
segundo 0:ac1725ba162c 372 /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
segundo 0:ac1725ba162c 373 LWIP_MEM_FREE_DECL_PROTECT();
segundo 0:ac1725ba162c 374
segundo 0:ac1725ba162c 375 /* Expand the size of the allocated memory region so that we can
segundo 0:ac1725ba162c 376 adjust for alignment. */
segundo 0:ac1725ba162c 377 newsize = LWIP_MEM_ALIGN_SIZE(newsize);
segundo 0:ac1725ba162c 378
segundo 0:ac1725ba162c 379 if(newsize < MIN_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 380 /* every data block must be at least MIN_SIZE_ALIGNED long */
segundo 0:ac1725ba162c 381 newsize = MIN_SIZE_ALIGNED;
segundo 0:ac1725ba162c 382 }
segundo 0:ac1725ba162c 383
segundo 0:ac1725ba162c 384 if (newsize > MEM_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 385 return NULL;
segundo 0:ac1725ba162c 386 }
segundo 0:ac1725ba162c 387
segundo 0:ac1725ba162c 388 LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
segundo 0:ac1725ba162c 389 (u8_t *)rmem < (u8_t *)ram_end);
segundo 0:ac1725ba162c 390
segundo 0:ac1725ba162c 391 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
segundo 0:ac1725ba162c 392 SYS_ARCH_DECL_PROTECT(lev);
segundo 0:ac1725ba162c 393 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
segundo 0:ac1725ba162c 394 /* protect mem stats from concurrent access */
segundo 0:ac1725ba162c 395 SYS_ARCH_PROTECT(lev);
segundo 0:ac1725ba162c 396 MEM_STATS_INC(illegal);
segundo 0:ac1725ba162c 397 SYS_ARCH_UNPROTECT(lev);
segundo 0:ac1725ba162c 398 return rmem;
segundo 0:ac1725ba162c 399 }
segundo 0:ac1725ba162c 400 /* Get the corresponding struct mem ... */
segundo 0:ac1725ba162c 401 mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
segundo 0:ac1725ba162c 402 /* ... and its offset pointer */
segundo 0:ac1725ba162c 403 ptr = (mem_size_t)((u8_t *)mem - ram);
segundo 0:ac1725ba162c 404
segundo 0:ac1725ba162c 405 size = mem->next - ptr - SIZEOF_STRUCT_MEM;
segundo 0:ac1725ba162c 406 LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
segundo 0:ac1725ba162c 407 if (newsize > size) {
segundo 0:ac1725ba162c 408 /* not supported */
segundo 0:ac1725ba162c 409 return NULL;
segundo 0:ac1725ba162c 410 }
segundo 0:ac1725ba162c 411 if (newsize == size) {
segundo 0:ac1725ba162c 412 /* No change in size, simply return */
segundo 0:ac1725ba162c 413 return rmem;
segundo 0:ac1725ba162c 414 }
segundo 0:ac1725ba162c 415
segundo 0:ac1725ba162c 416 /* protect the heap from concurrent access */
segundo 0:ac1725ba162c 417 LWIP_MEM_FREE_PROTECT();
segundo 0:ac1725ba162c 418
segundo 0:ac1725ba162c 419 mem2 = (struct mem *)(void *)&ram[mem->next];
segundo 0:ac1725ba162c 420 if(mem2->used == 0) {
segundo 0:ac1725ba162c 421 /* The next struct is unused, we can simply move it at little */
segundo 0:ac1725ba162c 422 mem_size_t next;
segundo 0:ac1725ba162c 423 /* remember the old next pointer */
segundo 0:ac1725ba162c 424 next = mem2->next;
segundo 0:ac1725ba162c 425 /* create new struct mem which is moved directly after the shrinked mem */
segundo 0:ac1725ba162c 426 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
segundo 0:ac1725ba162c 427 if (lfree == mem2) {
segundo 0:ac1725ba162c 428 lfree = (struct mem *)(void *)&ram[ptr2];
segundo 0:ac1725ba162c 429 }
segundo 0:ac1725ba162c 430 mem2 = (struct mem *)(void *)&ram[ptr2];
segundo 0:ac1725ba162c 431 mem2->used = 0;
segundo 0:ac1725ba162c 432 /* restore the next pointer */
segundo 0:ac1725ba162c 433 mem2->next = next;
segundo 0:ac1725ba162c 434 /* link it back to mem */
segundo 0:ac1725ba162c 435 mem2->prev = ptr;
segundo 0:ac1725ba162c 436 /* link mem to it */
segundo 0:ac1725ba162c 437 mem->next = ptr2;
segundo 0:ac1725ba162c 438 /* last thing to restore linked list: as we have moved mem2,
segundo 0:ac1725ba162c 439 * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
segundo 0:ac1725ba162c 440 * the end of the heap */
segundo 0:ac1725ba162c 441 if (mem2->next != MEM_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 442 ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
segundo 0:ac1725ba162c 443 }
segundo 0:ac1725ba162c 444 MEM_STATS_DEC_USED(used, (size - newsize));
segundo 0:ac1725ba162c 445 /* no need to plug holes, we've already done that */
segundo 0:ac1725ba162c 446 } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
segundo 0:ac1725ba162c 447 /* Next struct is used but there's room for another struct mem with
segundo 0:ac1725ba162c 448 * at least MIN_SIZE_ALIGNED of data.
segundo 0:ac1725ba162c 449 * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
segundo 0:ac1725ba162c 450 * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
segundo 0:ac1725ba162c 451 * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
segundo 0:ac1725ba162c 452 * region that couldn't hold data, but when mem->next gets freed,
segundo 0:ac1725ba162c 453 * the 2 regions would be combined, resulting in more free memory */
segundo 0:ac1725ba162c 454 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
segundo 0:ac1725ba162c 455 mem2 = (struct mem *)(void *)&ram[ptr2];
segundo 0:ac1725ba162c 456 if (mem2 < lfree) {
segundo 0:ac1725ba162c 457 lfree = mem2;
segundo 0:ac1725ba162c 458 }
segundo 0:ac1725ba162c 459 mem2->used = 0;
segundo 0:ac1725ba162c 460 mem2->next = mem->next;
segundo 0:ac1725ba162c 461 mem2->prev = ptr;
segundo 0:ac1725ba162c 462 mem->next = ptr2;
segundo 0:ac1725ba162c 463 if (mem2->next != MEM_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 464 ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
segundo 0:ac1725ba162c 465 }
segundo 0:ac1725ba162c 466 MEM_STATS_DEC_USED(used, (size - newsize));
segundo 0:ac1725ba162c 467 /* the original mem->next is used, so no need to plug holes! */
segundo 0:ac1725ba162c 468 }
segundo 0:ac1725ba162c 469 /* else {
segundo 0:ac1725ba162c 470 next struct mem is used but size between mem and mem2 is not big enough
segundo 0:ac1725ba162c 471 to create another struct mem
segundo 0:ac1725ba162c 472 -> don't do anyhting.
segundo 0:ac1725ba162c 473 -> the remaining space stays unused since it is too small
segundo 0:ac1725ba162c 474 } */
segundo 0:ac1725ba162c 475 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 476 mem_free_count = 1;
segundo 0:ac1725ba162c 477 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 478 LWIP_MEM_FREE_UNPROTECT();
segundo 0:ac1725ba162c 479 return rmem;
segundo 0:ac1725ba162c 480 }
segundo 0:ac1725ba162c 481
segundo 0:ac1725ba162c 482 /**
segundo 0:ac1725ba162c 483 * Adam's mem_malloc() plus solution for bug #17922
segundo 0:ac1725ba162c 484 * Allocate a block of memory with a minimum of 'size' bytes.
segundo 0:ac1725ba162c 485 *
segundo 0:ac1725ba162c 486 * @param size is the minimum size of the requested block in bytes.
segundo 0:ac1725ba162c 487 * @return pointer to allocated memory or NULL if no free memory was found.
segundo 0:ac1725ba162c 488 *
segundo 0:ac1725ba162c 489 * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT).
segundo 0:ac1725ba162c 490 */
segundo 0:ac1725ba162c 491 void *
segundo 0:ac1725ba162c 492 mem_malloc(mem_size_t size)
segundo 0:ac1725ba162c 493 {
segundo 0:ac1725ba162c 494 mem_size_t ptr, ptr2;
segundo 0:ac1725ba162c 495 struct mem *mem, *mem2;
segundo 0:ac1725ba162c 496 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 497 u8_t local_mem_free_count = 0;
segundo 0:ac1725ba162c 498 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 499 LWIP_MEM_ALLOC_DECL_PROTECT();
segundo 0:ac1725ba162c 500
segundo 0:ac1725ba162c 501 if (size == 0) {
segundo 0:ac1725ba162c 502 return NULL;
segundo 0:ac1725ba162c 503 }
segundo 0:ac1725ba162c 504
segundo 0:ac1725ba162c 505 /* Expand the size of the allocated memory region so that we can
segundo 0:ac1725ba162c 506 adjust for alignment. */
segundo 0:ac1725ba162c 507 size = LWIP_MEM_ALIGN_SIZE(size);
segundo 0:ac1725ba162c 508
segundo 0:ac1725ba162c 509 if(size < MIN_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 510 /* every data block must be at least MIN_SIZE_ALIGNED long */
segundo 0:ac1725ba162c 511 size = MIN_SIZE_ALIGNED;
segundo 0:ac1725ba162c 512 }
segundo 0:ac1725ba162c 513
segundo 0:ac1725ba162c 514 if (size > MEM_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 515 return NULL;
segundo 0:ac1725ba162c 516 }
segundo 0:ac1725ba162c 517
segundo 0:ac1725ba162c 518 /* protect the heap from concurrent access */
segundo 0:ac1725ba162c 519 sys_mutex_lock(&mem_mutex);
segundo 0:ac1725ba162c 520 LWIP_MEM_ALLOC_PROTECT();
segundo 0:ac1725ba162c 521 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 522 /* run as long as a mem_free disturbed mem_malloc */
segundo 0:ac1725ba162c 523 do {
segundo 0:ac1725ba162c 524 local_mem_free_count = 0;
segundo 0:ac1725ba162c 525 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 526
segundo 0:ac1725ba162c 527 /* Scan through the heap searching for a free block that is big enough,
segundo 0:ac1725ba162c 528 * beginning with the lowest free block.
segundo 0:ac1725ba162c 529 */
segundo 0:ac1725ba162c 530 for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;
segundo 0:ac1725ba162c 531 ptr = ((struct mem *)(void *)&ram[ptr])->next) {
segundo 0:ac1725ba162c 532 mem = (struct mem *)(void *)&ram[ptr];
segundo 0:ac1725ba162c 533 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 534 mem_free_count = 0;
segundo 0:ac1725ba162c 535 LWIP_MEM_ALLOC_UNPROTECT();
segundo 0:ac1725ba162c 536 /* allow mem_free to run */
segundo 0:ac1725ba162c 537 LWIP_MEM_ALLOC_PROTECT();
segundo 0:ac1725ba162c 538 if (mem_free_count != 0) {
segundo 0:ac1725ba162c 539 local_mem_free_count = mem_free_count;
segundo 0:ac1725ba162c 540 }
segundo 0:ac1725ba162c 541 mem_free_count = 0;
segundo 0:ac1725ba162c 542 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 543
segundo 0:ac1725ba162c 544 if ((!mem->used) &&
segundo 0:ac1725ba162c 545 (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
segundo 0:ac1725ba162c 546 /* mem is not used and at least perfect fit is possible:
segundo 0:ac1725ba162c 547 * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
segundo 0:ac1725ba162c 548
segundo 0:ac1725ba162c 549 if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
segundo 0:ac1725ba162c 550 /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
segundo 0:ac1725ba162c 551 * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
segundo 0:ac1725ba162c 552 * -> split large block, create empty remainder,
segundo 0:ac1725ba162c 553 * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
segundo 0:ac1725ba162c 554 * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
segundo 0:ac1725ba162c 555 * struct mem would fit in but no data between mem2 and mem2->next
segundo 0:ac1725ba162c 556 * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
segundo 0:ac1725ba162c 557 * region that couldn't hold data, but when mem->next gets freed,
segundo 0:ac1725ba162c 558 * the 2 regions would be combined, resulting in more free memory
segundo 0:ac1725ba162c 559 */
segundo 0:ac1725ba162c 560 ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
segundo 0:ac1725ba162c 561 /* create mem2 struct */
segundo 0:ac1725ba162c 562 mem2 = (struct mem *)(void *)&ram[ptr2];
segundo 0:ac1725ba162c 563 mem2->used = 0;
segundo 0:ac1725ba162c 564 mem2->next = mem->next;
segundo 0:ac1725ba162c 565 mem2->prev = ptr;
segundo 0:ac1725ba162c 566 /* and insert it between mem and mem->next */
segundo 0:ac1725ba162c 567 mem->next = ptr2;
segundo 0:ac1725ba162c 568 mem->used = 1;
segundo 0:ac1725ba162c 569
segundo 0:ac1725ba162c 570 if (mem2->next != MEM_SIZE_ALIGNED) {
segundo 0:ac1725ba162c 571 ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
segundo 0:ac1725ba162c 572 }
segundo 0:ac1725ba162c 573 MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
segundo 0:ac1725ba162c 574 } else {
segundo 0:ac1725ba162c 575 /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
segundo 0:ac1725ba162c 576 * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
segundo 0:ac1725ba162c 577 * take care of this).
segundo 0:ac1725ba162c 578 * -> near fit or excact fit: do not split, no mem2 creation
segundo 0:ac1725ba162c 579 * also can't move mem->next directly behind mem, since mem->next
segundo 0:ac1725ba162c 580 * will always be used at this point!
segundo 0:ac1725ba162c 581 */
segundo 0:ac1725ba162c 582 mem->used = 1;
segundo 0:ac1725ba162c 583 MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram));
segundo 0:ac1725ba162c 584 }
segundo 0:ac1725ba162c 585
segundo 0:ac1725ba162c 586 if (mem == lfree) {
segundo 0:ac1725ba162c 587 /* Find next free block after mem and update lowest free pointer */
segundo 0:ac1725ba162c 588 while (lfree->used && lfree != ram_end) {
segundo 0:ac1725ba162c 589 LWIP_MEM_ALLOC_UNPROTECT();
segundo 0:ac1725ba162c 590 /* prevent high interrupt latency... */
segundo 0:ac1725ba162c 591 LWIP_MEM_ALLOC_PROTECT();
segundo 0:ac1725ba162c 592 lfree = (struct mem *)(void *)&ram[lfree->next];
segundo 0:ac1725ba162c 593 }
segundo 0:ac1725ba162c 594 LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
segundo 0:ac1725ba162c 595 }
segundo 0:ac1725ba162c 596 LWIP_MEM_ALLOC_UNPROTECT();
segundo 0:ac1725ba162c 597 sys_mutex_unlock(&mem_mutex);
segundo 0:ac1725ba162c 598 LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
segundo 0:ac1725ba162c 599 (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
segundo 0:ac1725ba162c 600 LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
segundo 0:ac1725ba162c 601 ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
segundo 0:ac1725ba162c 602 LWIP_ASSERT("mem_malloc: sanity check alignment",
segundo 0:ac1725ba162c 603 (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
segundo 0:ac1725ba162c 604
segundo 0:ac1725ba162c 605 return (u8_t *)mem + SIZEOF_STRUCT_MEM;
segundo 0:ac1725ba162c 606 }
segundo 0:ac1725ba162c 607 }
segundo 0:ac1725ba162c 608 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
segundo 0:ac1725ba162c 609 /* if we got interrupted by a mem_free, try again */
segundo 0:ac1725ba162c 610 } while(local_mem_free_count != 0);
segundo 0:ac1725ba162c 611 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
segundo 0:ac1725ba162c 612 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
segundo 0:ac1725ba162c 613 MEM_STATS_INC(err);
segundo 0:ac1725ba162c 614 LWIP_MEM_ALLOC_UNPROTECT();
segundo 0:ac1725ba162c 615 sys_mutex_unlock(&mem_mutex);
segundo 0:ac1725ba162c 616 return NULL;
segundo 0:ac1725ba162c 617 }
segundo 0:ac1725ba162c 618
segundo 0:ac1725ba162c 619 #endif /* MEM_USE_POOLS */
segundo 0:ac1725ba162c 620 /**
segundo 0:ac1725ba162c 621 * Contiguously allocates enough space for count objects that are size bytes
segundo 0:ac1725ba162c 622 * of memory each and returns a pointer to the allocated memory.
segundo 0:ac1725ba162c 623 *
segundo 0:ac1725ba162c 624 * The allocated memory is filled with bytes of value zero.
segundo 0:ac1725ba162c 625 *
segundo 0:ac1725ba162c 626 * @param count number of objects to allocate
segundo 0:ac1725ba162c 627 * @param size size of the objects to allocate
segundo 0:ac1725ba162c 628 * @return pointer to allocated memory / NULL pointer if there is an error
segundo 0:ac1725ba162c 629 */
segundo 0:ac1725ba162c 630 void *mem_calloc(mem_size_t count, mem_size_t size)
segundo 0:ac1725ba162c 631 {
segundo 0:ac1725ba162c 632 void *p;
segundo 0:ac1725ba162c 633
segundo 0:ac1725ba162c 634 /* allocate 'count' objects of size 'size' */
segundo 0:ac1725ba162c 635 p = mem_malloc(count * size);
segundo 0:ac1725ba162c 636 if (p) {
segundo 0:ac1725ba162c 637 /* zero the memory */
segundo 0:ac1725ba162c 638 memset(p, 0, count * size);
segundo 0:ac1725ba162c 639 }
segundo 0:ac1725ba162c 640 return p;
segundo 0:ac1725ba162c 641 }
segundo 0:ac1725ba162c 642
segundo 0:ac1725ba162c 643 #endif /* !MEM_LIBC_MALLOC */