mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +00:00
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.
This commit is contained in:
parent
065b8c945b
commit
0c18e653e8
@ -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
|
||||
|
@ -48,7 +48,79 @@
|
||||
|
||||
#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 */
|
||||
|
@ -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
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -73,13 +75,51 @@
|
||||
/* 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
|
||||
|
Loading…
Reference in New Issue
Block a user