heap - 11 - malloc_consolidate 源码及其部分分析

fast chunk的内存整合

1. 介绍

  • 看了之前关于malloc和free的相关源码

    1
    2
    if (have_fastchunks (av))
    malloc_consolidate (av);

    就算不看malloc_consolidate的源码,也猜得出来其功能
    该函数是对 fast chunk 进行内存整合

    但为什么该函数取名为malloc_consolidate呢?真误导人呀 :-(

  • 但即便如此,该函数还起到了一个堆的初始化作用

    感到奇怪? 看源码咯~

  • 过程
    • 判断fast chunk的size最大值是否为0
      • 如果是,则表明堆相关尚未初始化(当堆尚未初始化时,此值为0),调用malloc_init_state函数等等
        最后,函数返回
      • 否则
        • 清空arena上关于fastbin的标志位
        • 依次遍历各个index的每一条fast bin
          • 依次遍历当前fast bin链上的各个fast chunk
            • 如果上一个内存相邻的chunk是空闲的,则当前chunk与其合并
            • 判断下一个内存相邻的chunk是否为top chunk
              • 如果是,则当前chunk与其合并
              • 如果不是
                • 如果下一个内存相邻的chunk是空闲的,则当前chunk与其合并
                • 将当前chunk放入unsorted bin中
        • 上述过程全部结束后,函数返回

2. 源码分析

所有的分析都以注释的形式添加进源代码中,方便阅读

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
------------------------- 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.
*/

static void malloc_consolidate(mstate av)
{
mfastbinptr* fb; /* current fastbin being consolidated */
mfastbinptr* maxfb; /* last fastbin (for loop control) */
mchunkptr p; /* current chunk being consolidated */
mchunkptr nextp; /* next chunk to consolidate */
mchunkptr unsorted_bin; /* bin header */
mchunkptr first_unsorted; /* chunk to link to */

/* These have same use as in free() */
mchunkptr nextchunk;
INTERNAL_SIZE_T size;
INTERNAL_SIZE_T nextsize;
INTERNAL_SIZE_T prevsize;
int nextinuse;
mchunkptr bck;
mchunkptr fwd;

/*
If max_fast is 0, we know that av hasn't
yet been initialized, in which case do so below
*/

if (get_max_fast () != 0) {
// 清空arena上关于fastbin的标志位
clear_fastchunks(av);

unsorted_bin = unsorted_chunks(av);

/*
Remove each chunk from fast bin and consolidate it, placing it
then in unsorted bin. Among other reasons for doing this,
placing in unsorted bin avoids needing to calculate actual bins
until malloc is sure that chunks aren't immediately going to be
reused anyway.
*/

maxfb = &fastbin (av, NFASTBINS - 1);
fb = &fastbin (av, 0);
do {
// 依次遍历fastbins的各个index的链头
p = atomic_exchange_acq (fb, 0);
// 如果当前遍历到的index,其链上存在fast chunk
if (p != 0) {
do {
check_inuse_chunk(av, p);
nextp = p->fd;

/* Slightly streamlined version of consolidation code in free() */
size = p->size & ~(PREV_INUSE|NON_MAIN_ARENA);
nextchunk = chunk_at_offset(p, size);
nextsize = chunksize(nextchunk);
// 如果上一个内存相邻chunk为free chunk,则与当前chunk合并
if (!prev_inuse(p)) {
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
unlink(av, p, bck, fwd);
}

// 如果下一个内存相邻chunk不为top chunk
if (nextchunk != av->top) {
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
// 如果下一个内存相邻chunk为free chunk,则与当前chunk合并
if (!nextinuse) {
size += nextsize;
unlink(av, nextchunk, bck, fwd);
} else
clear_inuse_bit_at_offset(nextchunk, 0);

// 将(已经合并了相邻chunk的)当前chunk放入unsorted bin里
first_unsorted = unsorted_bin->fd;
unsorted_bin->fd = p;
first_unsorted->bk = p;

if (!in_smallbin_range (size)) {
p->fd_nextsize = NULL;
p->bk_nextsize = NULL;
}

set_head(p, size | PREV_INUSE);
p->bk = unsorted_bin;
p->fd = first_unsorted;
set_foot(p, size);
}
// 如果下一个内存相邻chunk是top chunk
// 当前fast chunk与top chunk合并
else {
size += nextsize;
set_head(p, size | PREV_INUSE);
av->top = p;
}
// 一直遍历,直到当前fastbin链上的所有chunk全部放入unsorted bin里
} while ( (p = nextp) != 0);

}
// 一直遍历,直到所有fastbin链全部遍历完成
} while (fb++ != maxfb);
}
else {
// 初始时 fastchunk的最大值为0,此时需要对heap进行初始化
malloc_init_state(av);
check_malloc_state(av);
}
}
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2021 Kiprey
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~