-/* Statistics available to the user.
- FIXME: By design, the internals of the malloc package are no longer
- exported to the user via an include file, so access to this data needs
- to be via some other mechanism, such as mmstat_<something> where the
- return value is the <something> the user is interested in. */
-
-struct mstats {
- size_t bytes_total; /* Total size of the heap. */
- size_t chunks_used; /* Chunks allocated by the user. */
- size_t bytes_used; /* Byte total of user-allocated chunks. */
- size_t chunks_free; /* Chunks in the free list. */
- size_t bytes_free; /* Byte total of chunks in the free list. */
-};
+/* Data structure giving per-block information.
+ *
+ * There is one such structure in the mdp->heapinfo array per block used in that heap,
+ * the array index is the 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, not in the middle blocks.
+ *
+ * The type field is consistently updated for every blocks, even within clusters of blocks.
+ * You can crawl the array and rely on that value.
+ *
+ * TODO:
+ * - 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. */
+ unsigned short frag_size[MAX_FRAGMENT_PER_BLOCK];
+ void *bt[MAX_FRAGMENT_PER_BLOCK][XBT_BACKTRACE_SIZE]; /* Where it was malloced (or realloced lastly) */
+ } busy_frag;
+ struct {
+ size_t size; /* Size (in blocks) of a large cluster. */
+ size_t busy_size; /* Actually used space, in bytes */
+ void *bt[XBT_BACKTRACE_SIZE]; /* Where it was malloced (or realloced lastly) */
+ int bt_size;
+ } 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;
+ };
+} malloc_info;