Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
TODO--: the 'type' of each mmalloc block is granted to be uptodate at every point
[simgrid.git] / src / xbt / mmalloc / mmprivate.h
index 5396e55..423c57f 100644 (file)
@@ -16,6 +16,7 @@
 #include "portable.h"
 #include "xbt/xbt_os_thread.h"
 #include "xbt/mmalloc.h"
+#include "xbt/ex.h"
 #include <semaphore.h>
 
 #ifdef HAVE_LIMITS_H
 
 const char *xbt_thread_self_name(void);
 
-/* 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, 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:
+ *  - 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;
+       };
 } malloc_info;
 
 /* Doubly linked lists of free fragments.  */
 struct list {
-  struct list *next;
-  struct list *prev;
+       struct list *next;
+       struct list *prev;
 };
 
 /* Internal structure that defines the format of the malloc-descriptor.
@@ -116,78 +140,71 @@ struct list {
 
 struct mdesc {
 
-  /* Semaphore locking the access to the heap */
-  sem_t sem;
+       /* Semaphore locking the access to the heap */
+       sem_t sem;
 
-  /* Number of processes that attached the heap */
-  unsigned int refcount;
+       /* Number of processes that attached the heap */
+       unsigned int refcount;
 
-  /* Chained lists of mdescs */
-  struct mdesc *next_mdesc;
-  
-  /* The "magic number" for an mmalloc file. */
-  char magic[MMALLOC_MAGIC_SIZE];
+       /* Chained lists of mdescs */
+       struct mdesc *next_mdesc;
 
-  /* The size in bytes of this structure, used as a sanity check when reusing
-     a previously created mapped file. */
-  unsigned int headersize;
-
-  /* The version number of the mmalloc package that created this file. */
-  unsigned char version;
-
-  /* Some flag bits to keep track of various internal things. */
-  unsigned int flags;
-
-  /* Number of info entries.  */
-  size_t heapsize;
+       /* The "magic number" for an mmalloc file. */
+       char magic[MMALLOC_MAGIC_SIZE];
 
-  /* Pointer to first block of the heap (base of the first block).  */
-  void *heapbase;
+       /* The size in bytes of this structure, used as a sanity check when reusing
+     a previously created mapped file. */
+       unsigned int headersize;
 
-  /* Current search index for the heap table.  */
-  /* Search index in the info table.  */
-  size_t heapindex;
+       /* The version number of the mmalloc package that created this file. */
+       unsigned char version;
 
-  /* Limit of valid info table indices.  */
-  size_t heaplimit;
+       /* Some flag bits to keep track of various internal things. */
+       unsigned int flags;
 
-  /* Block information table.
-     Allocated with malign/__mmalloc_free (not mmalloc/mfree).  */
-  /* Table indexed by block number giving per-block information.  */
+       /* Number of info entries.  */
+       size_t heapsize;
 
-  malloc_info *heapinfo;
+       /* Pointer to first block of the heap (base of the first block).  */
+       void *heapbase;
 
-  /* Free list headers for each fragment size.  */
-  /* Free lists for each fragment size.  */
+       /* Current search index for the heap table.  */
+       /* Search index in the info table.  */
+       size_t heapindex;
 
-  struct list fraghead[BLOCKLOG];
+       /* Limit of valid info table indices.  */
+       size_t heaplimit;
 
-  /* List of blocks allocated by memalign.  */
+       /* Block information table.
+     Allocated with malign/mfree (not mmalloc/mfree).  */
+       /* Table indexed by block number giving per-block information.  */
+       malloc_info *heapinfo;
 
-  struct alignlist *aligned_blocks;
+       /* List of all blocks containing free fragments of this size. The array indice is the log2 of requested size */
+       struct list fraghead[BLOCKLOG];
 
-  /* The base address of the memory region for this malloc heap.  This
+       /* The base address of the memory region for this malloc heap.  This
      is the location where the bookkeeping data for mmap and for malloc
      begins. */
 
-  void *base;
+       void *base;
 
-  /* The current location in the memory region for this malloc heap which
+       /* The current location in the memory region for this malloc heap which
      represents the end of memory in use. */
 
-  void *breakval;
+       void *breakval;
 
-  /* The end of the current memory region for this malloc heap.  This is
+       /* The end of the current memory region for this malloc heap.  This is
      the first location past the end of mapped memory. */
 
-  void *top;
+       void *top;
 
-  /* Open file descriptor for the file to which this malloc heap is mapped.
+       /* Open file descriptor for the file to which this malloc heap is mapped.
      This will always be a valid file descriptor, since /dev/zero is used
      by default if no open file is supplied by the client.  Also note that
      it may change each time the region is mapped and unmapped. */
 
-  int fd;
+       int fd;
 
 };
 
@@ -201,10 +218,6 @@ void mmalloc_display_info(void *h);
 #define MMALLOC_ANONYMOUS (1 << 1)      /* Use anonymous mapping */
 #define MMALLOC_INITIALIZED    (1 << 2)        /* Initialized mmalloc */
 
-/* Internal version of `mfree' used in `morecore'. */
-
-extern void __mmalloc_free(struct mdesc *mdp, void *ptr);
-
 /* A default malloc descriptor for the single sbrk() managed region. */
 
 extern struct mdesc *__mmalloc_default_mdp;
@@ -220,9 +233,9 @@ extern void *mmorecore(struct mdesc *mdp, int size);
 
 /* Thread-safety (if the sem is already created) FIXME: KILLIT*/
 #define LOCK(mdp)                                        \
-  sem_wait(&mdp->sem)
+               sem_wait(&mdp->sem)
 
 #define UNLOCK(mdp)                                        \
-    sem_post(&mdp->sem)
+               sem_post(&mdp->sem)
 
 #endif                          /* __MMPRIVATE_H */