STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
mem.c
Go to the documentation of this file.
1 
23 /*
24  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
25  * All rights reserved.
26  *
27  * Redistribution and use in source and binary forms, with or without modification,
28  * are permitted provided that the following conditions are met:
29  *
30  * 1. Redistributions of source code must retain the above copyright notice,
31  * this list of conditions and the following disclaimer.
32  * 2. Redistributions in binary form must reproduce the above copyright notice,
33  * this list of conditions and the following disclaimer in the documentation
34  * and/or other materials provided with the distribution.
35  * 3. The name of the author may not be used to endorse or promote products
36  * derived from this software without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
39  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
41  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
43  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
46  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
47  * OF SUCH DAMAGE.
48  *
49  * This file is part of the lwIP TCP/IP stack.
50  *
51  * Author: Adam Dunkels <adam@sics.se>
52  * Simon Goldschmidt
53  *
54  */
55 
56 #include "lwip/opt.h"
57 
58 #if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */
59 
60 #include "lwip/def.h"
61 #include "lwip/mem.h"
62 #include "lwip/sys.h"
63 #include "lwip/stats.h"
64 #include "lwip/err.h"
65 
66 #include <string.h>
67 
68 #if MEM_USE_POOLS
69 
70 #if MEMP_MEM_MALLOC
71 #error MEM_USE_POOLS and MEMP_MEM_MALLOC cannot be used together
72 #endif
73 
74 /* lwIP head implemented with different sized pools */
75 
83 void *
85 {
86  void *ret;
87  struct memp_malloc_helper *element;
88  memp_t poolnr;
89  mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
90 
91  for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
92 #if MEM_USE_POOLS_TRY_BIGGER_POOL
93 again:
94 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
95  /* is this pool big enough to hold an element of the required size
96  plus a struct memp_malloc_helper that saves the pool this element came from? */
97  if (required_size <= memp_pools[poolnr]->size) {
98  break;
99  }
100  }
101  if (poolnr > MEMP_POOL_LAST) {
102  LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
103  return NULL;
104  }
105  element = (struct memp_malloc_helper*)memp_malloc(poolnr);
106  if (element == NULL) {
107  /* No need to DEBUGF or ASSERT: This error is already
108  taken care of in memp.c */
109 #if MEM_USE_POOLS_TRY_BIGGER_POOL
110 
111  if (poolnr < MEMP_POOL_LAST) {
112  poolnr++;
113  goto again;
114  }
115 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
116  return NULL;
117  }
118 
119  /* save the pool number this element came from */
120  element->poolnr = poolnr;
121  /* and return a pointer to the memory directly after the struct memp_malloc_helper */
122  ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
123 
124 #if MEMP_OVERFLOW_CHECK
125  /* initialize unused memory */
126  element->size = size;
127  memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size);
128 #endif /* MEMP_OVERFLOW_CHECK */
129  return ret;
130 }
131 
139 void
140 mem_free(void *rmem)
141 {
142  struct memp_malloc_helper *hmem;
143 
144  LWIP_ASSERT("rmem != NULL", (rmem != NULL));
145  LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
146 
147  /* get the original struct memp_malloc_helper */
148  hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)));
149 
150  LWIP_ASSERT("hmem != NULL", (hmem != NULL));
151  LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
152  LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
153 
154 #if MEMP_OVERFLOW_CHECK
155  {
156  u16_t i;
157  LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size",
158  hmem->size <= memp_pools[hmem->poolnr]->size);
159  /* check that unused memory remained untouched */
160  for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) {
161  u8_t data = *((u8_t*)rmem + i);
162  LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd);
163  }
164  }
165 #endif /* MEMP_OVERFLOW_CHECK */
166 
167  /* and put it in the pool we saved earlier */
168  memp_free(hmem->poolnr, hmem);
169 }
170 
171 #else /* MEM_USE_POOLS */
172 /* lwIP replacement for your libc malloc() */
173 
179 struct mem {
186 };
187 
191 #ifndef MIN_SIZE
192 #define MIN_SIZE 12
193 #endif /* MIN_SIZE */
194 /* some alignment macros: we define them here for better source code layout */
195 #define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
196 #define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
197 #define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
198 
203 #ifndef LWIP_RAM_HEAP_POINTER
204 
206 #define LWIP_RAM_HEAP_POINTER ram_heap
207 #endif /* LWIP_RAM_HEAP_POINTER */
208 
210 static u8_t *ram;
212 static struct mem *ram_end;
214 static struct mem *lfree;
215 
217 #if !NO_SYS
218 static sys_mutex_t mem_mutex;
219 #endif
220 
221 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
222 
223 static volatile u8_t mem_free_count;
224 
225 /* Allow mem_free from other (e.g. interrupt) context */
226 #define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free)
227 #define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free)
228 #define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free)
229 #define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
230 #define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc)
231 #define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc)
232 
233 #else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
234 
235 /* Protect the heap only by using a semaphore */
236 #define LWIP_MEM_FREE_DECL_PROTECT()
237 #define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex)
238 #define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex)
239 /* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
240 #define LWIP_MEM_ALLOC_DECL_PROTECT()
241 #define LWIP_MEM_ALLOC_PROTECT()
242 #define LWIP_MEM_ALLOC_UNPROTECT()
243 
244 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
245 
246 
258 static void
259 plug_holes(struct mem *mem)
260 {
261  struct mem *nmem;
262  struct mem *pmem;
263 
264  LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
265  LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
266  LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
267 
268  /* plug hole forward */
269  LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
270 
271  nmem = (struct mem *)(void *)&ram[mem->next];
272  if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
273  /* if mem->next is unused and not end of ram, combine mem and mem->next */
274  if (lfree == nmem) {
275  lfree = mem;
276  }
277  mem->next = nmem->next;
278  ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
279  }
280 
281  /* plug hole backward */
282  pmem = (struct mem *)(void *)&ram[mem->prev];
283  if (pmem != mem && pmem->used == 0) {
284  /* if mem->prev is unused, combine mem and mem->prev */
285  if (lfree == mem) {
286  lfree = pmem;
287  }
288  pmem->next = mem->next;
289  ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
290  }
291 }
292 
296 void
297 mem_init(void)
298 {
299  struct mem *mem;
300 
301  LWIP_ASSERT("Sanity check alignment",
302  (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
303 
304  /* align the heap */
306  /* initialize the start of the heap */
307  mem = (struct mem *)(void *)ram;
308  mem->next = MEM_SIZE_ALIGNED;
309  mem->prev = 0;
310  mem->used = 0;
311  /* initialize the end of the heap */
312  ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
313  ram_end->used = 1;
314  ram_end->next = MEM_SIZE_ALIGNED;
315  ram_end->prev = MEM_SIZE_ALIGNED;
316 
317  /* initialize the lowest-free pointer to the start of the heap */
318  lfree = (struct mem *)(void *)ram;
319 
321 
322  if (sys_mutex_new(&mem_mutex) != ERR_OK) {
323  LWIP_ASSERT("failed to create mem_mutex", 0);
324  }
325 }
326 
333 void
334 mem_free(void *rmem)
335 {
336  struct mem *mem;
338 
339  if (rmem == NULL) {
340  LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
341  return;
342  }
343  LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
344 
345  LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
346  (u8_t *)rmem < (u8_t *)ram_end);
347 
348  if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
350  LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
351  /* protect mem stats from concurrent access */
352  SYS_ARCH_PROTECT(lev);
353  MEM_STATS_INC(illegal);
354  SYS_ARCH_UNPROTECT(lev);
355  return;
356  }
357  /* protect the heap from concurrent access */
359  /* Get the corresponding struct mem ... */
360  mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
361  /* ... which has to be in a used state ... */
362  LWIP_ASSERT("mem_free: mem->used", mem->used);
363  /* ... and is now unused. */
364  mem->used = 0;
365 
366  if (mem < lfree) {
367  /* the newly freed struct is now the lowest */
368  lfree = mem;
369  }
370 
371  MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
372 
373  /* finally, see if prev or next are free also */
374  plug_holes(mem);
375 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
376  mem_free_count = 1;
377 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
379 }
380 
391 void *
392 mem_trim(void *rmem, mem_size_t newsize)
393 {
394  mem_size_t size;
395  mem_size_t ptr, ptr2;
396  struct mem *mem, *mem2;
397  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
399 
400  /* Expand the size of the allocated memory region so that we can
401  adjust for alignment. */
402  newsize = LWIP_MEM_ALIGN_SIZE(newsize);
403 
404  if (newsize < MIN_SIZE_ALIGNED) {
405  /* every data block must be at least MIN_SIZE_ALIGNED long */
406  newsize = MIN_SIZE_ALIGNED;
407  }
408 
409  if (newsize > MEM_SIZE_ALIGNED) {
410  return NULL;
411  }
412 
413  LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
414  (u8_t *)rmem < (u8_t *)ram_end);
415 
416  if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
418  LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
419  /* protect mem stats from concurrent access */
420  SYS_ARCH_PROTECT(lev);
421  MEM_STATS_INC(illegal);
422  SYS_ARCH_UNPROTECT(lev);
423  return rmem;
424  }
425  /* Get the corresponding struct mem ... */
426  mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
427  /* ... and its offset pointer */
428  ptr = (mem_size_t)((u8_t *)mem - ram);
429 
430  size = mem->next - ptr - SIZEOF_STRUCT_MEM;
431  LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
432  if (newsize > size) {
433  /* not supported */
434  return NULL;
435  }
436  if (newsize == size) {
437  /* No change in size, simply return */
438  return rmem;
439  }
440 
441  /* protect the heap from concurrent access */
443 
444  mem2 = (struct mem *)(void *)&ram[mem->next];
445  if (mem2->used == 0) {
446  /* The next struct is unused, we can simply move it at little */
448  /* remember the old next pointer */
449  next = mem2->next;
450  /* create new struct mem which is moved directly after the shrinked mem */
451  ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
452  if (lfree == mem2) {
453  lfree = (struct mem *)(void *)&ram[ptr2];
454  }
455  mem2 = (struct mem *)(void *)&ram[ptr2];
456  mem2->used = 0;
457  /* restore the next pointer */
458  mem2->next = next;
459  /* link it back to mem */
460  mem2->prev = ptr;
461  /* link mem to it */
462  mem->next = ptr2;
463  /* last thing to restore linked list: as we have moved mem2,
464  * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
465  * the end of the heap */
466  if (mem2->next != MEM_SIZE_ALIGNED) {
467  ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
468  }
469  MEM_STATS_DEC_USED(used, (size - newsize));
470  /* no need to plug holes, we've already done that */
471  } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
472  /* Next struct is used but there's room for another struct mem with
473  * at least MIN_SIZE_ALIGNED of data.
474  * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
475  * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
476  * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
477  * region that couldn't hold data, but when mem->next gets freed,
478  * the 2 regions would be combined, resulting in more free memory */
479  ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
480  mem2 = (struct mem *)(void *)&ram[ptr2];
481  if (mem2 < lfree) {
482  lfree = mem2;
483  }
484  mem2->used = 0;
485  mem2->next = mem->next;
486  mem2->prev = ptr;
487  mem->next = ptr2;
488  if (mem2->next != MEM_SIZE_ALIGNED) {
489  ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
490  }
491  MEM_STATS_DEC_USED(used, (size - newsize));
492  /* the original mem->next is used, so no need to plug holes! */
493  }
494  /* else {
495  next struct mem is used but size between mem and mem2 is not big enough
496  to create another struct mem
497  -> don't do anyhting.
498  -> the remaining space stays unused since it is too small
499  } */
500 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
501  mem_free_count = 1;
502 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
504  return rmem;
505 }
506 
516 void *
518 {
519  mem_size_t ptr, ptr2;
520  struct mem *mem, *mem2;
521 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
522  u8_t local_mem_free_count = 0;
523 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
525 
526  if (size == 0) {
527  return NULL;
528  }
529 
530  /* Expand the size of the allocated memory region so that we can
531  adjust for alignment. */
532  size = LWIP_MEM_ALIGN_SIZE(size);
533 
534  if (size < MIN_SIZE_ALIGNED) {
535  /* every data block must be at least MIN_SIZE_ALIGNED long */
536  size = MIN_SIZE_ALIGNED;
537  }
538 
539  if (size > MEM_SIZE_ALIGNED) {
540  return NULL;
541  }
542 
543  /* protect the heap from concurrent access */
544  sys_mutex_lock(&mem_mutex);
546 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
547  /* run as long as a mem_free disturbed mem_malloc or mem_trim */
548  do {
549  local_mem_free_count = 0;
550 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
551 
552  /* Scan through the heap searching for a free block that is big enough,
553  * beginning with the lowest free block.
554  */
555  for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;
556  ptr = ((struct mem *)(void *)&ram[ptr])->next) {
557  mem = (struct mem *)(void *)&ram[ptr];
558 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
559  mem_free_count = 0;
561  /* allow mem_free or mem_trim to run */
563  if (mem_free_count != 0) {
564  /* If mem_free or mem_trim have run, we have to restart since they
565  could have altered our current struct mem. */
566  local_mem_free_count = 1;
567  break;
568  }
569 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
570 
571  if ((!mem->used) &&
572  (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
573  /* mem is not used and at least perfect fit is possible:
574  * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
575 
576  if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
577  /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
578  * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
579  * -> split large block, create empty remainder,
580  * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
581  * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
582  * struct mem would fit in but no data between mem2 and mem2->next
583  * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
584  * region that couldn't hold data, but when mem->next gets freed,
585  * the 2 regions would be combined, resulting in more free memory
586  */
587  ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
588  /* create mem2 struct */
589  mem2 = (struct mem *)(void *)&ram[ptr2];
590  mem2->used = 0;
591  mem2->next = mem->next;
592  mem2->prev = ptr;
593  /* and insert it between mem and mem->next */
594  mem->next = ptr2;
595  mem->used = 1;
596 
597  if (mem2->next != MEM_SIZE_ALIGNED) {
598  ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
599  }
601  } else {
602  /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
603  * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
604  * take care of this).
605  * -> near fit or exact fit: do not split, no mem2 creation
606  * also can't move mem->next directly behind mem, since mem->next
607  * will always be used at this point!
608  */
609  mem->used = 1;
610  MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram));
611  }
612 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
613 mem_malloc_adjust_lfree:
614 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
615  if (mem == lfree) {
616  struct mem *cur = lfree;
617  /* Find next free block after mem and update lowest free pointer */
618  while (cur->used && cur != ram_end) {
619 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
620  mem_free_count = 0;
622  /* prevent high interrupt latency... */
624  if (mem_free_count != 0) {
625  /* If mem_free or mem_trim have run, we have to restart since they
626  could have altered our current struct mem or lfree. */
627  goto mem_malloc_adjust_lfree;
628  }
629 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
630  cur = (struct mem *)(void *)&ram[cur->next];
631  }
632  lfree = cur;
633  LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
634  }
636  sys_mutex_unlock(&mem_mutex);
637  LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
638  (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
639  LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
640  ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
641  LWIP_ASSERT("mem_malloc: sanity check alignment",
642  (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
643 
644  return (u8_t *)mem + SIZEOF_STRUCT_MEM;
645  }
646  }
647 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
648  /* if we got interrupted by a mem_free, try again */
649  } while (local_mem_free_count != 0);
650 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
651  LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
652  MEM_STATS_INC(err);
654  sys_mutex_unlock(&mem_mutex);
655  return NULL;
656 }
657 
658 #endif /* MEM_USE_POOLS */
659 
669 void *mem_calloc(mem_size_t count, mem_size_t size)
670 {
671  void *p;
672 
673  /* allocate 'count' objects of size 'size' */
674  p = mem_malloc(count * size);
675  if (p) {
676  /* zero the memory */
677  memset(p, 0, (size_t)count * (size_t)size);
678  }
679  return p;
680 }
681 
682 #endif /* !MEM_LIBC_MALLOC */
683 
Definition: memp.h:48
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.c:339
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
u8_t ram_heap[MEM_SIZE_ALIGNED+(2U *SIZEOF_STRUCT_MEM)+MEM_ALIGNMENT]
Definition: mem.c:205
u16_t mem_size_t
Definition: mem.h:76
void mem_free(void *rmem)
Definition: mem.c:334
#define LWIP_MEM_ALLOC_PROTECT()
Definition: mem.c:241
memp_t
Definition: memp.h:45
#define LWIP_MEM_FREE_DECL_PROTECT()
Definition: mem.c:236
#define LWIP_MEM_FREE_PROTECT()
Definition: mem.c:237
signed short s16_t
Definition: cc.h:41
#define SIZEOF_STRUCT_MEM
Definition: mem.c:196
mem_size_t prev
Definition: mem.c:183
void sys_mutex_unlock(sys_mutex_t *mutex)
Definition: sys_arch.c:377
#define MEM_STATS_INC(x)
Definition: stats.h:330
void sys_mutex_lock(sys_mutex_t *mutex)
Definition: sys_arch.c:370
void memp_free(memp_t type, void *mem)
Definition: memp.c:399
#define MEM_STATS_AVAIL(x, y)
Definition: stats.h:329
u32_t mem_ptr_t
Definition: cc.h:44
#define MEM_ALIGNMENT
Definition: lwipopts.h:73
#define SYS_ARCH_DECL_PROTECT(lev)
Definition: sys.h:304
u8_t used
Definition: mem.c:185
void * mem_trim(void *rmem, mem_size_t newsize)
Definition: mem.c:392
#define NULL
Definition: usbd_def.h:53
#define LWIP_MEM_ALLOC_DECL_PROTECT()
Definition: mem.c:240
const struct memp_desc * memp_pools[MEMP_MAX]
Definition: memp.c:75
#define ERR_OK
Definition: err.h:52
void mem_init(void)
Definition: mem.c:297
void * mem_calloc(mem_size_t count, mem_size_t size)
Definition: mem.c:669
#define LWIP_DBG_TRACE
Definition: debug.h:57
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:70
mem_size_t next
Definition: mem.c:181
#define S16_F
Definition: cc.h:49
u16_t size
Definition: memp_priv.h:124
#define LWIP_DBG_LEVEL_SEVERE
Definition: debug.h:48
unsigned char u8_t
Definition: cc.h:38
#define SYS_ARCH_PROTECT(lev)
Definition: sys.h:305
#define LWIP_RAM_HEAP_POINTER
Definition: mem.c:206
#define LWIP_MEM_ALIGN(addr)
Definition: mem.h:116
#define SYS_ARCH_UNPROTECT(lev)
Definition: sys.h:306
Definition: mem.c:179
void * mem_malloc(mem_size_t size)
Definition: mem.c:517
#define LWIP_MEM_ALIGN_SIZE(size)
Definition: mem.h:101
#define MEM_STATS_INC_USED(x, y)
Definition: stats.h:331
#define MEM_STATS_DEC_USED(x, y)
Definition: stats.h:332
#define MEM_DEBUG
Definition: opt.h:2858
#define MEM_SIZE_ALIGNED
Definition: mem.c:197
void * memp_malloc(memp_t type)
Definition: memp.c:303
#define LWIP_MEM_ALLOC_UNPROTECT()
Definition: mem.c:242
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:113
#define MIN_SIZE_ALIGNED
Definition: mem.c:195
unsigned short u16_t
Definition: cc.h:40
#define LWIP_MEM_FREE_UNPROTECT()
Definition: mem.c:238
osSemaphoreId sys_mutex_t
Definition: sys_arch.h:45