heap - 5 - malloc、free函数相关的宏定义

注:宏定义 不建议 单独阅读,应在分析源代码时查阅参考

fastbin相关宏定义

  1. set_max_fast(s)
    • 用处

      • 设置fast chunk大小的最大值为变量s(为0则弃用fast chunk和fastbin)
    • 源代码

      1
      2
      3
      #define set_max_fast(s) \
      global_max_fast = (((s) == 0) \
      ? SMALLBIN_WIDTH : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK))
  1. get_max_fast()

    • 用处

      • 获取fast chunk大小的最大值
    • 源代码

      1
      #define get_max_fast() global_max_fast
  2. fastbin_index(sz)

    • 用处

      • 根据所请求的chunk大小,获取fastbin中对应的索引
    • 源代码

      1
      2
      3
      /* offset 2 to use otherwise unindexable first 2 bins */
      #define fastbin_index(sz) \
      ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
  3. fastbin(ar_ptr, idx)

    • 用处

      • 返回指针ar_ptr指向的arena中,fastbin对应变量idx索引的值
    • 源代码

      1
      #define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
  4. catomic_compare_and_exchange_val_acq(mem, newval, oldval)

    • 用处

      • 线程安全 的交换两个值
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      #  define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
      atomic_compare_and_exchange_val_acq (mem, newval, oldval)

      #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
      ({ __typeof (mem) __gmemp = (mem); \
      __typeof (*mem) __gret = *__gmemp; \
      __typeof (*mem) __gnewval = (newval) \
      \
      if (__gret == (oldval)) \
      *__gmemp = __gnewval; \
      __gret; })
  5. have_fastchunks(M)

    • 用处

      • 判断指针M指向的arena,其fastbin上是否有空闲的fast chunks
    • 源代码

      1
      #define have_fastchunks(M)     (((M)->flags & FASTCHUNKS_BIT) == 0)

