title: malloc_consolidate() 函数作用
date: 2018-04-15 08:33:05
categories:
进入 malloc_consolidate()
,首先通过 get_max_fast()
判断当前堆是否已经初始化。当进程第一次调用 malloc()
申请分配的时候,get_max_fast()
返回值等于 0,此时会进行堆的初始化工作:
if (get_max_fast () != 0) {
...
}
else {
malloc_init_state(av);
check_malloc_state(av);
}
在 malloc_init_state()
里会进行堆的初始化工作,并且会调用 set_max_fast()
设置 global_max_fast
为 DEFAULT_MXFAST
,DEFAULT_MXFAST
在 32 位系统上为 64,在 64 位系统上为 128。因而在以后进入 malloc_consolidate()
的时候 get_max_fast()
返回值都不会等于 0,保证不会重复进行堆的初始化工作。
如果 get_max_fast()
返回值不等于 0,说明堆已经初始化,接下来就将 fastbin 中的每一个 chunk 合并整理到 unsorted_bin 或 top_chunk。
因为 malloc_consolidate()
会清空 fastbin,因此首先调用 clear_fastchunks()
清除 fastbin 标志位:
if (get_max_fast () != 0) {
clear_fastchunks(av);
...
}
接下来是一个二层循环,第一层遍历 fastbinY 数组,得到每一个固定尺寸的 fastbin 单链表。二层则遍历 fastbin 单链表得到每一个相同尺寸的空闲 chunk。
/*
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 {
p = atomic_exchange_acq (fb, NULL);
if (p != 0) {
do {
check_inuse_chunk(av, p);
nextp = p->fd;
...
} while ( (p = nextp) != 0);
}
} while (fb++ != maxfb);
对每一个 chunk,首先尝试向后合并。合并操作即更新 p 的 size 以及指向,然后调用 unlink()
宏将后方 chunk 从其链接的 bin 中脱链:
if (!prev_inuse(p)) {
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
unlink(av, p, bck, fwd);
}
然后尝试向前合并。向前合并情况复杂点,它的处理是这样的:
代码如下:
if (nextchunk != av->top) {
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
if (!nextinuse) {
size += nextsize;
unlink(av, nextchunk, bck, fwd);
} else
clear_inuse_bit_at_offset(nextchunk, 0);
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);
}
else {
size += nextsize;
set_head(p, size | PREV_INUSE);
av->top = p;
}