madvise

with such flags marks pages as not needed for the application, OS may destroy data from them and unmap physical space;

Ref: link

由於沒有時間細細研究 Understanding glibc malloc

/*
  malloc_trim(size_t pad);
  If possible, gives memory back to the system (via negative
  arguments to sbrk) if there is unused memory at the `high' end of
  the malloc pool. You can call this after freeing large blocks of
  memory to potentially reduce the system-level memory requirements
  of a program. However, it cannot guarantee to reduce memory. Under
  some allocation patterns, some large free blocks of memory will be
  locked between two used chunks, so they cannot be given back to
  the system.
  The `pad' argument to malloc_trim represents the amount of free
  trailing space to leave untrimmed. If this argument is zero,
  only the minimum amount of memory to maintain internal data
  structures will be left (one page or less). Non-zero arguments
  can be supplied to maintain enough trailing space to service
  future expected allocations without having to re-obtain memory
  from the system.
  Malloc_trim returns 1 if it actually released any memory, else 0.
  On systems that do not support "negative sbrks", it will always
  return 0.
*/

int
__malloc_trim(size_t s)
{
  int result = 0;

  if(__malloc_initialized < 0)
    ptmalloc_init ();

  mstate ar_ptr = &main_arena;
  do
    {
      (void) mutex_lock (&ar_ptr->mutex);
      result |= mtrim (ar_ptr, s);
      (void) mutex_unlock (&ar_ptr->mutex);

      ar_ptr = ar_ptr->next;
    }
  while (ar_ptr != &main_arena);

  return result;
}


/*
  ------------------------- malloc_consolidate -------------------------
  malloc_consolidate is a specialized version of free() that tears
  down chunks held in fastbins.  Free itself cannot be used for this
  purpose since, among other things, it might place chunks back onto
  fastbins.  So, instead, we need to use a minor variant of the same
  code.
  Also, because this routine needs to be called the first time through
  malloc anyway, it turns out to be the perfect place to trigger
  initialization code.
*/

/*
  ------------------------------ malloc_trim ------------------------------
*/

static int mtrim(mstate av, size_t pad)
{
  /* Ensure initialization/consolidation */
  malloc_consolidate (av);

  const size_t ps = GLRO(dl_pagesize);
  int psindex = bin_index (ps);
  const size_t psm1 = ps - 1;

  int result = 0;
  for (int i = 1; i < NBINS; ++i)
    if (i == 1 || i >= psindex)
      {
    mbinptr bin = bin_at (av, i);

    for (mchunkptr p = last (bin); p != bin; p = p->bk)
      {
        INTERNAL_SIZE_T size = chunksize (p);

        if (size > psm1 + sizeof (struct malloc_chunk))
          {
        /* See whether the chunk contains at least one unused page.  */
        char *paligned_mem = (char *) (((uintptr_t) p
                        + sizeof (struct malloc_chunk)
                        + psm1) & ~psm1);

        assert ((char *) chunk2mem (p) + 4 * SIZE_SZ <= paligned_mem);
        assert ((char *) p + size > paligned_mem);

        /* This is the size we could potentially free.  */
        size -= paligned_mem - (char *) p;

        if (size > psm1)
          {
#ifdef MALLOC_DEBUG
            /* When debugging we simulate destroying the memory
               content.  */
            memset (paligned_mem, 0x89, size & ~psm1);
#endif
            madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);

            result = 1;
          }
          }
      }
      }

#ifndef MORECORE_CANNOT_TRIM
  return result | (av == &main_arena ? systrim (pad, av) : 0);
#else
  return result;
#endif
}

results matching ""

    No results matching ""