[MEDIUM] implement memory pools version 2
The new pools know about their size and usage. Malloc is not used
anymore, instead a dedicated function to refill the entries is used.
diff --git a/Makefile b/Makefile
index c7017e5..122f1c6 100644
--- a/Makefile
+++ b/Makefile
@@ -217,7 +217,7 @@
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
- src/session.o src/hdr_idx.o src/ev_select.o src/acl.o
+ src/session.o src/hdr_idx.o src/ev_select.o src/acl.o src/memory.o
haproxy: $(OBJS) $(OPT_OBJS)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
diff --git a/Makefile.bsd b/Makefile.bsd
index 76fe256..945b08e 100644
--- a/Makefile.bsd
+++ b/Makefile.bsd
@@ -88,7 +88,7 @@
src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o \
- src/ev_kqueue.o src/acl.o
+ src/ev_kqueue.o src/acl.o src/memory.o
all: haproxy
diff --git a/Makefile.osx b/Makefile.osx
index 15db775..0618e68 100644
--- a/Makefile.osx
+++ b/Makefile.osx
@@ -87,7 +87,8 @@
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
- src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o src/acl.o
+ src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o src/acl.o \
+ src/memory.o
all: haproxy
diff --git a/include/common/config.h b/include/common/config.h
index e8d8ad2..85deeae 100644
--- a/include/common/config.h
+++ b/include/common/config.h
@@ -2,7 +2,7 @@
include/common/config.h
This files contains most of the user-configurable settings.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -39,6 +39,27 @@
# define CONFIG_HAP_MEM_OPTIM
#endif /* CONFIG_HAP_NO_MEM_OPTIM */
+/* CONFIG_HAP_MALLOC / CONFIG_HAP_CALLOC / CONFIG_HAP_FREE
+ * This macro allows to replace the malloc function with another one.
+ */
+#ifdef CONFIG_HAP_MALLOC
+#define MALLOC CONFIG_HAP_MALLOC
+#else
+#define MALLOC malloc
+#endif
+
+#ifdef CONFIG_HAP_CALLOC
+#define CALLOC CONFIG_HAP_CALLOC
+#else
+#define CALLOC calloc
+#endif
+
+#ifdef CONFIG_HAP_FREE
+#define FREE CONFIG_HAP_FREE
+#else
+#define FREE free
+#endif
+
/* CONFIG_HAP_INLINE_FD_SET
* This makes use of inline FD_* macros instead of calling equivalent
diff --git a/include/common/memory.h b/include/common/memory.h
index 820c1d9..77346b7 100644
--- a/include/common/memory.h
+++ b/include/common/memory.h
@@ -2,7 +2,7 @@
include/common/memory.h
Memory management definitions..
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <common/config.h>
+#include <common/mini-clist.h>
#define sizeof_requri REQURI_LEN
#define sizeof_capture CAPTURE_LEN
@@ -112,6 +113,73 @@
}
}
+
+/******* pools version 2 ********/
+
+#define MEM_F_SHARED 0x1
+
+struct pool_head {
+ void **free_list;
+ struct list list; /* list of all known pools */
+ unsigned int used; /* how many chunks are currently in use */
+ unsigned int allocated; /* how many chunks have been allocated */
+ unsigned int limit; /* hard limit on the number of chunks */
+ unsigned int minavail; /* how many chunks are expected to be used */
+ unsigned int size; /* chunk size */
+ unsigned int flags; /* MEM_F_* */
+ char name[9]; /* name of the pool */
+};
+
+
+/* Allocate a new entry for pool <pool>, and return it for immediate use.
+ * NULL is returned if no memory is available for a new creation.
+ */
+void *refill_pool_alloc(struct pool_head *pool);
+
+/* Try to find an existing shared pool with the same characteristics and
+ * returns it, otherwise creates this one. NULL is returned if no memory
+ * is available for a new creation.
+ */
+struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
+
+/* Dump statistics on pools usage.
+ */
+void dump_pools(void);
+
+/*
+ * Returns a pointer to type <type> taken from the
+ * pool <pool_type> or dynamically allocated. In the
+ * first case, <pool_type> is updated to point to the
+ * next element in the list.
+ */
+#define pool_alloc2(pool) \
+({ \
+ void *__p; \
+ if ((__p = pool.free_list) == NULL) \
+ __p = pool_refill_alloc(&pool); \
+ else { \
+ pool.free_list = *(void **)pool.free_list; \
+ pool.used++; \
+ } \
+ __p; \
+})
+
+/*
+ * Puts a memory area back to the corresponding pool.
+ * Items are chained directly through a pointer that
+ * is written in the beginning of the memory area, so
+ * there's no need for any carrier cell. This implies
+ * that each memory area is at least as big as one
+ * pointer.
+ */
+#define pool_free2(pool, ptr) \
+({ \
+ *(void **)ptr = (void *)pool.free_list; \
+ pool.free_list = (void *)ptr; \
+ pool.used--; \
+})
+
+
#endif /* _COMMON_MEMORY_H */
/*
diff --git a/src/memory.c b/src/memory.c
new file mode 100644
index 0000000..5dbbdd9
--- /dev/null
+++ b/src/memory.c
@@ -0,0 +1,111 @@
+/*
+ * Memory management functions.
+ *
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <common/config.h>
+#include <common/memory.h>
+#include <common/mini-clist.h>
+#include <common/standard.h>
+
+#include <proto/log.h>
+
+static struct list pools = LIST_HEAD_INIT(pools);
+
+/* Try to find an existing shared pool with the same characteristics and
+ * returns it, otherwise creates this one. NULL is returned if no memory
+ * is available for a new creation.
+ */
+struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
+{
+ struct pool_head *pool;
+ unsigned int align;
+
+ /* We need to store at least a (void *) in the chunks. Since we know
+ * that the malloc() function will never return such a small size,
+ * let's round the size up to something slightly bigger, in order to
+ * ease merging of entries. Note that the rounding is a power of two.
+ */
+
+ align = 4 * sizeof(void *);
+ size = (size + align - 1) & -align;
+
+ pool = NULL;
+ if (flags & MEM_F_SHARED) {
+ struct pool_head *entry;
+ list_for_each_entry(entry, &pools, list) {
+ if (!(entry->flags & MEM_F_SHARED))
+ continue;
+ if (entry->size == size) {
+ pool = entry;
+ break;
+ }
+ }
+ }
+
+ if (!pool) {
+ pool = CALLOC(1, sizeof(*pool));
+ if (!pool)
+ return NULL;
+ if (name)
+ strlcpy2(pool->name, name, sizeof(pool->name));
+ pool->size = size;
+ pool->flags = flags;
+ LIST_ADDQ(&pools, &pool->list);
+ }
+ return pool;
+}
+
+/* Allocate a new entry for pool <pool>, and return it for immediate use.
+ * NULL is returned if no memory is available for a new creation.
+ */
+void *refill_pool_alloc(struct pool_head *pool)
+{
+ void *ret;
+
+ if (pool->limit && (pool->allocated >= pool->limit))
+ return NULL;
+ ret = MALLOC(pool->size);
+ if (!ret)
+ return NULL;
+ pool->allocated++;
+ pool->used++;
+ return ret;
+}
+
+/* Dump statistics on pools usage.
+ */
+void dump_pools(void)
+{
+ struct pool_head *entry;
+ unsigned long allocated, used;
+ int nbpools;
+
+ allocated = used = nbpools = 0;
+ qfprintf(stderr, "Dumping pools usage.\n");
+ list_for_each_entry(entry, &pools, list) {
+ qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated, %d used%s\n",
+ entry->name, entry->size, entry->allocated, entry->used,
+ (entry->flags & MEM_F_SHARED) ? " (SHARED)" : "");
+
+ allocated += entry->allocated * entry->size;
+ used += entry->used * entry->size;
+ nbpools++;
+ }
+ qfprintf(stderr, "Total: %d pools, %lu allocated, %lu used.\n",
+ nbpools, allocated, used);
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * End:
+ */