#include "mempool.h"
#include "llist.h"
+/*
+ * As the name implies, allocfree pools support both allocating and freeing
+ * memory.
+ *
+ * Implementation
+ * ==============
+ *
+ * Each allocfree pool contains a pool structure (struct allocfree_pool) to
+ * keep track of allocfree-specific pool information and zero or more blocks
+ * (struct pool_block) that keep track of ranges of memory used to back the
+ * allocations. The blocks are kept in a doubly-linked list used to keep
+ * track of all allocations that belong to the pool.
+ *
+ * +-----------+
+ * | allocfree |
+ * | pool |
+ * +-----+-----+
+ * |
+ * | blocks +------------+ next +------------+ next
+ * \------->| pool block |<=====>| pool block |<=====>...<====> NULL
+ * +------------+ prev +------------+ prev
+ * | <data> | | <data> |
+ * . .
+ * . .
+ * . | <data> |
+ * . +------------+
+ * | <data> |
+ * +------------+
+ *
+ * Creation
+ * --------
+ *
+ * When an allocfree pool is created the linked list of allocated blocks is
+ * initialized to be empty.
+ *
+ * Allocation & Freeing
+ * --------------------
+ *
+ * Since each allocation (via p_malloc()) corresponds to one block,
+ * allocations are simply a matter of:
+ *
+ * - allocating enough memory from the system heap (via calloc()) to hold
+ * the block header and the requested number of bytes,
+ * - making a note of the user-requested size in the block header,
+ * - adding the new block to the pool's linked list of blocks, and
+ * - returning a pointer to the payload area of the block to the caller.
+ *
+ * Freeing memory is simpler. The passed in pointer is converted to a
+ * struct pool_block pointer. Then the block is removed from the pool's
+ * linked list and free()d.
+ *
+ * If the pool was created via pool_allocfree_create_clean(), all blocks are
+ * safe_memset() to zero just before being free()d.
+ *
+ * Reallocation
+ * ------------
+ *
+ * Reallocation is done by calling realloc() with a new size that is large
+ * enough to cover the requested number of bytes plus the block header
+ * overhead.
+ *
+ * Clearing
+ * --------
+ *
+ * Clearing the pool is supposed to return the pool to the same state it was
+ * in when it was first created. To that end, the allocfree pool frees all
+ * the blocks allocated since the pool's creation. In other words, clearing
+ * is equivalent to (but faster than) calling p_free() for each allocation
+ * in the pool.
+ *
+ * Finally, if the pool was created via pool_allocfree_create_clean(), all
+ * blocks are safe_memset() to zero before being free()d.
+ *
+ * Destruction
+ * -----------
+ *
+ * Destroying a pool first clears it (see above) and then the pool structure
+ * itself is safe_memset() to zero (if pool_allocfree_create_clean() was
+ * used) and free()d. (The clearing leaves the pool in a minimal state
+ * with no blocks allocated.)
+ */
+
#define MAX_ALLOC_SIZE SSIZE_T_MAX
struct allocfree_pool {