Merge branch 'pools' into merge-pools
diff --git a/Makefile b/Makefile
index c7017e5..37439c3 100644
--- a/Makefile
+++ b/Makefile
@@ -215,9 +215,9 @@
 OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
        src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
        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/checks.o src/queue.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..cc80040 100644
--- a/Makefile.bsd
+++ b/Makefile.bsd
@@ -85,10 +85,10 @@
 OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
        src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
        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/checks.o src/queue.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..5cf4f08 100644
--- a/Makefile.osx
+++ b/Makefile.osx
@@ -85,9 +85,10 @@
 OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
        src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
        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/checks.o src/queue.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/appsession.h b/include/common/appsession.h
index 8fa681c..4687298 100644
--- a/include/common/appsession.h
+++ b/include/common/appsession.h
@@ -10,6 +10,7 @@
 #include <common/config.h>
 #include <common/hashpjw.h>
 #include <common/list.h>
+#include <common/memory.h>
 
 #include <types/task.h>
 
@@ -20,14 +21,11 @@
 	unsigned long int request_count;
 } appsess;
 
-#define sizeof_appsess  sizeof(struct appsessions)
-extern void **pool_appsess;
+extern struct pool_head *pool2_appsess;
 
 struct app_pool {
-	void **sessid;
-	void **serverid;
-	int ses_waste, ses_use, ses_msize;
-	int ser_waste, ser_use, ser_msize;
+	struct pool_head *sessid;
+	struct pool_head *serverid;
 };
 
 extern struct app_pool apools;
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..835d79d 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,9 +25,8 @@
 #include <stdlib.h>
 
 #include <common/config.h>
+#include <common/mini-clist.h>
 
-#define sizeof_requri   REQURI_LEN
-#define sizeof_capture  CAPTURE_LEN
 /*
  * Returns a pointer to an area of <__len> bytes taken from the pool <pool> or
  * dynamically allocated. In the first case, <__pool> is updated to point to
@@ -112,6 +111,91 @@
 	}
 }
 
+
+/******* 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_* */
+	unsigned int users;	/* number of pools sharing this zone */
+	char name[12];		/* 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 *pool_refill_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);
+
+/*
+ * This function frees whatever can be freed in pool <pool>.
+ */
+void pool_flush2(struct pool_head *pool);
+
+/*
+ * This function frees whatever can be freed in all pools, but respecting
+ * the minimum thresholds imposed by owners.
+ */
+void pool_gc2();
+
+/*
+ * This function destroys a pull by freeing it completely.
+ * This should be called only under extreme circumstances.
+ */
+void *pool_destroy2(struct pool_head *pool);
+
+/*
+ * 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/include/import/tree.h b/include/import/tree.h
index 7c375e7..11ca6e0 100644
--- a/include/import/tree.h
+++ b/include/import/tree.h
@@ -2,6 +2,8 @@
  * tree.h : tree manipulation macros and structures.
  * (C) 2002 - Willy Tarreau - willy@ant-computing.com
  *
+ * 2007/05/13: adapted to mempools v2.
+ *
  */
 
 #ifndef __TREE_H__
@@ -51,8 +53,7 @@
     struct tree64 *up;			/* parent node. NULL = root */
 };
 
-#define sizeof_tree64 (sizeof (struct tree64))
-extern void **pool_tree64;
+extern struct pool_head *pool2_tree64;
 
 #define ULTREE_HEAD(l)		struct ultree (l) = { .left=NULL, .right=NULL, .up=NULL, .low=0, .level=LONGBITS, .data=NULL }
 #define ULTREE_INIT(l)		{ (l)->data = (l)->left = (l)->right = NULL; }
