⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlmalloc.c

📁 ARMboot is a firmware monitor/bootloader for embedded systems based on ARM or StrongARM CPUs
💻 C
📖 第 1 页 / 共 5 页
字号:
  assert((p->prev_size == offset));  set_head(p, (new_size - offset)|IS_MMAPPED);  mmapped_mem -= size + offset;  mmapped_mem += new_size;  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)    max_mmapped_mem = mmapped_mem;  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)    max_total_mem = mmapped_mem + sbrked_mem;  return p;}#endif /* HAVE_MREMAP */#endif /* HAVE_MMAP *//*  Extend the top-most chunk by obtaining memory from system.  Main interface to sbrk (but see also malloc_trim).*/#if __STD_Cstatic void malloc_extend_top(INTERNAL_SIZE_T nb)#elsestatic void malloc_extend_top(nb) INTERNAL_SIZE_T nb;#endif{  char*     brk;                  /* return value from sbrk */  INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */  INTERNAL_SIZE_T correction;     /* bytes for 2nd sbrk call */  char*     new_brk;              /* return of 2nd sbrk call */  INTERNAL_SIZE_T top_size;       /* new size of top chunk */  mchunkptr old_top     = top;  /* Record state of old top */  INTERNAL_SIZE_T old_top_size = chunksize(old_top);  char*     old_end      = (char*)(chunk_at_offset(old_top, old_top_size));  /* Pad request with top_pad plus minimal overhead */  INTERNAL_SIZE_T    sbrk_size     = nb + top_pad + MINSIZE;  unsigned long pagesz    = malloc_getpagesize;  /* If not the first time through, round to preserve page boundary */  /* Otherwise, we need to correct to a page size below anyway. */  /* (We also correct below if an intervening foreign sbrk call.) */  if (sbrk_base != (char*)(-1))    sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1);  brk = (char*)(MORECORE (sbrk_size));  /* Fail if sbrk failed or if a foreign sbrk call killed our space */  if (brk == (char*)(MORECORE_FAILURE) ||      (brk < old_end && old_top != initial_top))    return;  sbrked_mem += sbrk_size;  if (brk == old_end) /* can just add bytes to current top */  {    top_size = sbrk_size + old_top_size;    set_head(top, top_size | PREV_INUSE);  }  else  {    if (sbrk_base == (char*)(-1))  /* First time through. Record base */      sbrk_base = brk;    else  /* Someone else called sbrk().  Count those bytes as sbrked_mem. */      sbrked_mem += brk - (char*)old_end;    /* Guarantee alignment of first new chunk made from this space */    front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;    if (front_misalign > 0)    {      correction = (MALLOC_ALIGNMENT) - front_misalign;      brk += correction;    }    else      correction = 0;    /* Guarantee the next brk will be at a page boundary */    correction += ((((unsigned long)(brk + sbrk_size))+(pagesz-1)) &                   ~(pagesz - 1)) - ((unsigned long)(brk + sbrk_size));    /* Allocate correction */    new_brk = (char*)(MORECORE (correction));    if (new_brk == (char*)(MORECORE_FAILURE)) return;    sbrked_mem += correction;    top = (mchunkptr)brk;    top_size = new_brk - brk + correction;    set_head(top, top_size | PREV_INUSE);    if (old_top != initial_top)    {      /* There must have been an intervening foreign sbrk call. */      /* A double fencepost is necessary to prevent consolidation */      /* If not enough space to do this, then user did something very wrong */      if (old_top_size < MINSIZE)      {        set_head(top, PREV_INUSE); /* will force null return from malloc */        return;      }      /* Also keep size a multiple of MALLOC_ALIGNMENT */      old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;      set_head_size(old_top, old_top_size);      chunk_at_offset(old_top, old_top_size          )->size =        SIZE_SZ|PREV_INUSE;      chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =        SIZE_SZ|PREV_INUSE;      /* If possible, release the rest. */      if (old_top_size >= MINSIZE)        fREe(chunk2mem(old_top));    }  }  if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem)    max_sbrked_mem = sbrked_mem;  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)    max_total_mem = mmapped_mem + sbrked_mem;  /* We always land on a page boundary */  assert(((unsigned long)((char*)top + top_size) & (pagesz - 1)) == 0);}/* Main public routines *//*  Malloc Algorthim:    The requested size is first converted into a usable form, `nb'.    This currently means to add 4 bytes overhead plus possibly more to    obtain 8-byte alignment and/or to obtain a size of at least    MINSIZE (currently 16 bytes), the smallest allocatable size.    (All fits are considered `exact' if they are within MINSIZE bytes.)    From there, the first successful of the following steps is taken:      1. The bin corresponding to the request size is scanned, and if         a chunk of exactly the right size is found, it is taken.      2. The most recently remaindered chunk is used if it is big         enough.  This is a form of (roving) first fit, used only in         the absence of exact fits. Runs of consecutive requests use         the remainder of the chunk used for the previous such request         whenever possible. This limited use of a first-fit style         allocation strategy tends to give contiguous chunks         coextensive lifetimes, which improves locality and can reduce         fragmentation in the long run.      3. Other bins are scanned in increasing size order, using a         chunk big enough to fulfill the request, and splitting off         any remainder.  This search is strictly by best-fit; i.e.,         the smallest (with ties going to approximately the least         recently used) chunk that fits is selected.      4. If large enough, the chunk bordering the end of memory         (`top') is split off. (This use of `top' is in accord with         the best-fit search rule.  In effect, `top' is treated as         larger (and thus less well fitting) than any other available         chunk since it can be extended to be as large as necessary         (up to system limitations).      5. If the request size meets the mmap threshold and the         system supports mmap, and there are few enough currently         allocated mmapped regions, and a call to mmap succeeds,         the request is allocated via direct memory mapping.      6. Otherwise, the top of memory is extended by         obtaining more space from the system (normally using sbrk,         but definable to anything else via the MORECORE macro).         Memory is gathered from the system (in system page-sized         units) in a way that allows chunks obtained across different         sbrk calls to be consolidated, but does not require         contiguous memory. Thus, it should be safe to intersperse         mallocs with other sbrk calls.      All allocations are made from the the `lowest' part of any found      chunk. (The implementation invariant is that prev_inuse is      always true of any allocated chunk; i.e., that each allocated      chunk borders either a previously allocated and still in-use chunk,      or the base of its memory arena.)*/#if __STD_CVoid_t* mALLOc(size_t bytes)#elseVoid_t* mALLOc(bytes) size_t bytes;#endif{  mchunkptr victim;                  /* inspected/selected chunk */  INTERNAL_SIZE_T victim_size;       /* its size */  int       idx;                     /* index for bin traversal */  mbinptr   bin;                     /* associated bin */  mchunkptr remainder;               /* remainder from a split */  long      remainder_size;          /* its size */  int       remainder_index;         /* its bin index */  unsigned long block;               /* block traverser bit */  int       startidx;                /* first bin of a traversed block */  mchunkptr fwd;                     /* misc temp for linking */  mchunkptr bck;                     /* misc temp for linking */  mbinptr q;                         /* misc temp */  INTERNAL_SIZE_T nb;  if ((long)bytes < 0) return 0;  nb = request2size(bytes);  /* padded request size; */  /* Check for exact match in a bin */  if (is_small_request(nb))  /* Faster version for small requests */  {    idx = smallbin_index(nb);    /* No traversal or size check necessary for small bins.  */    q = bin_at(idx);    victim = last(q);    /* Also scan the next one, since it would have a remainder < MINSIZE */    if (victim == q)    {      q = next_bin(q);      victim = last(q);    }    if (victim != q)    {      victim_size = chunksize(victim);      unlink(victim, bck, fwd);      set_inuse_bit_at_offset(victim, victim_size);      check_malloced_chunk(victim, nb);      return chunk2mem(victim);    }    idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */  }  else  {    idx = bin_index(nb);    bin = bin_at(idx);    for (victim = last(bin); victim != bin; victim = victim->bk)    {      victim_size = chunksize(victim);      remainder_size = victim_size - nb;      if (remainder_size >= (long)MINSIZE) /* too big */      {        --idx; /* adjust to rescan below after checking last remainder */        break;      }      else if (remainder_size >= 0) /* exact fit */      {        unlink(victim, bck, fwd);        set_inuse_bit_at_offset(victim, victim_size);        check_malloced_chunk(victim, nb);        return chunk2mem(victim);      }    }    ++idx;  }  /* Try to use the last split-off remainder */  if ( (victim = last_remainder->fd) != last_remainder)  {    victim_size = chunksize(victim);    remainder_size = victim_size - nb;    if (remainder_size >= (long)MINSIZE) /* re-split */    {      remainder = chunk_at_offset(victim, nb);      set_head(victim, nb | PREV_INUSE);      link_last_remainder(remainder);      set_head(remainder, remainder_size | PREV_INUSE);      set_foot(remainder, remainder_size);      check_malloced_chunk(victim, nb);      return chunk2mem(victim);    }    clear_last_remainder;    if (remainder_size >= 0)  /* exhaust */    {      set_inuse_bit_at_offset(victim, victim_size);      check_malloced_chunk(victim, nb);      return chunk2mem(victim);    }    /* Else place in bin */    frontlink(victim, victim_size, remainder_index, bck, fwd);  }  /*     If there are any possibly nonempty big-enough blocks,     search for best fitting chunk by scanning bins in blockwidth units.  */  if ( (block = idx2binblock(idx)) <= binblocks)  {    /* Get to the first marked block */    if ( (block & binblocks) == 0)    {      /* force to an even block boundary */      idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH;      block <<= 1;      while ((block & binblocks) == 0)      {        idx += BINBLOCKWIDTH;        block <<= 1;      }    }    /* For each possibly nonempty block ... */    for (;;)    {      startidx = idx;          /* (track incomplete blocks) */      q = bin = bin_at(idx);      /* For each bin in this block ... */      do      {        /* Find and use first big enough chunk ... */        for (victim = last(bin); victim != bin; victim = victim->bk)        {          victim_size = chunksize(victim);          remainder_size = victim_size - nb;          if (remainder_size >= (long)MINSIZE) /* split */          {            remainder = chunk_at_offset(victim, nb);            set_head(victim, nb | PREV_INUSE);            unlink(victim, bck, fwd);            link_last_remainder(remainder);            set_head(remainder, remainder_size | PREV_INUSE);            set_foot(remainder, remainder_size);            check_malloced_chunk(victim, nb);            return chunk2mem(victim);          }          else if (remainder_size >= 0)  /* take */          {            set_inuse_bit_at_offset(victim, victim_size);            unlink(victim, bck, fwd);            check_malloced_chunk(victim, nb);            return chunk2mem(victim);          }        }       bin = next_bin(bin);      } while ((++idx & (BINBLOCKWIDTH - 1)) != 0);      /* Clear out the block bit. */      do   /* Possibly backtrack to try to clear a partial block */      {        if ((startidx & (BINBLOCKWIDTH - 1)) == 0)        {          binblocks &= ~block;          break;        }        --startidx;       q = prev_bin(q);      } while (first(q) == q);      /* Get to the next possibly nonempty block */      if ( (block <<= 1) <= binblocks && (block != 0) )      {        while ((block & binblocks) == 0)        {          idx += BINBLOCKWIDTH;          block <<= 1;        }      }      else        break;    }  }  /* Try to use top chunk */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -