-/* Data structure giving per-block information. */
-typedef union {
- /* Heap information for a busy block. */
- struct {
- /* Zero for a large block, or positive giving the
- logarithm to the base two of the fragment size. */
- int type;
- union {
- struct {
- size_t nfree; /* Free fragments in a fragmented block. */
- size_t first; /* First free fragment of the block. */
- } frag;
- struct {
- size_t size; /* Size (in blocks) of a large cluster. */
- size_t busy_size;
- } block;
- } info;
- } busy;
- /* Heap information for a free block (that may be the first of
- a free cluster). */
- struct {
- size_t size; /* Size (in blocks) of a free cluster. */
- size_t next; /* Index of next free cluster. */
- size_t prev; /* Index of previous free cluster. */
- } free;
+/* Data structure giving per-block information.
+ *
+ * There is one such structure in the mdp->heapinfo array,
+ * that is addressed by block number.
+ *
+ * There is several types of blocks in memory:
+ * - full busy blocks: used when we are asked to malloc a block which size is > BLOCKSIZE/2
+ * In this situation, the full block is given to the malloc.
+ *
+ * - fragmented busy blocks: when asked for smaller amount of memory.
+ * Fragment sizes are only power of 2. When looking for such a free fragment,
+ * we get one from mdp->fraghead (that contains a linked list of blocks fragmented at that
+ * size and containing a free fragment), or we get a fresh block that we fragment.
+ *
+ * - free blocks are grouped by clusters, that are chained together.
+ * When looking for free blocks, we traverse the mdp->heapinfo looking
+ * for a cluster of free blocks that would be large enough.
+ *
+ * The size of the cluster is only to be trusted in the first block of the cluster.
+ * If the cluster results of the fusion of several clusters, the previously first
+ * block of their cluster will have partial data. The only information kept consistent over
+ * all blocks of the clusters is their type (== -1).
+ *
+ * Note that there is no way to determine if the block is free or busy by exploring
+ * this structure only. It wasn't intended to be crawled for comparison and we should fix it (TODO).
+ *
+ * TODO: understand whether the information are written in each blocks of a cluster (be it
+ * free or busy) or only in the first block of the cluster. And in the latter case, how can
+ * I retrieve the first block of my cluster.
+ *
+ * TODO:
+ * - add an indication of the requested size in each fragment, similarly to busy_block.busy_size
+ * - make room to store the backtrace of where the blocks and fragment were malloced, too.
+ */
+typedef struct {
+ int type; /* 0: busy large block
+ >0: busy fragmented (fragments of size 2^type bytes)
+ <0: free block */
+ union {
+ /* Heap information for a busy block. */
+ struct {
+ size_t nfree; /* Free fragments in a fragmented block. */
+ size_t first; /* First free fragment of the block. */
+ } busy_frag;
+ struct {
+ size_t size; /* Size (in blocks) of a large cluster. */
+ size_t busy_size; /* Actually used space, in bytes */
+ } busy_block;
+ /* Heap information for a free block (that may be the first of a free cluster). */
+ struct {
+ size_t size; /* Size (in blocks) of a free cluster. */
+ size_t next; /* Index of next free cluster. */
+ size_t prev; /* Index of previous free cluster. */
+ } free_block;
+ };