@@ -96,7 +97,7 @@
 
 	if (next == NULL) {
 	    /* we'll have to insert our node here */
-	    *branch = new = (struct ulltree *)pool_alloc(tree64);
+	    *branch = new = (struct ulltree *)pool_alloc2(pool2_tree64);
 	    ULLTREE_INIT(new);
 	    new->up = root;
 	    new->value = x;
@@ -111,7 +112,7 @@
     /* ok, now we know that we must insert between both. */
 
     /* the new interconnect node */
-    *branch = node = (struct ulltree *)pool_alloc(tree64); /* was <next> */
+    *branch = node = (struct ulltree *)pool_alloc2(pool2_tree64); /* was <next> */
     ULLTREE_INIT(node);
     node->up = root;
     next->up = node;
@@ -139,7 +140,7 @@
 
     /* the new leaf now */
     node->level = m; /* set the level to the lowest common bit */
-    new = (struct ulltree *)pool_alloc(tree64);
+    new = (struct ulltree *)pool_alloc2(pool2_tree64);
     ULLTREE_INIT(new);
     new->value = x;
     new->level = ffs;
@@ -186,7 +187,7 @@
 
 	if (next == NULL) {
 	    /* we'll have to insert our node here */
-	    *branch = new = (struct ultree *)pool_alloc(tree64);
+	    *branch = new = (struct ultree *)pool_alloc2(pool2_tree64);
 	    ULTREE_INIT(new);
 	    new->up = root;
 	    new->low = x;
@@ -200,7 +201,7 @@
     /* ok, now we know that we must insert between both. */
 
     /* the new interconnect node */
-    *branch = node = (struct ultree *)pool_alloc(tree64); /* was <next> */
+    *branch = node = (struct ultree *)pool_alloc2(pool2_tree64); /* was <next> */
     ULTREE_INIT(node);
     node->up = root;
     next->up = node;
@@ -228,7 +229,7 @@
 
     /* the new leaf now */
     node->level = m; /* set the level to the lowest common bit */
-    new = (struct ultree *)pool_alloc(tree64);
+    new = (struct ultree *)pool_alloc2(pool2_tree64);
     ULTREE_INIT(new);
     new->low = x;
     new->level = ffs;
@@ -279,7 +280,7 @@
 
 	if (next == NULL) {
 	    /* we'll have to insert our node here */
-	    *branch = new =(struct ultree *)pool_alloc(tree64);
+	    *branch = new =(struct ultree *)pool_alloc2(pool2_tree64);
 	    UL2TREE_INIT(new);
 	    new->up = root;
 	    new->high = h;
@@ -308,7 +309,7 @@
     /* ok, now we know that we must insert between both. */
 
     /* the new interconnect node */
-    *branch = node = (struct ultree *)pool_alloc(tree64); /* was <next> */
+    *branch = node = (struct ultree *)pool_alloc2(pool2_tree64); /* was <next> */
     UL2TREE_INIT(node);
     node->up = root;
     next->up = node;
@@ -352,7 +353,7 @@
 
     /* the new leaf now */
     node->level = m; /* set the level to the lowest common bit */
-    new = (struct ultree *)pool_alloc(tree64);
+    new = (struct ultree *)pool_alloc2(pool2_tree64);
     UL2TREE_INIT(new);
     new->high = h;
     new->low = l;
@@ -456,7 +457,7 @@
 	    goto __end; /* nothing left, don't delete the root node */	\
 	else {								\
 	    typeof (__root) __old;					\
-	    pool_free(tree64, __ptr);					\
+	    pool_free2(pool2_tree64, __ptr);				\
 	    __old = __ptr;						\
 	    __ptr = __stack[__slen];					\
 	    if (__ptr->left == __old) {					\
@@ -506,7 +507,7 @@
 	    goto __end; /* nothing left, don't delete the root node */	\
 	else {								\
 	    typeof (__root) __old;					\
-	    pool_free(__type, __ptr);					\
+	    pool_free2(pool##__type, __ptr);				\
 	    __old = __ptr;						\
 	    __ptr = __stack[__slen];					\
 	    if (__ptr->left == __old) {					\
@@ -561,7 +562,7 @@
 	    goto __end; /* nothing left, don't delete the root node */	\
 	else {								\
 	    typeof (__root) __old;					\
-	    pool_free(tree64, __ptr);					\
+	    pool_free2(pool2_tree64, __ptr);				\
 	    __old = __ptr;						\
 	    __ptr = __stack[__slen];					\
 	    if (__ptr->left == __old) {					\
@@ -617,7 +618,7 @@
 	    goto __end; /* nothing left, don't delete the root node */	\
 	else {								\
 	    typeof (__root) __old;					\
-	    pool_free(tree64, __ptr);					\
+	    pool_free2(pool2_tree64, __ptr);				\
 	    __old = __ptr;						\
 	    __ptr = __stack[__slen];					\
 	    if (__ptr->left == __old) {					\
@@ -671,7 +672,7 @@
 	 */
 	down = node;
 	node = node->up;
-	pool_free(tree64, down);
+	pool_free2(pool2_tree64, down);
 	if (node->data || node->up == NULL)
 	    return node;
 	/* now we're sure we were sharing this empty node with another branch, let's find it */
@@ -684,7 +685,7 @@
 	down->up = node->up;
     }
     /* free the last node */
-    pool_free(tree64, node);
+    pool_free2(pool2_tree64, node);
     return down->up;
 }
 
@@ -716,7 +717,7 @@
 	    uplink = &up->right;
 
 	*uplink = down; /* we relink the lower branch above us or simply cut it */
-	pool_free(tree64, node);
+	pool_free2(pool2_tree64, node);
 	node = up;
 	if (down)
 	    down->up = node;
diff --git a/include/proto/buffers.h b/include/proto/buffers.h
index 6c39962..74efe8f 100644
--- a/include/proto/buffers.h
+++ b/include/proto/buffers.h
@@ -22,11 +22,19 @@
 #ifndef _PROTO_BUFFERS_H
 #define _PROTO_BUFFERS_H
 
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <common/config.h>
+#include <common/memory.h>
 #include <types/buffers.h>
 
+extern struct pool_head *pool2_buffer;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_buffer();
+
 /* Initializes all fields in the buffer. The ->rlim field is initialized last
  * so that the compiler can optimize it away if changed immediately after the
  * call to this function.
diff --git a/include/proto/log.h b/include/proto/log.h
index 4ed56dd..1a02ec1 100644
--- a/include/proto/log.h
+++ b/include/proto/log.h
@@ -27,10 +27,13 @@
 #include <syslog.h>
 
 #include <common/config.h>
+#include <common/memory.h>
 #include <types/log.h>
 #include <types/proxy.h>
 #include <types/session.h>
 
+extern struct pool_head *pool2_requri;
+
 /*
  * Displays the message on stderr with the date and pid. Overrides the quiet
  * mode during startup.
diff --git a/include/proto/queue.h b/include/proto/queue.h
index 4370cb3..092747a 100644
--- a/include/proto/queue.h
+++ b/include/proto/queue.h
@@ -32,6 +32,9 @@
 #include <types/server.h>
 #include <types/task.h>
 
+extern struct pool_head *pool2_pendconn;
+
+int init_pendconn();
 struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px);
 struct pendconn *pendconn_add(struct session *sess);
 void pendconn_free(struct pendconn *p);
diff --git a/include/proto/session.h b/include/proto/session.h
index e3e5234..a18669e 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -2,7 +2,7 @@
   include/proto/session.h
   This file defines everything related to sessions.
 
-  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
@@ -23,10 +23,15 @@
 #define _PROTO_SESSION_H
 
 #include <common/config.h>
+#include <common/memory.h>
 #include <types/session.h>
 
+extern struct pool_head *pool2_session;
+
 void session_free(struct session *s);
 
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_session();
 
 #endif /* _PROTO_SESSION_H */
 
diff --git a/include/proto/task.h b/include/proto/task.h
index c594d52..6bee1b2 100644
--- a/include/proto/task.h
+++ b/include/proto/task.h
@@ -33,6 +33,10 @@
 #include <types/task.h>
 
 extern void *run_queue;
+extern struct pool_head *pool2_task;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_task();
 
 /* needed later */
 void *tree_delete(void *node);
@@ -97,7 +101,7 @@
  */
 static inline void task_free(struct task *t)
 {
-	pool_free(task, t);
+	pool_free2(pool2_task, t);
 }
 
 /* inserts <task> into its assigned wait queue, where it may already be. In this case, it
diff --git a/include/types/buffers.h b/include/types/buffers.h
index 9b781b8..09d1e34 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -73,9 +73,6 @@
 	char data[BUFSIZE];
 };
 
-#define sizeof_buffer   sizeof(struct buffer)
-extern void **pool_buffer;
-
 
 #endif /* _TYPES_BUFFERS_H */
 
diff --git a/include/types/capture.h b/include/types/capture.h
index d0271a2..e37cc48 100644
--- a/include/types/capture.h
+++ b/include/types/capture.h
@@ -2,7 +2,7 @@
   include/types/capture.h
   This file defines everything related to captures.
 
-  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
@@ -23,6 +23,7 @@
 #define _TYPES_CAPTURE_H
 
 #include <common/config.h>
+#include <common/memory.h>
 
 struct cap_hdr {
     struct cap_hdr *next;
@@ -30,10 +31,10 @@
     int namelen;			/* length of the header name, to speed-up lookups */
     int len;				/* capture length, not including terminal zero */
     int index;				/* index in the output array */
-    void *pool;				/* pool of pre-allocated memory area of (len+1) bytes */
+    struct pool_head *pool;		/* pool of pre-allocated memory area of (len+1) bytes */
 };
 
-extern void **pool_capture;
+extern struct pool_head *pool2_capture;
 
 #endif /* _TYPES_CAPTURE_H */
 
diff --git a/include/types/log.h b/include/types/log.h
index dc04e65..12f8e27 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -44,8 +44,6 @@
 #define LW_REQHDR	1024	/* request header(s) */
 #define LW_RSPHDR	2048	/* response header(s) */
 
-extern void **pool_requri;
-
 
 #endif /* _TYPES_LOG_H */
 
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 532348e..bfbe631 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -140,8 +140,9 @@
 	int nb_req_cap, nb_rsp_cap;		/* # of headers to be captured */
 	struct cap_hdr *req_cap;		/* chained list of request headers to be captured */
 	struct cap_hdr *rsp_cap;		/* chained list of response headers to be captured */
-	void *req_cap_pool, *rsp_cap_pool;	/* pools of pre-allocated char ** used to build the sessions */
-	void *hdr_idx_pool;                     /* pools of pre-allocated int* used for headers indexing */
+	struct pool_head *req_cap_pool,		/* pools of pre-allocated char ** used to build the sessions */
+	                 *rsp_cap_pool;
+	struct pool_head *hdr_idx_pool;         /* pools of pre-allocated int* used for headers indexing */
 	char *req_add[MAX_NEWHDR], *rsp_add[MAX_NEWHDR]; /* headers to be added */
 	int grace;				/* grace time after stop request */
 	char *check_req;			/* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */
diff --git a/include/types/queue.h b/include/types/queue.h
index a8e7d8b..922aa92 100644
--- a/include/types/queue.h
+++ b/include/types/queue.h
@@ -34,10 +34,6 @@
 	struct server *srv;		/* the server we are waiting for */
 };
 
-#define sizeof_pendconn sizeof(struct pendconn)
-extern void **pool_pendconn;
-
-
 #endif /* _TYPES_QUEUE_H */
 
 /*
diff --git a/include/types/session.h b/include/types/session.h
index 7ef138f..819acfd 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -2,7 +2,7 @@
   include/types/session.h
   This file defines everything related to sessions.
 
-  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
@@ -123,10 +123,6 @@
 };
 
 
-#define sizeof_session  sizeof(struct session)
-extern void **pool_session;
-
-
 #endif /* _TYPES_SESSION_H */
 
 /*
diff --git a/include/types/task.h b/include/types/task.h
index 42699db..e0bbd6d 100644
--- a/include/types/task.h
+++ b/include/types/task.h
@@ -42,9 +42,6 @@
 	void *context;			/* the task's context */
 };
 
-#define sizeof_task     sizeof(struct task)
-extern void **pool_task;
-
 #endif /* _TYPES_TASK_H */
 
 /*
diff --git a/src/appsession.c b/src/appsession.c
index 72b7e40..50554a5 100644
--- a/src/appsession.c
+++ b/src/appsession.c
@@ -2,6 +2,7 @@
  * AppSession functions.
  *
  * Copyright 2004-2006 Alexander Lazic, Klaus Wagner
+ * Copyright 2006-2007 Willy Tarreau
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,6 +18,7 @@
 #include <common/chtbl.h>
 #include <common/config.h>
 #include <common/list.h>
+#include <common/memory.h>
 #include <common/time.h>
 
 #include <types/buffers.h>
@@ -27,7 +29,7 @@
 #include <proto/task.h>
 
 
-void **pool_appsess = NULL;
+struct pool_head *pool2_appsess;
 struct app_pool apools;
 int have_appsession;
 
@@ -72,30 +74,40 @@
 	struct proxy        *p = proxy;
     
 	if (!initialized) {
+		pool2_appsess = create_pool("appsess", sizeof(appsess), MEM_F_SHARED);
+		if (pool2_appsess == NULL)
+			return -1;
+
 		if (!appsession_task_init()) {
+			int ser_msize, ses_msize;
+
 			apools.sessid = NULL;
 			apools.serverid = NULL;
-			apools.ser_waste = 0;
-			apools.ser_use = 0;
-			apools.ser_msize = sizeof(void *);
-			apools.ses_waste = 0;
-			apools.ses_use = 0;
-			apools.ses_msize = sizeof(void *);
+
+			ser_msize = sizeof(void *);
+			ses_msize = sizeof(void *);
 			while (p) {
 				s = p->srv;
-				if (apools.ses_msize < p->appsession_len)
-					apools.ses_msize = p->appsession_len;
+				if (ses_msize < p->appsession_len)
+					ses_msize = p->appsession_len;
 				while (s) {
 					idlen = strlen(s->id);
-					if (apools.ser_msize < idlen)
-						apools.ser_msize = idlen;
+					if (ser_msize < idlen)
+						ser_msize = idlen;
 					s = s->next;
 				}
 				p = p->next;
 			}
 			/* we use strings, so reserve space for '\0' */
-			apools.ser_msize ++;
-			apools.ses_msize ++;
+			ser_msize ++;
+			ses_msize ++;
+
+			apools.sessid = create_pool("sessid", ses_msize, MEM_F_SHARED);
+			if (!apools.sessid)
+				return -1;
+			apools.serverid = create_pool("serverid", ser_msize, MEM_F_SHARED);
+			if (!apools.serverid)
+				return -1;
 		}
 		else {
 			fprintf(stderr, "appsession_task_init failed\n");
@@ -111,15 +123,15 @@
 	static int initialized = 0;
 	struct task *t;
 	if (!initialized) {
-		if ((t = pool_alloc(task)) == NULL)
+		if ((t = pool_alloc2(pool2_task)) == NULL)
 			return -1;
 		t->wq = NULL;
 		t->qlist.p = NULL;
 		t->state = TASK_IDLE;
 		t->context = NULL;
 		tv_ms_add(&t->expire, &now, TBLCHKINT);
-		task_queue(t);
 		t->process = appsession_refresh;
+		task_queue(t);
 		initialized ++;
 	}
 	return 0;
@@ -174,6 +186,7 @@
 		p = p->next;
 	}
 	tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
+	task_queue(t);
 	*next = t->expire;
 } /* end appsession_refresh */
 
@@ -196,12 +209,12 @@
     temp1 = (appsess *)data;
 
     if (temp1->sessid)
-	pool_free_to(apools.sessid, temp1->sessid);
+	pool_free2(apools.sessid, temp1->sessid);
 
     if (temp1->serverid)
-	pool_free_to(apools.serverid, temp1->serverid);
+	pool_free2(apools.serverid, temp1->serverid);
 
-    pool_free(appsess, temp1);
+    pool_free2(pool2_appsess, temp1);
 } /* end destroy */
 
 void appsession_cleanup( void )
diff --git a/src/buffers.c b/src/buffers.c
index 5739fcf..658539c 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -15,9 +15,19 @@
 #include <string.h>
 
 #include <common/config.h>
+#include <common/memory.h>
 #include <proto/buffers.h>
 
-void **pool_buffer   = NULL;
+struct pool_head *pool2_buffer;
+
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_buffer()
+{
+	pool2_buffer = create_pool("buffer", sizeof(struct buffer), MEM_F_SHARED);
+	return pool2_buffer != NULL;
+}
+
 
 /* writes <len> bytes from message <msg> to buffer <buf>. Returns 0 in case of
  * success, or the number of bytes available otherwise.
diff --git a/src/capture.c b/src/capture.c
deleted file mode 100644
index c0c4a75..0000000
--- a/src/capture.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Capture variables and functions.
- *
- * Copyright 2000-2006 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 <stdlib.h>
-
-#include <common/config.h>
-#include <types/capture.h>
-
-void **pool_capture  = NULL;
-
-
-/*
- * Local variables:
- *  c-indent-level: 8
- *  c-basic-offset: 8
- * End:
- */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 1edaa8f..5165474 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -824,6 +824,7 @@
 			hdr->name = strdup(args[3]);
 			hdr->namelen = strlen(args[3]);
 			hdr->len = atol(args[5]);
+			hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
 			hdr->index = curproxy->nb_req_cap++;
 			curproxy->req_cap = hdr;
 			curproxy->to_log |= LW_REQHDR;
@@ -846,6 +847,7 @@
 			hdr->name = strdup(args[3]);
 			hdr->namelen = strlen(args[3]);
 			hdr->len = atol(args[5]);
+			hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
 			hdr->index = curproxy->nb_rsp_cap++;
 			curproxy->rsp_cap = hdr;
 			curproxy->to_log |= LW_RSPHDR;
@@ -2401,6 +2403,20 @@
 			memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
 		}
 
+		/* The small pools required for the capture lists */
+		if (curproxy->nb_req_cap)
+			curproxy->req_cap_pool = create_pool("ptrcap",
+							     curproxy->nb_req_cap * sizeof(char *),
+							     MEM_F_SHARED);
+		if (curproxy->nb_rsp_cap)
+			curproxy->rsp_cap_pool = create_pool("ptrcap",
+							     curproxy->nb_rsp_cap * sizeof(char *),
+							     MEM_F_SHARED);
+
+		curproxy->hdr_idx_pool = create_pool("hdr_idx",
+						     MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
+						     MEM_F_SHARED);
+
 		/* for backwards compatibility with "listen" instances, if
 		 * fullconn is not set but maxconn is set, then maxconn
 		 * is used.
@@ -2488,7 +2504,7 @@
 			if (newsrv->maxconn > 0) {
 				struct task *t;
 
-				if ((t = pool_alloc(task)) == NULL) {
+				if ((t = pool_alloc2(pool2_task)) == NULL) {
 					Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
 					return -1;
 				}
@@ -2535,7 +2551,7 @@
 			while (newsrv != NULL) {
 				/* should this server be checked ? */
 				if (newsrv->state & SRV_CHECKED) {
-					if ((t = pool_alloc(task)) == NULL) {
+					if ((t = pool_alloc2(pool2_task)) == NULL) {
 						Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
 						return -1;
 					}
diff --git a/src/client.c b/src/client.c
index 52b281b..50a0f5d 100644
--- a/src/client.c
+++ b/src/client.c
@@ -41,6 +41,7 @@
 #include <proto/log.h>
 #include <proto/hdr_idx.h>
 #include <proto/proto_http.h>
+#include <proto/session.h>
 #include <proto/stream_sock.h>
 #include <proto/task.h>
 
@@ -110,7 +111,7 @@
 			}
 		}
 
-		if ((s = pool_alloc(session)) == NULL) { /* disable this proxy for a while */
+		if ((s = pool_alloc2(pool2_session)) == NULL) { /* disable this proxy for a while */
 			Alert("out of memory in event_accept().\n");
 			EV_FD_CLR(fd, DIR_RD);
 			p->state = PR_STIDLE;
@@ -127,18 +128,18 @@
 		    (((struct sockaddr_in *)&addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr) {
 			if (p->mode == PR_MODE_TCP) {
 				close(cfd);
-				pool_free(session, s);
+				pool_free2(pool2_session, s);
 				continue;
 			}
 			s->flags |= SN_MONITOR;
 		}
 
-		if ((t = pool_alloc(task)) == NULL) { /* disable this proxy for a while */
+		if ((t = pool_alloc2(pool2_task)) == NULL) { /* disable this proxy for a while */
 			Alert("out of memory in event_accept().\n");
 			EV_FD_CLR(fd, DIR_RD);
 			p->state = PR_STIDLE;
 			close(cfd);
-			pool_free(session, s);
+			pool_free2(pool2_session, s);
 			return 0;
 		}
 
@@ -146,8 +147,8 @@
 		if (cfd >= global.maxsock) {
 			Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
 			close(cfd);
-			pool_free(task, t);
-			pool_free(session, s);
+			pool_free2(pool2_task, t);
+			pool_free2(pool2_session, s);
 			return 0;
 		}
 
@@ -156,8 +157,8 @@
 				(char *) &one, sizeof(one)) == -1)) {
 			Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
 			close(cfd);
-			pool_free(task, t);
-			pool_free(session, s);
+			pool_free2(pool2_task, t);
+			pool_free2(pool2_session, s);
 			return 0;
 		}
 
@@ -229,15 +230,12 @@
 			txn->req.som = txn->req.eoh = 0; /* relative to the buffer */
 			txn->auth_hdr.len = -1;
 
-			txn->hdr_idx.size = MAX_HTTP_HDR;
-
 			if (p->nb_req_cap > 0) {
-				if ((txn->req.cap =
-				     pool_alloc_from(p->req_cap_pool, p->nb_req_cap*sizeof(char *)))
-				    == NULL) { /* no memory */
+				if ((txn->req.cap = pool_alloc2(p->req_cap_pool)) == NULL) {
+					/* no memory */
 					close(cfd); /* nothing can be done for this fd without memory */
-					pool_free(task, t);
-					pool_free(session, s);
+					pool_free2(pool2_task, t);
+					pool_free2(pool2_session, s);
 					return 0;
 				}
 				memset(txn->req.cap, 0, p->nb_req_cap*sizeof(char *));
@@ -245,30 +243,30 @@
 
 
 			if (p->nb_rsp_cap > 0) {
-				if ((txn->rsp.cap =
-				     pool_alloc_from(p->rsp_cap_pool, p->nb_rsp_cap*sizeof(char *)))
-				    == NULL) { /* no memory */
+				if ((txn->rsp.cap = pool_alloc2(p->rsp_cap_pool)) == NULL) {
+					/* no memory */
 					if (txn->req.cap != NULL)
-						pool_free_to(p->req_cap_pool, txn->req.cap);
+						pool_free2(p->req_cap_pool, txn->req.cap);
 					close(cfd); /* nothing can be done for this fd without memory */
-					pool_free(task, t);
-					pool_free(session, s);
+					pool_free2(pool2_task, t);
+					pool_free2(pool2_session, s);
 					return 0;
 				}
 				memset(txn->rsp.cap, 0, p->nb_rsp_cap*sizeof(char *));
 			}
 
 
-			if ((txn->hdr_idx.v =
-			     pool_alloc_from(p->hdr_idx_pool, txn->hdr_idx.size*sizeof(*txn->hdr_idx.v)))
-			    == NULL) { /* no memory */
+			txn->hdr_idx.size = MAX_HTTP_HDR;
+
+			if ((txn->hdr_idx.v = pool_alloc2(p->hdr_idx_pool)) == NULL) {
+				/* no memory */
 				if (txn->rsp.cap != NULL)
-					pool_free_to(p->rsp_cap_pool, txn->rsp.cap);
+					pool_free2(p->rsp_cap_pool, txn->rsp.cap);
 				if (txn->req.cap != NULL)
-					pool_free_to(p->req_cap_pool, txn->req.cap);
+					pool_free2(p->req_cap_pool, txn->req.cap);
 				close(cfd); /* nothing can be done for this fd without memory */
-				pool_free(task, t);
-				pool_free(session, s);
+				pool_free2(pool2_task, t);
+				pool_free2(pool2_session, s);
 				return 0;
 			}
 			hdr_idx_init(&txn->hdr_idx);
@@ -346,16 +344,16 @@
 			write(1, trash, len);
 		}
 
-		if ((s->req = pool_alloc(buffer)) == NULL) { /* no memory */
+		if ((s->req = pool_alloc2(pool2_buffer)) == NULL) { /* no memory */
 			if (txn->hdr_idx.v != NULL)
-				pool_free_to(p->hdr_idx_pool, txn->hdr_idx.v);
+				pool_free2(p->hdr_idx_pool, txn->hdr_idx.v);
 			if (txn->rsp.cap != NULL)
-				pool_free_to(p->rsp_cap_pool, txn->rsp.cap);
+				pool_free2(p->rsp_cap_pool, txn->rsp.cap);
 			if (txn->req.cap != NULL)
-				pool_free_to(p->req_cap_pool, txn->req.cap);
+				pool_free2(p->req_cap_pool, txn->req.cap);
 			close(cfd); /* nothing can be done for this fd without memory */
-			pool_free(task, t);
-			pool_free(session, s);
+			pool_free2(pool2_task, t);
+			pool_free2(pool2_session, s);
 			return 0;
 		}
 
@@ -368,17 +366,17 @@
 		s->req->wto = s->be->srvtimeout;
 		s->req->cto = s->be->srvtimeout;
 
-		if ((s->rep = pool_alloc(buffer)) == NULL) { /* no memory */
-			pool_free(buffer, s->req);
+		if ((s->rep = pool_alloc2(pool2_buffer)) == NULL) { /* no memory */
+			pool_free2(pool2_buffer, s->req);
 			if (txn->hdr_idx.v != NULL)
-				pool_free_to(p->hdr_idx_pool, txn->hdr_idx.v);
+				pool_free2(p->hdr_idx_pool, txn->hdr_idx.v);
 			if (txn->rsp.cap != NULL)
-				pool_free_to(p->rsp_cap_pool, txn->rsp.cap);
+				pool_free2(p->rsp_cap_pool, txn->rsp.cap);
 			if (txn->req.cap != NULL)
-				pool_free_to(p->req_cap_pool, txn->req.cap);
+				pool_free2(p->req_cap_pool, txn->req.cap);
 			close(cfd); /* nothing can be done for this fd without memory */
-			pool_free(task, t);
-			pool_free(session, s);
+			pool_free2(pool2_task, t);
+			pool_free2(pool2_session, s);
 			return 0;
 		}
 
diff --git a/src/haproxy.c b/src/haproxy.c
index 0acf75f..a86abeb 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -87,6 +87,7 @@
 #include <proto/proxy.h>
 #include <proto/queue.h>
 #include <proto/server.h>
+#include <proto/session.h>
 #include <proto/stream_sock.h>
 #include <proto/task.h>
 
@@ -202,6 +203,7 @@
 void sig_soft_stop(int sig)
 {
 	soft_stop();
+	pool_gc2();
 	signal(sig, SIG_IGN);
 }
 
@@ -211,6 +213,7 @@
 void sig_pause(int sig)
 {
 	pause_proxies();
+	pool_gc2();
 	signal(sig, sig_pause);
 }
 
@@ -292,6 +295,9 @@
 			 );
 	}
 #endif
+	/* dump memory usage then free everything possible */
+	dump_pools();
+	pool_gc2();
 }
 
 #ifdef DEBUG_MEMORY
@@ -314,6 +320,7 @@
 	   0 GRACE time
 	*/
 	fast_stop();
+	pool_gc2();
 	/* If we are killed twice, we decide to die*/
 	signal(sig, SIG_DFL);
 }
@@ -326,6 +333,7 @@
 	   0 GRACE time
 	*/
 	fast_stop();
+	pool_gc2();
 	/* If we are killed twice, we decide to die*/
 	signal(sig, SIG_DFL);
 }
@@ -370,6 +378,10 @@
 	localtime((time_t *)&now.tv_sec);
 	start_date = now;
 
+	init_task();
+	init_session();
+	init_buffer();
+	init_pendconn();
 	init_proto_http();
 
 	cfg_polling_mechanism = POLL_USE_SELECT;  /* select() is always available */
@@ -572,7 +584,7 @@
 
 void deinit(void)
 {
-	struct proxy *p = proxy;
+	struct proxy *p = proxy, *p0;
 	struct cap_hdr *h,*h_next;
 	struct server *s,*s_next;
 	struct listener *l,*l_next;
@@ -608,7 +620,7 @@
 			h_next = h->next;
 			if (h->name)
 				free(h->name);
-			pool_destroy(h->pool);
+			pool_destroy2(h->pool);
 			free(h);
 			h = h_next;
 		}/* end while(h) */
@@ -619,7 +631,7 @@
 			if (h->name)
 				free(h->name);
 	    
-			pool_destroy(h->pool);
+			pool_destroy2(h->pool);
 			free(h);
 			h = h_next;
 		}/* end while(h) */
@@ -644,9 +656,11 @@
 			l = l_next;
 		}/* end while(l) */
 	
-		pool_destroy((void **) p->req_cap_pool);
-		pool_destroy((void **) p->rsp_cap_pool);
+		pool_destroy2(p->req_cap_pool);
+		pool_destroy2(p->rsp_cap_pool);
+		p0 = p;
 		p = p->next;
+		free(p0);
 	}/* end while(p) */
     
 	if (global.chroot)    free(global.chroot);
@@ -654,16 +668,17 @@
     
 	if (fdtab)            free(fdtab);
     
-	pool_destroy(pool_session);
-	pool_destroy(pool_buffer);
-	pool_destroy(pool_requri);
-	pool_destroy(pool_task);
-	pool_destroy(pool_capture);
-	pool_destroy(pool_appsess);
+	pool_destroy2(pool2_session);
+	pool_destroy2(pool2_buffer);
+	pool_destroy2(pool2_requri);
+	pool_destroy2(pool2_task);
+	pool_destroy2(pool2_capture);
+	pool_destroy2(pool2_appsess);
+	pool_destroy2(pool2_pendconn);
     
 	if (have_appsession) {
-		pool_destroy(apools.serverid);
-		pool_destroy(apools.sessid);
+		pool_destroy2(apools.serverid);
+		pool_destroy2(apools.sessid);
 	}
 } /* end deinit() */
 
diff --git a/src/memory.c b/src/memory.c
new file mode 100644
index 0000000..8009227
--- /dev/null
+++ b/src/memory.c
@@ -0,0 +1,187 @@
+/*
+ * 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;
+	struct pool_head *entry;
+	struct list *start;
+	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 = 16;
+	size  = (size + align - 1) & -align;
+
+	start = &pools;
+	pool = NULL;
+
+	list_for_each_entry(entry, &pools, list) {
+		if (entry->size == size) {
+			/* either we can share this place and we take it, or
+			 * we look for a sharable one or for the next position
+			 * before which we will insert a new one.
+			 */
+			if (flags & entry->flags & MEM_F_SHARED) {
+				/* we can share this one */
+				pool = entry;
+				break;
+			}
+		}
+		else if (entry->size > size) {
+			/* insert before this one */
+			start = &entry->list;
+			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(start, &pool->list);
+	}
+	pool->users++;
+	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. A call
+ * to the garbage collector is performed before returning NULL.
+ */
+void *pool_refill_alloc(struct pool_head *pool)
+{
+	void *ret;
+
+	if (pool->limit && (pool->allocated >= pool->limit))
+		return NULL;
+	ret = MALLOC(pool->size);
+	if (!ret) {
+		pool_gc2();
+		ret = MALLOC(pool->size);
+		if (!ret)
+			return NULL;
+	}
+	pool->allocated++;
+	pool->used++;
+	return ret;
+}
+
+/*
+ * This function frees whatever can be freed in pool <pool>.
+ */
+void pool_flush2(struct pool_head *pool)
+{
+	void *temp, *next;
+	if (!pool)
+		return;
+
+	next = pool->free_list;
+	while (next) {
+		temp = next;
+		next = *(void **)temp;
+		pool->allocated--;
+		FREE(temp);
+	}
+	pool->free_list = next;
+
+	/* here, we should have pool->allocate == pool->used */
+}
+
+/*
+ * This function frees whatever can be freed in all pools, but respecting
+ * the minimum thresholds imposed by owners.
+ */
+void pool_gc2()
+{
+	struct pool_head *entry;
+	list_for_each_entry(entry, &pools, list) {
+		void *temp, *next;
+		//qfprintf(stderr, "Flushing pool %s\n", entry->name);
+		next = entry->free_list;
+		while (next &&
+		       entry->allocated > entry->minavail &&
+		       entry->allocated > entry->used) {
+			temp = next;
+			next = *(void **)temp;
+			entry->allocated--;
+			FREE(temp);
+		}
+		entry->free_list = next;
+	}
+}
+
+/*
+ * This function destroys a pull by freeing it completely.
+ * This should be called only under extreme circumstances.
+ * It always returns NULL, easing the clearing of the old pointer.
+ */
+void *pool_destroy2(struct pool_head *pool)
+{
+	if (pool) {
+		pool_flush2(pool);
+		FREE(pool);
+	}
+	return NULL;
+}
+
+/* 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 (%lu bytes), %d used, %d users%s\n",
+			 entry->name, entry->size, entry->allocated,
+			 entry->size * entry->allocated, entry->used,
+			 entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
+
+		allocated += entry->allocated * entry->size;
+		used += entry->used * entry->size;
+		nbpools++;
+	}
+	qfprintf(stderr, "Total: %d pools, %lu bytes allocated, %lu used.\n",
+		 nbpools, allocated, used);
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/src/proto_http.c b/src/proto_http.c
index d1bfdcf..4e9e683 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -243,6 +243,10 @@
 		FD_SET(*tmp, url_encode_map);
 		tmp++;
 	}
+
+	/* memory allocations */
+	pool2_requri = create_pool("requri", REQURI_LEN, MEM_F_SHARED);
+	pool2_capture = create_pool("capture", CAPTURE_LEN, MEM_F_SHARED);
 }
 
 /*
@@ -624,7 +628,8 @@
 const char sess_set_cookie[8] = "N1I3PD5R";	/* No set-cookie, unknown, Set-Cookie Inserted, unknown,
 					    	   Set-cookie seen and left unchanged (passive), Set-cookie Deleted,
 						   unknown, Set-cookie Rewritten */
