]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/commitdiff
Introduced the option MEM_USE_POOLS to use 4 pools with different sized elements...
authorgoldsimon <goldsimon>
Thu, 21 Jun 2007 20:12:11 +0000 (20:12 +0000)
committergoldsimon <goldsimon>
Thu, 21 Jun 2007 20:12:11 +0000 (20:12 +0000)
CHANGELOG
src/core/mem.c
src/core/memp.c
src/include/lwip/mem.h
src/include/lwip/memp.h
src/include/lwip/opt.h

index 32585ebf4aae712c747782b44bc3a7315b469534..3d1478236b1d8737ea5d740200fdfd273512670c 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -19,6 +19,12 @@ HISTORY
 
   ++ New features:
 
+  2007-06-21 Simon Goldschmidt
+  * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option
+    MEM_USE_POOLS to use 4 pools with different sized elements instead of a
+    heap. This both prevents memory fragmentation and gives a higher speed
+    at the cost of more memory consumption. Turned off by default.
+
   2007-06-21 Simon Goldschmidt
   * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of
     netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into
index 12d91e1bf83dbabb80f38e34c1f838d8c5eca51b..99faf2ce6507d8bb738fde462d0c88e28e9fe123 100644 (file)
 
 #include "lwip/stats.h"
 
-#if (MEM_LIBC_MALLOC == 0)
+#if !MEM_LIBC_MALLOC
+#if MEM_USE_POOLS
+/* lwIP head implemented with different sized pools */
+
+/**
+ * This structure is used to save the pool one element came from.
+ */
+struct mem_helper
+{
+   memp_t poolnr;
+};
+
+/**
+ * Allocate memory: determine the smallest pool that is big enough
+ * to contain an element of 'size' and get an element from that pool.
+ *
+ * @param size the size in bytes of the memory needed
+ * @return a pointer to the allocated memory or NULL if the pool is empty
+ */
+void *
+mem_malloc(mem_size_t size)
+{
+  struct mem_helper *element;
+  int poolnr = -1;
+
+  for (poolnr = MEMP_MEM_POOL_1; poolnr < (MEMP_MEM_POOL_1 + MEM_POOL_COUNT); poolnr++) {
+    if ((size + sizeof(struct mem_helper)) <= memp_sizes[poolnr]) {
+      break;
+    }
+  }
+  if (poolnr == -1) {
+    LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
+    return NULL;
+  }
+  element = (struct mem_helper*)memp_malloc(poolnr);
+  if (element == NULL) {
+    /* No need to DEBUGF or ASSERT: This error is already
+       taken care of in memp.c */
+    /** @todo: we could try a bigger pool if this one is empty! */
+    return NULL;
+  }
+
+  element->poolnr = poolnr;
+  element++;
+
+  return element;
+}
+
+/**
+ * Free memory previously allocated by mem_malloc. Loads the pool number
+ * and calls memp_free with that pool number to put the element back into
+ * its pool
+ *
+ * @param rmem the memory element to free
+ */
+void
+mem_free(void *rmem)
+{
+  struct mem_helper *hmem = (struct mem_helper*)rmem;
+
+  LWIP_ASSERT("rmem != NULL", (rmem != NULL));
+  LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == MEM_ALIGN(rmem)));
+
+  hmem--;
+
+  LWIP_ASSERT("hmem != NULL", (hmem != NULL));
+  LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == MEM_ALIGN(hmem)));
+  LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
+
+  memp_free(hmem->poolnr, hmem);
+}
+
+#else /* MEM_USE_POOLS */
 /* lwIP replacement for your libc malloc() */
 
 /* This does not have to be aligned since for getting its size,
@@ -427,5 +499,5 @@ mem_malloc(mem_size_t size)
   return NULL;
 }
 
-#endif /* MEM_LIBC_MALLOC == 0 */
-
+#endif /* MEM_USE_POOLS */
+#endif /* !MEM_LIBC_MALLOC */
index 2edf2425441e972f422aea92d5fbb4ee6db9ab4b..98acb4ef0316d8d4bdc01bcf1fbc3e5e103bfff3 100644 (file)
@@ -99,7 +99,10 @@ static struct memp *memp_tab[MEMP_MAX];
 
 #endif /* MEMP_OVERFLOW_CHECK */
 
-static const u16_t memp_sizes[MEMP_MAX] = {
+#if !MEM_USE_POOLS
+static
+#endif
+const u16_t memp_sizes[MEMP_MAX] = {
   MEMP_ALIGN_SIZE(sizeof(struct pbuf)),
   MEMP_ALIGN_SIZE(sizeof(struct raw_pcb)),
   MEMP_ALIGN_SIZE(sizeof(struct udp_pcb)),
@@ -113,7 +116,13 @@ static const u16_t memp_sizes[MEMP_MAX] = {
   MEMP_ALIGN_SIZE(sizeof(struct etharp_q_entry)),
 #endif
   MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(PBUF_POOL_BUFSIZE),
-  MEMP_ALIGN_SIZE(sizeof(struct sys_timeo))
+  MEMP_ALIGN_SIZE(sizeof(struct sys_timeo)),
+#if MEM_USE_POOLS
+  MEMP_ALIGN_SIZE(MEM_POOL_SIZE_1),
+  MEMP_ALIGN_SIZE(MEM_POOL_SIZE_2),
+  MEMP_ALIGN_SIZE(MEM_POOL_SIZE_3),
+  MEMP_ALIGN_SIZE(MEM_POOL_SIZE_4),
+#endif
 };
 
 static const u16_t memp_num[MEMP_MAX] = {
@@ -130,7 +139,13 @@ static const u16_t memp_num[MEMP_MAX] = {
   MEMP_NUM_ARP_QUEUE,
 #endif
   PBUF_POOL_SIZE,
-  MEMP_NUM_SYS_TIMEOUT
+  MEMP_NUM_SYS_TIMEOUT,
+#if MEM_USE_POOLS
+  MEM_POOL_NUM_1,
+  MEM_POOL_NUM_2,
+  MEM_POOL_NUM_3,
+  MEM_POOL_NUM_4,
+#endif
 };
 
 #define MEMP_TYPE_SIZE(qty, type) \
@@ -150,8 +165,15 @@ static u8_t memp_memory[MEM_ALIGNMENT - 1 +
   MEMP_TYPE_SIZE(MEMP_NUM_ARP_QUEUE, struct etharp_q_entry) +
 #endif
   MEMP_TYPE_SIZE(PBUF_POOL_SIZE, struct pbuf) +
-                 PBUF_POOL_SIZE * MEMP_ALIGN_SIZE(PBUF_POOL_BUFSIZE) +
-  MEMP_TYPE_SIZE(MEMP_NUM_SYS_TIMEOUT, struct sys_timeo)];
+                 ((PBUF_POOL_SIZE) * MEMP_ALIGN_SIZE(PBUF_POOL_BUFSIZE)) +
+  MEMP_TYPE_SIZE(MEMP_NUM_SYS_TIMEOUT, struct sys_timeo)
+#if MEM_USE_POOLS
+  + ((MEM_POOL_NUM_1) * MEMP_ALIGN_SIZE(MEM_POOL_SIZE_1))
+  + ((MEM_POOL_NUM_2) * MEMP_ALIGN_SIZE(MEM_POOL_SIZE_2))
+  + ((MEM_POOL_NUM_3) * MEMP_ALIGN_SIZE(MEM_POOL_SIZE_3))
+  + ((MEM_POOL_NUM_4) * MEMP_ALIGN_SIZE(MEM_POOL_SIZE_4))
+#endif
+];
 
 #if MEMP_SANITY_CHECK
 /**
index b5894309c8e0c5e692ac9ab1db5faf69d895de1f..4091c964817e5e80fa11e0f480bc15f5d4226788 100644 (file)
@@ -66,11 +66,21 @@ typedef u16_t mem_size_t;
 #define mem_realloc(x, size) realloc(x,size)
 #endif
 #else /* MEM_LIBC_MALLOC */
+#if MEM_USE_POOLS
+/** The pool implementation of the heap currently uses 4 pools */
+#define MEM_POOL_COUNT   4
+/** mem_init is not used when using pools instead of a heap */
+#define mem_init()
+/** mem_realloc is not used when using pools instead of a heap:
+    we can't free part of a pool element and don't want to copy the rest */
+#define mem_realloc(mem, size) (mem)
+#else /* MEM_USE_POOLS */
 /* lwIP alternative malloc */
 void  mem_init(void);
+void *mem_realloc(void *mem, mem_size_t size);
+#endif /* MEM_USE_POOLS */
 void *mem_malloc(mem_size_t size);
 void  mem_free(void *mem);
-void *mem_realloc(void *mem, mem_size_t size);
 #endif /* MEM_LIBC_MALLOC */
 
 #ifndef LWIP_MEM_ALIGN_SIZE
index 64447c934b99b5987a24aa5266ce089ce8ebc0df..3f272b4c25903f1b2671d38d0267a40f6471e165 100644 (file)
@@ -56,6 +56,12 @@ typedef enum {
 #endif
   MEMP_PBUF_POOL,
   MEMP_SYS_TIMEOUT,
+#if MEM_USE_POOLS
+  MEMP_MEM_POOL_1,
+  MEMP_MEM_POOL_2,
+  MEMP_MEM_POOL_3,
+  MEMP_MEM_POOL_4,
+#endif
 
   MEMP_MAX
 } memp_t;
@@ -70,6 +76,10 @@ void *memp_malloc(memp_t type);
 #endif
 void  memp_free(memp_t type, void *mem);
 
+#if MEM_USE_POOLS
+extern const u16_t memp_sizes[MEMP_MAX];
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 5aca48b4aefcac26a0b0937b4ec179740eae1dce..0fd1d20a5f26334c6dcf3e7e98153c185b226dee 100644 (file)
@@ -66,6 +66,8 @@
 #endif
 
 /* ---------- Memory options ---------- */
+/* Use malloc/free/realloc provided by your C-library instead of the
+   lwip internal allocator. Can save code size if you already use it. */
 #ifndef MEM_LIBC_MALLOC
 #define MEM_LIBC_MALLOC                 0
 #endif
 /* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
    lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
    byte alignment -> define MEM_ALIGNMENT to 2. */
-
 #ifndef MEM_ALIGNMENT
 #define MEM_ALIGNMENT                   1
 #endif
 
+/* Memory can be allocated from 4 pools with element of different size.
+   When mem_malloc is called, and element of the smallest pool that can
+   provide the lenght needed is returned. */
+#ifndef MEM_USE_POOLS
+#define MEM_USE_POOLS                   0
+#endif
+
+#if MEM_USE_POOLS
+/* The element sizes of the 4 pools.
+   The sizes must be increasing, e.g. the elements in pool 2 must be
+   bigger than the elements in pool 1 and so on. If this is not the case,
+   mem_malloc will not work correctly. */
+#ifndef MEM_POOL_SIZE_1
+#error You must have at least one pool if MEM_USE_POOLS is set to 1!
+#endif
+#ifndef MEM_POOL_SIZE_2
+#define MEM_POOL_SIZE_2                 0
+#endif
+#ifndef MEM_POOL_SIZE_3
+#define MEM_POOL_SIZE_3                 0
+#endif
+#ifndef MEM_POOL_SIZE_4
+#define MEM_POOL_SIZE_4                 0
+#endif
+/* The element count of the 4 pools */
+#ifndef MEM_POOL_NUM_1
+#error You must have at least one pool if MEM_USE_POOLS is set to 1!
+#endif
+#ifndef MEM_POOL_NUM_2
+#define MEM_POOL_NUM_2                  0
+#endif
+#ifndef MEM_POOL_NUM_3
+#define MEM_POOL_NUM_3                  0
+#endif
+#ifndef MEM_POOL_NUM_4
+#define MEM_POOL_NUM_4                  0
+#endif
+#endif
+
 /* MEM_SIZE: the size of the heap memory. If the application will send
-a lot of data that needs to be copied, this should be set high. */
+   a lot of data that needs to be copied, this should be set high. */
 #ifndef MEM_SIZE
 #define MEM_SIZE                        1600
 #endif