Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fix MC on FreeBSD
[simgrid.git] / src / xbt / mmalloc / mm_module.c
index a2c36cd..9f96095 100644 (file)
@@ -1,6 +1,6 @@
 /* Initialization for acces s to a mmap'd malloc managed region. */
 
-/* Copyright (c) 2012-2014. The SimGrid Team.
+/* Copyright (c) 2012-2019. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
    not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include "src/internal_config.h"
 #include <sys/types.h>
 #include <fcntl.h>              /* After sys/types.h, at least for dpx/2.  */
 #include <sys/stat.h>
 #include <string.h>
-#ifdef HAVE_UNISTD_H
+#if HAVE_UNISTD_H
 #include <unistd.h>             /* Prototypes for lseek */
 #endif
 #include "mmprivate.h"
 #include "xbt/ex.h"
-#include "xbt_modinter.h" /* declarations of mmalloc_preinit and friends that live here */
+#include "src/xbt_modinter.h" /* declarations of mmalloc_preinit and friends that live here */
 
 #ifndef SEEK_SET
 #define SEEK_SET 0
@@ -47,7 +48,7 @@
    If FD is a valid file descriptor for an open file then data for the
    mmalloc managed region is mapped to that file, otherwise an anonymous
    map is used if supported by the underlying OS. In case of running in
-   an OS without support of anonymous mappings then "/dev/zero" is used 
+   an OS without support of anonymous mappings then "/dev/zero" is used
    and in both cases the data will not exist in any filesystem object.
 
    If the open file corresponding to FD is from a previous use of
@@ -57,8 +58,8 @@
    the current process as the process that created the file (ignoring
    the BASEADDR parameter).
 
-   For non valid FDs or empty files ones the mapping is established 
-   starting at the specified address BASEADDR in the process address 
+   For non valid FDs or empty files ones the mapping is established
+   starting at the specified address BASEADDR in the process address
    space.
 
    The provided BASEADDR should be choosed carefully in order to avoid
@@ -119,7 +120,8 @@ xbt_mheap_t xbt_mheap_new_options(int fd, void *baseaddr, int options)
          unsuccessful for some reason. */
 
       struct mdesc newmd;
-      struct mdesc *mdptr = NULL, *mdptemp = NULL;
+      struct mdesc* mdptr   = NULL;
+      struct mdesc* mdptemp = NULL;
 
       if (lseek(fd, 0L, SEEK_SET) != 0)
         return NULL;
@@ -137,7 +139,7 @@ xbt_mheap_t xbt_mheap_new_options(int fd, void *baseaddr, int options)
         mdptr = (struct mdesc *) newmd.base;
         mdptr->fd = fd;
         if(!mdptr->refcount){
-          sem_init(&mdptr->sem, 0, 1);
+          pthread_mutex_init(&mdptr->mutex, NULL);
           mdptr->refcount++;
         }
       }
@@ -155,15 +157,13 @@ xbt_mheap_t xbt_mheap_new_options(int fd, void *baseaddr, int options)
     }
   }
 
-  /* NULL is not a valid baseaddr as we cannot map anything there.
-     C'mon, user. Think! */
+  /* NULL is not a valid baseaddr as we cannot map anything there. C'mon, user. Think! */
   if (baseaddr == NULL)
     return (NULL);
 
-  /* We start off with the malloc descriptor allocated on the stack, until
-     we build it up enough to call _mmalloc_mmap_morecore() to allocate the
-     first page of the region and copy it there.  Ensure that it is zero'd and
-     then initialize the fields that we know values for. */
+  /* We start off with the malloc descriptor allocated on the stack, until we build it up enough to
+   * call _mmalloc_mmap_morecore() to allocate the first page of the region and copy it there.  Ensure that it is
+   * zero'd and then initialize the fields that we know values for. */
 
   mdp = &mtemp;
   memset((char *) mdp, 0, sizeof(mtemp));
@@ -175,22 +175,20 @@ xbt_mheap_t xbt_mheap_new_options(int fd, void *baseaddr, int options)
   mdp->next_mdesc = NULL;
   mdp->refcount = 1;
   mdp->options = options;
-  
+
   /* If we have not been passed a valid open file descriptor for the file
      to map to, then we go for an anonymous map */
 
   if (mdp->fd < 0){
     mdp->flags |= MMALLOC_ANONYMOUS;
   }
-  sem_init(&mdp->sem, 0, 1);
-  
+  pthread_mutex_init(&mdp->mutex, NULL);
   /* If we have not been passed a valid open file descriptor for the file
      to map to, then open /dev/zero and use that to map to. */
 
-  /* Now try to map in the first page, copy the malloc descriptor structure
-     there, and arrange to return a pointer to this new copy.  If the mapping
-     fails, then close the file descriptor if it was opened by us, and arrange
-     to return a NULL. */
+  /* Now try to map in the first page, copy the malloc descriptor structure there, and arrange to return a pointer to
+   * this new copy.  If the mapping fails, then close the file descriptor if it was opened by us, and arrange to return
+   * a NULL. */
 
   if ((mbase = mmorecore(mdp, sizeof(mtemp))) != NULL) {
     memcpy(mbase, mdp, sizeof(mtemp));
@@ -199,7 +197,7 @@ xbt_mheap_t xbt_mheap_new_options(int fd, void *baseaddr, int options)
     abort();
   }
 
-  /* Add the new heap to the linked list of heaps attached by mmalloc */  
+  /* Add the new heap to the linked list of heaps attached by mmalloc */
   if(__mmalloc_default_mdp){
     mdp = __mmalloc_default_mdp;
     while(mdp->next_mdesc)
@@ -225,46 +223,39 @@ void xbt_mheap_destroy_no_free(xbt_mheap_t md)
   struct mdesc *mdp = md;
 
   if(--mdp->refcount == 0){
-    LOCK(mdp) ;
-    sem_destroy(&mdp->sem);
+    pthread_mutex_destroy(&mdp->mutex);
   }
 }
 