-void **pool_requri = NULL;
+struct pool_head *pool2_requri;
+struct pool_head *pool2_capture;
 
 /*
  * send a log for the session when we have enough info about it.
@@ -770,7 +775,7 @@
 			    (strncasecmp(sol, h->name, h->namelen) == 0)) {
 				if (cap[h->index] == NULL)
 					cap[h->index] =
-						pool_alloc_from(h->pool, h->len + 1);
+						pool_alloc2(h->pool);
 
 				if (cap[h->index] == NULL) {
 					Alert("HTTP capture : out of memory.\n");
@@ -1592,7 +1597,7 @@
 		 */
 		if (unlikely(t->logs.logwait & LW_REQ)) {
 			/* we have a complete HTTP request that we must log */
-			if ((txn->uri = pool_alloc(requri)) != NULL) {
+			if ((txn->uri = pool_alloc2(pool2_requri)) != NULL) {
 				int urilen = msg->sl.rq.l;
 
 				if (urilen >= REQURI_LEN)
@@ -4169,7 +4174,7 @@
 				    memcmp(p1, t->fe->capture_name, t->fe->capture_namelen) == 0) {
 					int log_len = p4 - p1;
 
-					if ((txn->cli_cookie = pool_alloc(capture)) == NULL) {
+					if ((txn->cli_cookie = pool_alloc2(pool2_capture)) == NULL) {
 						Alert("HTTP logging : out of memory.\n");
 					} else {
 						if (log_len > t->fe->capture_len)
@@ -4298,7 +4303,7 @@
 
 					asession_temp = &local_asession;
 			  
-					if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
+					if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) {
 						Alert("Not enough memory process_cli():asession->sessid:malloc().\n");
 						send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n");
 						return;
@@ -4310,9 +4315,9 @@
 			    
 					/* only do insert, if lookup fails */
 					if (chtbl_lookup(&(t->be->htbl_proxy), (void *) &asession_temp) != 0) {
-						if ((asession_temp = pool_alloc(appsess)) == NULL) {
+						if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
 							/* free previously allocated memory */
-							pool_free_to(apools.sessid, local_asession.sessid);
+							pool_free2(apools.sessid, local_asession.sessid);
 							Alert("Not enough memory process_cli():asession:calloc().\n");
 							send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
 							return;
@@ -4323,7 +4328,7 @@
 						chtbl_insert(&(t->be->htbl_proxy), (void *) asession_temp);
 					} else {
 						/* free previously allocated memory */
-						pool_free_to(apools.sessid, local_asession.sessid);
+						pool_free2(apools.sessid, local_asession.sessid);
 					}
 			    
 					if (asession_temp->serverid == NULL) {
@@ -4704,7 +4709,7 @@
 			    memcmp(p1, t->be->capture_name, t->be->capture_namelen) == 0) {
 				int log_len = p4 - p1;
 
-				if ((txn->srv_cookie = pool_alloc(capture)) == NULL) {
+				if ((txn->srv_cookie = pool_alloc2(pool2_capture)) == NULL) {
 					Alert("HTTP logging : out of memory.\n");
 				}
 
@@ -4771,7 +4776,7 @@
 				size_t server_id_len = strlen(t->srv->id) + 1;
 				asession_temp = &local_asession;
 		      
-				if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
+				if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) {
 					Alert("Not enough Memory process_srv():asession->sessid:malloc().\n");
 					send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n");
 					return;
@@ -4782,7 +4787,7 @@
 
 				/* only do insert, if lookup fails */
 				if (chtbl_lookup(&(t->be->htbl_proxy), (void *) &asession_temp) != 0) {
-					if ((asession_temp = pool_alloc(appsess)) == NULL) {
+					if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
 						Alert("Not enough Memory process_srv():asession:calloc().\n");
 						send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n");
 						return;
@@ -4793,11 +4798,11 @@
 				}/* end if (chtbl_lookup()) */
 				else {
 					/* free wasted memory */
-					pool_free_to(apools.sessid, local_asession.sessid);
+					pool_free2(apools.sessid, local_asession.sessid);
 				} /* end else from if (chtbl_lookup()) */
 		      
 				if (asession_temp->serverid == NULL) {
-					if ((asession_temp->serverid = pool_alloc_from(apools.serverid, apools.ser_msize)) == NULL) {
+					if ((asession_temp->serverid = pool_alloc2(apools.serverid)) == NULL) {
 						Alert("Not enough Memory process_srv():asession->sessid:malloc().\n");
 						send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n");
 						return;
@@ -4941,7 +4946,7 @@
 	/* First try if we already have an appsession */
 	asession_temp = &local_asession;
 	
-	if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
+	if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) {
 		Alert("Not enough memory process_cli():asession_temp->sessid:calloc().\n");
 		send_log(t->be, LOG_ALERT, "Not enough Memory process_cli():asession_temp->sessid:calloc().\n");
 		return;
@@ -4954,9 +4959,9 @@
 	
 	/* only do insert, if lookup fails */
 	if (chtbl_lookup(&(t->be->htbl_proxy), (void *)&asession_temp)) {
-		if ((asession_temp = pool_alloc(appsess)) == NULL) {
+		if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
 			/* free previously allocated memory */
-			pool_free_to(apools.sessid, local_asession.sessid);
+			pool_free2(apools.sessid, local_asession.sessid);
 			Alert("Not enough memory process_cli():asession:calloc().\n");
 			send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
 			return;
@@ -4967,7 +4972,7 @@
 	}
 	else {
 		/* free previously allocated memory */
-		pool_free_to(apools.sessid, local_asession.sessid);
+		pool_free2(apools.sessid, local_asession.sessid);
 	}
 	
 	tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
diff --git a/src/proxy.c b/src/proxy.c
index dd7f993..7d4b2ec 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -19,6 +19,7 @@
 #include <common/defaults.h>
 #include <common/compat.h>
 #include <common/config.h>
+#include <common/memory.h>
 #include <common/time.h>
 
 #include <types/global.h>
@@ -230,6 +231,8 @@
 						listeners--;
 					}
 					p->state = PR_STSTOPPED;
+					/* try to free more memory */
+					pool_gc2();
 				}
 				else {
 					tv_bound(next, &p->stop_time);
diff --git a/src/queue.c b/src/queue.c
index 37d3ed8..a4670a8 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -11,6 +11,7 @@
  */
 
 #include <common/config.h>
+#include <common/memory.h>
 #include <common/time.h>
 
 #include <types/proxy.h>
@@ -21,7 +22,14 @@
 #include <proto/task.h>
 
 
-void **pool_pendconn = NULL;
+struct pool_head *pool2_pendconn;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_pendconn()
+{
+	pool2_pendconn = create_pool("pendconn", sizeof(struct pendconn), MEM_F_SHARED);
+	return pool2_pendconn != NULL;
+}
 
 /* returns the effective dynamic maxconn for a server, considering the minconn
  * and the proxy's usage relative to its dynamic connections limit. It is
@@ -98,7 +106,7 @@
 {
 	struct pendconn *p;
 
-	p = pool_alloc(pendconn);
+	p = pool_alloc2(pool2_pendconn);
 	if (!p)
 		return NULL;
 
@@ -136,7 +144,7 @@
 	else
 		p->sess->be->nbpend--;
 	p->sess->be->totpend--;
-	pool_free(pendconn, p);
+	pool_free2(pool2_pendconn, p);
 }
 
 
diff --git a/src/session.c b/src/session.c
index 21d3480..d13f995 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1,7 +1,7 @@
 /*
  * Server management functions.
  *
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * 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
@@ -21,12 +21,14 @@
 #include <types/proxy.h>
 #include <types/server.h>
 
+#include <proto/buffers.h>
 #include <proto/hdr_idx.h>
+#include <proto/log.h>
 #include <proto/session.h>
 #include <proto/queue.h>
 
 
-void **pool_session = NULL;
+struct pool_head *pool2_session;
 
 /*
  * frees  the context associated to a session. It must have been removed first.
@@ -38,38 +40,46 @@
 	if (s->pend_pos)
 		pendconn_free(s->pend_pos);
 	if (s->req)
-		pool_free(buffer, s->req);
+		pool_free2(pool2_buffer, s->req);
 	if (s->rep)
-		pool_free(buffer, s->rep);
+		pool_free2(pool2_buffer, s->rep);
 
 	if (txn->hdr_idx.v != NULL)
-		pool_free_to(s->fe->hdr_idx_pool, txn->hdr_idx.v);
+		pool_free2(s->fe->hdr_idx_pool, txn->hdr_idx.v);
 
 	if (txn->rsp.cap != NULL) {
 		struct cap_hdr *h;
 		for (h = s->fe->rsp_cap; h; h = h->next) {
 			if (txn->rsp.cap[h->index] != NULL)
-				pool_free_to(h->pool, txn->rsp.cap[h->index]);
+				pool_free2(h->pool, txn->rsp.cap[h->index]);
 		}
-		pool_free_to(s->fe->rsp_cap_pool, txn->rsp.cap);
+		pool_free2(s->fe->rsp_cap_pool, txn->rsp.cap);
 	}
 	if (txn->req.cap != NULL) {
 		struct cap_hdr *h;
 		for (h = s->fe->req_cap; h; h = h->next) {
 			if (txn->req.cap[h->index] != NULL)
-				pool_free_to(h->pool, txn->req.cap[h->index]);
+				pool_free2(h->pool, txn->req.cap[h->index]);
 		}
-		pool_free_to(s->fe->req_cap_pool, txn->req.cap);
+		pool_free2(s->fe->req_cap_pool, txn->req.cap);
 	}
 
 	if (txn->uri)
-		pool_free(requri, txn->uri);
+		pool_free2(pool2_requri, txn->uri);
 	if (txn->cli_cookie)
-		pool_free(capture, txn->cli_cookie);
+		pool_free2(pool2_capture, txn->cli_cookie);
 	if (txn->srv_cookie)
-		pool_free(capture, txn->srv_cookie);
+		pool_free2(pool2_capture, txn->srv_cookie);
 
-	pool_free(session, s);
+	pool_free2(pool2_session, s);
+}
+
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_session()
+{
+	pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
+	return pool2_session != NULL;
 }
 
 
diff --git a/src/task.c b/src/task.c
index 6190670..7f6e0e7 100644
--- a/src/task.c
+++ b/src/task.c
@@ -11,6 +11,7 @@
  */
 
 #include <common/config.h>
+#include <common/memory.h>
 #include <common/mini-clist.h>
 #include <common/standard.h>
 #include <common/time.h>
@@ -23,15 +24,22 @@
 #include <import/bitops.h>
 #include <import/tree.h>
 
-
-void **pool_task= NULL;
-void **pool_tree64 = NULL;
 static struct ultree *stack[LLONGBITS];
 
+struct pool_head *pool2_task, *pool2_tree64;
+
 UL2TREE_HEAD(timer_wq);
 void *eternity_queue = NULL;
 void *run_queue = NULL;
 
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_task()
+{
+	pool2_task = create_pool("task", sizeof(struct task), MEM_F_SHARED);
+	pool2_tree64 = create_pool("tree64", sizeof(struct tree64), MEM_F_SHARED);
+	return pool2_task && pool2_tree64;
+}
+
 struct ultree *ul2tree_insert(struct ultree *root, unsigned long h, unsigned long l)
 {
 	return __ul2tree_insert(root, h, l);