smallbin 相关宏定义

  1. in_smallbin_range(sz)

    • 用处

      • 判断变量sz是否处于small chunk的大小范围内
    • 源代码

      1
      2
      #define in_smallbin_range(sz)  \
      ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
  2. smallbin_index(sz)

    • 用处

      • 根据所请求的chunk大小,获取smallbin中对应的索引
    • 源代码

      1
      2
      3
      #define smallbin_index(sz) \
      ((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
      + SMALLBIN_CORRECTION)

unsorted bin 相关宏定义

  1. unsorted_chunks(M)
    • 用处

      • 获取指针M指向arena上的unsorted bin地址
    • 源代码

      1
      2
      /* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
      #define unsorted_chunks(M) (bin_at (M, 1))

largebin 相关宏定义

  1. largebin_index(sz)
    • 用处

      • 根据所请求的chunk大小,获取largebin中对应的索引
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      #define largebin_index(sz) \
      (SIZE_SZ == 8 ? largebin_index_64 (sz) \
      : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
      : largebin_index_32 (sz))

      #define largebin_index_32(sz) \
      (((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
      ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
      ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
      ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
      ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
      126)

      #define largebin_index_32_big(sz) \
      (((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
      ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
      ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
      ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
      ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
      126)

      // XXX It remains to be seen whether it is good to keep the widths of
      // XXX the buckets the same or whether it should be scaled by a factor
      // XXX of two as well.
      #define largebin_index_64(sz) \
      (((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
      ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
      ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
      ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
      ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
      126)

其他通用宏定义

  1. atomic_forced_read(x)

    • 用处

      • 使用内联汇编,在 线程间 安全的读取某个变量
    • 源代码

      1
      2
      # define atomic_forced_read(x) \
      ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; })
  2. __builtin_expect(expr, val)

    • 用处

      • 返回expr的值;val为人工预测expr返回的值。该特殊宏定义可以提高CPU分支预测的准确性,加快CPU的执行速度
      • 注意!这个宏定义只是 预测 该条件的结果,并没有对值进行任何修改
    • 源代码

      1
      # define __builtin_expect(expr, val) (expr)
  3. __glibc_unlikely(cond)

    • 用处

      • 预测表达式cond的结果为假 (不修改返回值)
    • 源代码

      1
      # define __glibc_unlikely(cond) __builtin_expect ((cond), 0)
  4. __glibc_likely(cond)

    • 用处

      • 预测表达式cond的结果为真 (不修改返回值)
    • 源代码

      1
      # define __glibc_likely(cond) __builtin_expect ((cond), 1)
  5. arena_get(ptr, size)

    • 用处

      • 获取当前线程的arena(可能获得main_arena),并将指针ptr设置为获取到的arena地址
      • 之后锁定该arena
    • 源代码

      1
      2
      3
      4
      #define arena_get(ptr, size) do { \
      ptr = thread_arena; \
      arena_lock (ptr, size); \
      } while (0)
  6. arena_lock(ptr, size)

    • 用处

      • 锁定指针ptr指向的arena,以保证对该arena操作时是 线程安全
    • 源代码

      1
      2
      3
      4
      5
      6
      #define arena_lock(ptr, size) do {      \
      if (ptr && !arena_is_corrupt (ptr)) \
      (void) mutex_lock (&ptr->mutex); \
      else \
      ptr = arena_get2 ((size), NULL); \
      } while (0)
  7. mutex_unlock(m)

    • 用处

      • 对指针m指向的单元进行 线程解锁
    • 源代码

      1
      # define mutex_unlock(m)        (*(m) = 0)
  8. assert(expr)

    • 用处

      • 如果表达式expr为假,则输出错误信息并异常退出(抛出SIGABRT信号)
    • 源代码

      1
      2
      3
      4
      # define assert(expr) \
      ((expr) \
      ? ((void) 0) \
      : __malloc_assert (#expr, __FILE__, __LINE__, __func__))
  9. chunk_is_mmapped(p)

    • 用处

      • 判断指针p指向的chunk是否通过mmap函数分配
    • 源代码

      1
      #define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
  10. chunk2mem(p)

    • 用处

      • 将指向chunk header的指针,通过添加偏移,变更为用户使用的指针
    • 源代码

      1
      #define chunk2mem(p)   ((void*)((char*)(p) + 2*SIZE_SZ))
  11. mem2chunk(mem)

    • 用处

      • 将用户使用的指针,通过减小偏移,变更为指向chunk header的指针
    • 源代码

      1
      #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
  12. arena_for_chunk(ptr)

    • 用处

      • 获取指针ptr指向的chunk,其所属的arena地址
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      #define arena_for_chunk(ptr) \
      (chunk_non_main_arena (ptr) ? heap_for_ptr (ptr)->ar_ptr : &main_arena)

      #define chunk_non_main_arena(p) ((p)->size & NON_MAIN_ARENA)

      #define heap_for_ptr(ptr) \
      ((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE - 1)))
  13. request2size(req)

    • 用处

      • 根据用户申请的内存大小req,计算出待申请的chunk的大小
    • 源代码

      1
      2
      3
      4
      #define request2size(req)                                         \
      (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
      MINSIZE : \
      ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
  14. checked_request2size(req, sz)

    • 用处

      • 该宏定义的主要功能在glibc中是这样声明的

        Check if a request is so large that it would wrap around zero when padded and aligned.

      • 判断用户申请的内存大小是否 非常大,大到以至于在添加堆头与内存对齐之后,size_t类型的堆块大小有可能上溢至0
      • 如果用户申请的内存大小req 正常,则由用户所需的内存大小,计算出将要申请的chunk的大小,并将该值赋给变量sz
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #define checked_request2size(req, sz)\
      if (REQUEST_OUT_OF_RANGE (req)) { \
      __set_errno (ENOMEM); \
      return 0; \
      } \
      (sz) = request2size (req);

      #define REQUEST_OUT_OF_RANGE(req) \
      ((unsigned long) (req) >= \
      (unsigned long) (INTERNAL_SIZE_T) (-2 * MINSIZE))
  15. bin_at(m, i)

    • 用处

      • 获取arena上的bins数组中,对应索引的bin地址
      • 指针m指向待使用的arena,变量i为待使用bin的索引
    • 源代码

      1
      2
      3
      4
      /* addressing -- note that bin_at(0) does not exist */
      #define bin_at(m, i) \
      (mbinptr) (((char *) &((m)->bins[((i) - 1) * 2])) \
      - offsetof (struct malloc_chunk, fd))
  16. first(b) / last(b)

    • 用处

      • 获取该bin的第一个chunk的地址 / 最后一个chunk的地址
      • 指针b指向待使用的chunk
    • 源代码

      1
      2
      3
      /* Reminders about list directionality within bins */
      #define first(b) ((b)->fd)
      #define last(b) ((b)->bk)
  17. set_inuse_bit_at_offset(p, s)

    • 用处

      • 为当前chunk的下一个相邻chunk设置PREV_INUSE标志位,以说明被设置PREV_INUSE的chunk的上一个chunk已被分配
    • 源代码

      1
      2
      #define set_inuse_bit_at_offset(p, s)      \
      (((mchunkptr) (((char *) (p)) + (s)))->size |= PREV_INUSE)
  18. check_malloced_chunk(A, P, N)

    • 用处

      • 调用函数来检测指针P指向的chunk是否异常
      • 参数A为arena地址、参数P为chunk地址、参数N为chunk的大小
    • 源代码

      1
      # define check_malloced_chunk(A, P, N)   do_check_malloced_chunk (A, P, N)
  19. chunksize(p)

    • 用处

      • 返回受指针p指向的chunk,其除去各种标志位后的的大小
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      /*
      Bits to mask off when extracting size

      Note: IS_MMAPPED is intentionally not masked off from size field in
      macros for which mmapped chunks should never be seen. This should
      cause helpful core dumps to occur if it is tried by accident by
      people extending or adapting this malloc.
      */
      #define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)

      /* Get size, ignoring use bits */
      #define chunksize(p) ((p)->size & ~(SIZE_BITS))
  20. chunk_at_offset(p, s)

    • 用处

      • 返回chunk p 偏移 s 个单位后的地址
    • 源代码

      1
      2
      /* Treat space at ptr + offset as a chunk */
      #define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
  21. set_head(p, s)

    • 用处

      • 设置chunk p 的 size成员为变量s
    • 源代码

      1
      2
      /* Set size/use field */
      #define set_head(p, s) ((p)->size = (s))
  22. set_foot(p, s)

    • 用处

      • 设置chunk p 下一个chunk 的 prev_size成员为变量s
      • 这个设置当且仅当 被设置prev_size的chunk 的上一个chunk为free chunk时才有效
    • 源代码

      1
      2
      /* Set size at footer (only when chunk is not in use) */
      #define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->prev_size = (s)))
  23. unlink(AV, P, BK, FD)

    • 用处

      • 将该chunk从bin链上断开连接
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      /* Take a chunk off a bin list */
      #define unlink(AV, P, BK, FD) { \
      FD = P->fd; \
      BK = P->bk; \
      if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
      malloc_printerr (check_action, "corrupted double-linked list", P, AV); \
      else { \
      FD->bk = BK; \
      BK->fd = FD; \
      if (!in_smallbin_range (P->size) \
      && __builtin_expect (P->fd_nextsize != NULL, 0)) { \
      if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \
      || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \
      malloc_printerr (check_action, \
      "corrupted double-linked list (not small)", \
      P, AV); \
      if (FD->fd_nextsize == NULL) { \
      if (P->fd_nextsize == P) \
      FD->fd_nextsize = FD->bk_nextsize = FD; \
      else { \
      FD->fd_nextsize = P->fd_nextsize; \
      FD->bk_nextsize = P->bk_nextsize; \
      P->fd_nextsize->bk_nextsize = FD; \
      P->bk_nextsize->fd_nextsize = FD; \
      } \
      } else { \
      P->fd_nextsize->bk_nextsize = P->bk_nextsize; \
      P->bk_nextsize->fd_nextsize = P->fd_nextsize; \
      } \
      } \
      } \
      }
  24. next_bin(b)

    • 用处

      • 返回下一个bin链的地址
    • 源代码

      1
      2
      /* analog of ++bin */
      #define next_bin(b) ((mbinptr) ((char *) (b) + (sizeof (mchunkptr) << 1)))
  25. idx2block(i)

    • 用处

      • 返回传入的索引对应的binmap索引
    • 源代码

      1
      2
      #define BINMAPSHIFT      5
      #define idx2block(i) ((i) >> BINMAPSHIFT)
  26. mark_bin(m, i)

    • 用处

      • 在arena上binmap的对应索引处设置标记,以表示当前索引的large bin非空
    • 源代码

      1
      #define mark_bin(m, i)    ((m)->binmap[idx2block (i)] |= idx2bit (i))
  27. unmark_bin(m, i)

    • 用处

      • 在arena上binmap的对应索引处解除标记,以表示当前索引的large bin为空
    • 源代码

      1
      #define unmark_bin(m, i)  ((m)->binmap[idx2block (i)] &= ~(idx2bit (i)))
  28. get_binmap(m, i)

    • 用处

      • 获取arena上binmap对应索引的值,以获得对应bin的状态
    • 源代码

      1
      #define get_binmap(m, i)  ((m)->binmap[idx2block (i)] & idx2bit (i))
  29. MINSIZE

    • 用处

      • 一个宏常量,表示最小可配分配的chunk大小,通常为 0x10字节(32位) / 0x20字节(64位)
    • 源代码

      1
      2
      3
      4
      5
      6
      7
      /* The smallest possible chunk */
      #define MIN_CHUNK_SIZE (offsetof(struct malloc_chunk, fd_nextsize))

      /* The smallest size we can malloc is an aligned minimal chunk */

      #define MINSIZE \
      (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
  30. misaligned_chunk(p)

    • 用处

      • 用于校验地址是否是按 2SIZE_SZ 对齐
    • 源代码

      1
      2
      3
      #define misaligned_chunk(p) \
      ((uintptr_t)(MALLOC_ALIGNMENT == 2 * SIZE_SZ ? (p) : chunk2mem (p)) \
      & MALLOC_ALIGN_MASK)
  31. aligned_OK(m)

    • 用处

      • 判断当前chunk是否对齐了内存
    • 源代码

      1
      #define aligned_OK(m)  (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
  32. set_fastchunks(M)

    • 用处

      • 设置arena上关于fastbin的标志位
    • 源代码

      1
      #define set_fastchunks(M)      catomic_and (&(M)->flags, ~FASTCHUNKS_BIT)
  33. prev_inuse(p)

    • 用处

      • 判断当前chunk是否设置了prev_inuse(即上一个chunk是否已经被分配了)
    • 源代码

      1
      #define prev_inuse(p)       ((p)->size & PREV_INUSE)
  34. FASTBIN_CONSOLIDATION_THRESHOLD

    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      /*
      FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()
      that triggers automatic consolidation of possibly-surrounding
      fastbin chunks. This is a heuristic, so the exact value should not
      matter too much. It is defined at half the default trim threshold as a
      compromise heuristic to only attempt consolidation if it is likely
      to lead to trimming. However, it is not dynamically tunable, since
      consolidation reduces fragmentation surrounding large chunks even
      if trimming is not used.
      */
      /*
      If freeing a large space, consolidate possibly-surrounding
      chunks. Then, if the total unused topmost memory exceeds trim
      threshold, ask malloc_trim to reduce top.

      Unless max_fast is 0, we don't know if there are fastbins
      bordering top, so we cannot tell for sure whether threshold
      has been reached unless fastbins are consolidated. But we
      don't want to consolidate on each free. As a compromise,
      consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
      is reached.
      */
      #define FASTBIN_CONSOLIDATION_THRESHOLD (65536UL)
  35. contiguous(M)

    • 源代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      /*
      NONCONTIGUOUS_BIT indicates that MORECORE does not return contiguous
      regions. Otherwise, contiguity is exploited in merging together,
      when possible, results from consecutive MORECORE calls.

      The initial value comes from MORECORE_CONTIGUOUS, but is
      changed dynamically if mmap is ever used as an sbrk substitute.
      */

      #define NONCONTIGUOUS_BIT (2U)
      #define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2021 Kiprey
  • 访问人数: | 浏览次数:

请我喝杯奶茶吧~