-/** Terminate access to a mmalloc managed region by unmapping all memory pages
-    associated with the region, and closing the file descriptor if it is one
-    that we opened.
+/** Terminate access to a mmalloc managed region by unmapping all memory pages associated with the region, and closing
+ *  the file descriptor if it is one that we opened.
 
     Returns NULL on success.
 
-    Returns the malloc descriptor on failure, which can subsequently be used
-    for further action, such as obtaining more information about the nature of
-    the failure.
+    Returns the malloc descriptor on failure, which can subsequently be used for further action, such as obtaining more
+    information about the nature of the failure.
 
-    Note that the malloc descriptor that we are using is currently located in
-    region we are about to unmap, so we first make a local copy of it on the
-    stack and use the copy. */
+    Note that the malloc descriptor that we are using is currently located in region we are about to unmap, so we first
+    make a local copy of it on the stack and use the copy. */
 
 void *xbt_mheap_destroy(xbt_mheap_t mdp)
 {
-  struct mdesc mtemp, *mdptemp;
-
   if (mdp != NULL) {
     /* Remove the heap from the linked list of heaps attached by mmalloc */
-    mdptemp = __mmalloc_default_mdp;
+    struct mdesc* mdptemp = __mmalloc_default_mdp;
     while(mdptemp->next_mdesc != mdp )
       mdptemp = mdptemp->next_mdesc;
 
     mdptemp->next_mdesc = mdp->next_mdesc;
 
     xbt_mheap_destroy_no_free(mdp);
-    mtemp = *mdp;
+    struct mdesc mtemp = *mdp;
 
     /* Now unmap all the pages associated with this region by asking for a
        negative increment equal to the current size of the region. */
 
     if (mmorecore(&mtemp, (char *)mtemp.base - (char *)mtemp.breakval) == NULL) {
-      /* Deallocating failed.  Update the original malloc descriptor
-         with any changes */
+      /* Deallocating failed.  Update the original malloc descriptor with any changes */
       *mdp = mtemp;
     } else {
       if (mtemp.flags & MMALLOC_DEVZERO) {
@@ -278,8 +269,7 @@ void *xbt_mheap_destroy(xbt_mheap_t mdp)
 }
 
 /* Safety gap from the heap's break address.
- * Try to increase this first if you experience strange errors under
- * valgrind. */
+ * Try to increase this first if you experience strange errors under valgrind. */
 #define HEAP_OFFSET   (128UL<<20)
 
 xbt_mheap_t mmalloc_get_default_md(void)
@@ -328,25 +318,19 @@ static void mmalloc_fork_child(void)
 /* Initialize the default malloc descriptor. */
 void *mmalloc_preinit(void)
 {
-  int res;
   if (__mmalloc_default_mdp == NULL) {
+    if(!xbt_pagesize)
+      xbt_pagesize = getpagesize();
     unsigned long mask = ~((unsigned long)xbt_pagesize - 1);
     void *addr = (void*)(((unsigned long)sbrk(0) + HEAP_OFFSET) & mask);
     __mmalloc_default_mdp = xbt_mheap_new_options(-1, addr, XBT_MHEAP_OPTION_MEMSET);
-    /* Fixme? only the default mdp in protected against forks */
-    // This is mandated to protect the mmalloced areas through forks. Think of tesh.
-    // Nah, removing the mutex isn't a good idea either for tesh
-    res = xbt_os_thread_atfork(mmalloc_fork_prepare,  
-                               mmalloc_fork_parent, mmalloc_fork_child);
-    if (res != 0)
-      THROWF(system_error,0,"xbt_os_thread_atfork() failed: return value %d",res);
+
+    // atfork mandated at least on FreeBSD, or simgrid-mc will fail to fork the verified app
+    int res = pthread_atfork(mmalloc_fork_prepare, mmalloc_fork_parent, mmalloc_fork_child);
+    xbt_assert(res == 0, "pthread_atfork() failed: return value %d", res);
   }
   xbt_assert(__mmalloc_default_mdp != NULL);
 
-#if defined(HAVE_GNU_LD) && defined(MMALLOC_WANT_OVERRIDE_LEGACY)
-  mm_gnuld_legacy_init();
-#endif
-
   return __mmalloc_default_mdp;
 }
 
@@ -357,27 +341,31 @@ void mmalloc_postexit(void)
   // xbt_mheap_destroy_no_free(__mmalloc_default_mdp);
 }
 
-size_t mmalloc_get_bytes_used(xbt_mheap_t heap){
-  int i = 0, j = 0;
+// This is the underlying implementation of mmalloc_get_bytes_used_remote.
+// Is it used directly in order to evaluate the bytes used from a different
+// process.
+size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo)
+{
   int bytes = 0;
-  
-  while(i<=((struct mdesc *)heap)->heaplimit){
-    if(((struct mdesc *)heap)->heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
-      if(((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size > 0)
-        bytes += ((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size;
-     
-    } else if(((struct mdesc *)heap)->heapinfo[i].type > 0){
-      for(j=0; j < (size_t) (BLOCKSIZE >> ((struct mdesc *)heap)->heapinfo[i].type); j++){
-        if(((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j] > 0)
-          bytes += ((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j];
+  for (size_t i=0; i < heaplimit; ++i){
+    if (heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
+      if (heapinfo[i].busy_block.busy_size > 0)
+        bytes += heapinfo[i].busy_block.busy_size;
+    } else if (heapinfo[i].type > 0) {
+      for (size_t j=0; j < (size_t) (BLOCKSIZE >> heapinfo[i].type); j++){
+        if(heapinfo[i].busy_frag.frag_size[j] > 0)
+          bytes += heapinfo[i].busy_frag.frag_size[j];
       }
     }
-    i++; 
   }
-
   return bytes;
 }
 
+size_t mmalloc_get_bytes_used(const xbt_mheap_t heap){
+  const struct mdesc* heap_data = (const struct mdesc *) heap;
+  return mmalloc_get_bytes_used_remote(heap_data->heaplimit, heap_data->heapinfo);
+}
+
 ssize_t mmalloc_get_busy_size(xbt_mheap_t heap, void *ptr){
 
   ssize_t block = ((char*)ptr - (char*)(heap->heapbase)) / BLOCKSIZE + 1;
@@ -389,34 +377,5 @@ ssize_t mmalloc_get_busy_size(xbt_mheap_t heap, void *ptr){
     ssize_t frag = ((uintptr_t) (ADDR2UINT (ptr) % (BLOCKSIZE))) >> heap->heapinfo[block].type;
     return heap->heapinfo[block].busy_frag.frag_size[frag];
   }
-    
-}
 
-void mmcheck(xbt_mheap_t heap) {return;
-  if (!heap->heapinfo)
-    return;
-  malloc_info* heapinfo = NULL;
-  for (size_t i=1; i < heap->heaplimit; i += mmalloc_get_increment(heapinfo)) {
-    heapinfo = heap->heapinfo + i;
-    switch (heapinfo->type) {
-    case MMALLOC_TYPE_HEAPINFO:
-    case MMALLOC_TYPE_FREE:
-      if (heapinfo->free_block.size==0) {
-        xbt_die("Block size == 0");
-      }
-      break;
-    case MMALLOC_TYPE_UNFRAGMENTED:
-      if (heapinfo->busy_block.size==0) {
-        xbt_die("Block size == 0");
-      }
-      if (heapinfo->busy_block.busy_size==0 && heapinfo->busy_block.size!=0) {
-        xbt_die("Empty busy block");
-      }
-      break;
-    default:
-      if (heapinfo->type<0) {
-        xbt_die("Unkown mmalloc block type.");
-      }
-    }
-  }
 }