[MEDIUM] enhance behaviour of mempools v2

- keep the number of users of each pool
- call the garbage collector on out of memory conditions
- sort the pools by size for faster creation
- force the alignment size to 16 bytes instead of 4*sizeof(void *)
diff --git a/include/common/memory.h b/include/common/memory.h
index 45ac7f9..66f789e 100644
--- a/include/common/memory.h
+++ b/include/common/memory.h
@@ -125,7 +125,8 @@
 	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 */
+	unsigned int users;	/* number of pools sharing this zone */
+	char name[12];		/* name of the pool */
 };
 
 
diff --git a/src/memory.c b/src/memory.c
index dd54225..589d1d2 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -26,6 +26,8 @@
 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
@@ -34,20 +36,29 @@
 	 * ease merging of entries. Note that the rounding is a power of two.
 	 */
 
-	align = 4 * sizeof(void *);
+	align = 16;
 	size  = (size + align - 1) & -align;
 
+	start = &pools;
 	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) {
+
+	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) {
@@ -58,13 +69,15 @@
 			strlcpy2(pool->name, name, sizeof(pool->name));
 		pool->size = size;
 		pool->flags = flags;
-		LIST_ADDQ(&pools, &pool->list);
+		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.
+ * 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)
 {
@@ -73,8 +86,12 @@
 	if (pool->limit && (pool->allocated >= pool->limit))
 		return NULL;
 	ret = MALLOC(pool->size);
-	if (!ret)
-		return NULL;
+	if (!ret) {
+		pool_gc2();
+		ret = MALLOC(pool->size);
+		if (!ret)
+			return NULL;
+	}
 	pool->allocated++;
 	pool->used++;
 	return ret;
@@ -142,10 +159,10 @@
 	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%s\n",
+		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->flags & MEM_F_SHARED) ? " [SHARED]" : "");
+			 entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
 
 		allocated += entry->allocated * entry->size;
 		used += entry->used * entry->size;