IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40117 for trunk


Ignore:
Timestamp:
Aug 11, 2017, 2:18:20 PM (9 years ago)
Author:
eugene
Message:

add code to use mmap instead of malloc; add code to tell malloc to avoid mmap

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/libohana/src/ohana_allocate.c

    r39457 r40117  
    66# include <string.h>
    77# include <errno.h>
     8# include <malloc.h>
     9# include <sys/mman.h>
    810
    911# define TEST_SAVE_FREE_BLOCKS 0
    1012# define TEST_SAVE_DROP_BLOCKS 0
     13# define USE_MMAP_SIZE 0x80000000
     14# define USE_MMAP_LOCAL FALSE
     15/* # define USE_MMAP_SIZE 0x100000 - 1M */
     16/* USE_MMAP_SIZE is used to tell ohana memory functions to switch to raw mmap/munmap call
     17   instead of malloc / realloc / free.  This is in an attempt to avoid a poorly-understood
     18   bug in malloc which I've identfied.  The bug is seen in programs running on linux
     19   kernel 3.7.6 for glibc 2.8.
     20   This did not work as hoped; instead I've had to prevent the use of MMAP all together by
     21   setting M_MMAP_MAX to 0 with mallopt
     22*/
    1123
    1224# undef OHANA_MEMORY
     
    4961void *ohana_malloc (const char *file, int line, const char *func, size_t Nelem, size_t esize) {
    5062
     63  // we want to call mallopt if we have not yet used the memory system
     64  // this disables the use of mmap by malloc and forces it to use on sbrk
     65  pthread_mutex_lock(&memBlockListMutex);
     66  if (!lastBlock) {
     67    mallopt (M_MMAP_MAX, 0);
     68  }
     69  pthread_mutex_unlock(&memBlockListMutex);
     70
    5171  char *ptr;                  // actual user memory allocated
    5272  OhanaMemblock *new;         // new memblock created to track the user memory
    53   size_t size;                // total number of bytes requested (not items)
    54 
    55   Nelem = MAX (1, Nelem);
    56   size = Nelem * esize;
     73
     74  size_t myNelem = MAX (1, Nelem);
     75  size_t size = myNelem * esize; // total number of bytes requested (not items)
     76  size_t fullSize = sizeof(OhanaMemblock) + size + 2*sizeof(void *);   // total size is : memblock + data + endpost
    5777  // if (size % 8) size += (8 - size % 8); // do NOT round to 8-byte boundary (did not fix corruption)
    5878
    59   // total size is : memblock + data + endpost
    60   new = (OhanaMemblock *) malloc (sizeof(OhanaMemblock) + size + 2*sizeof(void *));
    61   if (new == NULL) ohana_memabort ("failed to allocate memory (%s, %d, %s)\n", file, line, func);
     79  if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) {
     80    fprintf (stderr, "** mmap %ld (%s, %d, %s)\n", fullSize, file, line, func);
     81    new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     82    if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func);
     83  } else {
     84    new = (OhanaMemblock *) malloc (fullSize);
     85    if (new == NULL) ohana_memabort ("failed to allocate memory (%s, %d, %s)\n", file, line, func);
     86  }
    6287  // if (errno == ENOMEM) abort(); I should not check the value of errno if new is not NULL
    6388
     
    139164  size_t oldsize = old->size;
    140165
     166  // total size is : memblock + data + endpost
     167  size_t fullSize = sizeof(OhanaMemblock) + size + 2*sizeof(void *);
     168  size_t oldFullSize = sizeof(OhanaMemblock) + oldsize + 2*sizeof(void *);
     169
    141170  pthread_mutex_lock(&memBlockListMutex);
    142171
     
    151180  // XXX for a test, we are going to always alloc a new block, copy the old data to the new block
    152181  // poison the old block, then free it
    153   new = (OhanaMemblock *) malloc (sizeof(OhanaMemblock) + size + 2*sizeof(void *));
    154   if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     182  if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) {
     183    fprintf (stderr, "** mmap %ld (%s, %d, %s)\n", fullSize, file, line, func);
     184    new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     185    if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func);
     186  } else {
     187    new = (OhanaMemblock *) malloc (fullSize);
     188    if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     189  }
    155190  char *ptr_new = (char *) (new + 1);
    156191  char *ptr_old = (char *) (old + 1);
     
    165200# else
    166201  // ask for new memory
    167   // total size is : memblock + data + endpost
    168   new = (OhanaMemblock *) realloc (old, sizeof(OhanaMemblock) + size + 2*sizeof(void *));
    169   if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     202
     203  if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) {
     204    if (oldFullSize > USE_MMAP_SIZE) {
     205      // new = (OhanaMemblock *) mremap (old, oldFullSize, fullSize, 0); NOTE: mremap is a Linux / GNU only feature
     206      // mmap to mmap (allocate new, copy user bytes, free old)
     207      fprintf (stderr, "** mmap 1 %ld to %ld (%s, %d, %s)\n", oldFullSize, fullSize, file, line, func);
     208      new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     209      if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func);
     210      char *ptr_new = (char *) (new + 1);
     211      char *ptr_old = (char *) (old + 1);
     212      size_t copy_bytes = old->size < size ? old->size : size;
     213      memcpy (ptr_new, ptr_old, copy_bytes);
     214      memset (ptr_old, 0x7f, old->size);
     215      new->nextBlock = old->nextBlock;
     216      new->prevBlock = old->prevBlock;
     217      new->startblock = OHANA_MEMMAGIC;
     218      new->endblock = OHANA_MEMMAGIC;
     219      new->freed = FALSE;
     220      fprintf (stderr, "** munmap %ld (%s, %d, %s)\n", oldFullSize, file, line, func);
     221      int mstatus = munmap (old, oldFullSize); // XXX ???
     222      if (mstatus != 0) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     223    } else {
     224      // malloc to mmap (allocate new, copy user bytes, free old)
     225      fprintf (stderr, "** mmap 2 %ld to %ld (%s, %d, %s)\n", oldFullSize, fullSize, file, line, func);
     226      new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     227      if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func);
     228      char *ptr_new = (char *) (new + 1);
     229      char *ptr_old = (char *) (old + 1);
     230      size_t copy_bytes = old->size < size ? old->size : size;
     231      memcpy (ptr_new, ptr_old, copy_bytes);
     232      memset (ptr_old, 0x7f, old->size);
     233      new->nextBlock = old->nextBlock;
     234      new->prevBlock = old->prevBlock;
     235      new->startblock = OHANA_MEMMAGIC;
     236      new->endblock = OHANA_MEMMAGIC;
     237      new->freed = FALSE;
     238      free (old); // XXX ???
     239    }
     240  } else {
     241    if (USE_MMAP_LOCAL && (oldFullSize > USE_MMAP_SIZE)) {
     242      // mmap to malloc (allocate new, copy user bytes, free old)
     243      new = (OhanaMemblock *) malloc (fullSize);
     244      if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     245      char *ptr_new = (char *) (new + 1);
     246      char *ptr_old = (char *) (old + 1);
     247      size_t copy_bytes = old->size < size ? old->size : size;
     248      memcpy (ptr_new, ptr_old, copy_bytes);
     249      memset (ptr_old, 0x7f, old->size);
     250      new->nextBlock = old->nextBlock;
     251      new->prevBlock = old->prevBlock;
     252      new->startblock = OHANA_MEMMAGIC;
     253      new->endblock = OHANA_MEMMAGIC;
     254      new->freed = FALSE;
     255      fprintf (stderr, "** munmap %ld (%s, %d, %s)\n", oldFullSize, file, line, func);
     256      int mstatus = munmap (old, oldFullSize); // XXX ???
     257      if (mstatus != 0) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     258    } else {
     259      // mmap to mmap
     260      new = (OhanaMemblock *) realloc (old, fullSize);
     261      if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
     262    }
     263  }
    170264  char *ptr_new = (char *) (new + 1);
    171265# endif
     
    217311}
    218312
     313// XXX this function is only used for memory allocated outside of the ohana_allocate system
    219314void real_free (void *in) {
    220315
     
    237332  ref = (OhanaMemblock *) in - 1;
    238333  if (!ref->nextBlock && !ref->prevBlock && (Nblock > 1)) ohana_memabort ("orphan block?? (%s@%d : %s)\n", file, line, func);
     334  size_t fullSize = sizeof(OhanaMemblock) + ref->size + 2*sizeof(void *);   // total size is : memblock + data + endpost
    239335
    240336  if (ref->freed) ohana_memabort ("memory already freed (%s, %d, %s [%d bytes])\n", ref->file, ref->line, ref->func, ref->size);
     
    291387# if (!TEST_SAVE_FREE_BLOCKS)
    292388  memset (ref, 0x7f, sizeof(OhanaMemblock));
    293   free (ref);
     389  if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) {
     390    fprintf (stderr, "** munmap %ld (%s, %d, %s)\n", fullSize, file, line, func);
     391    int mstatus = munmap (ref, fullSize);
     392    if (mstatus != 0) ohana_memabort ("failed to free memory (%s, %d, %s)\n", file, line, func);
     393  } else {
     394    free (ref);
     395  }
    294396# endif
    295397
Note: See TracChangeset for help on using the changeset viewer.