5.7.2.5 malloc_consolidate()
malloc_consolidate()
函数用于将
fast bins
中的
chunk
合并,并加入
unsorted
bin
中,其实现源代码如下:
/*
------------------------- 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.
*/
#if __STD_C
static void malloc_consolidate(mstate av)
#else
static void malloc_consolidate(av) mstate av;
#endif
{
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) {
clear_fastchunks(av);
unsorted_bin = unsorted_chunks(av);
如果全局变量
global_max_fast
不为零,表示
ptmalloc
已经初始化,清除分配区
flag
中
fast bin
的标志位,该标志位表示分配区的
fast bins
中包含空闲
chunk
。然后获得分配区的
unsorted bin
。
/*
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.
*/
#if 0
/* It is wrong to limit the fast bins to search using get_max_fast
because, except for the main arena, all the others might have
blocks in the high fast bins. It's not worth it anyway, just
search all bins all the time. */
maxfb = &fastbin (av, fastbin_index(get_max_fast ()));
#else
maxfb = &fastbin (av, NFASTBINS - 1);
#endif
fb = &fastbin (av, 0);
将分配区最大的一个fast bin赋值给maxfb,第一个fast bin赋值给fb,然后遍历fast bins。
do {
#ifdef ATOMIC_FASTBINS
p = atomic_exchange_acq (fb, 0);
#else
p = *fb;
#endif
if (p != 0) {
#ifndef ATOMIC_FASTBINS
*fb = 0;
#endif
获取当前遍历的fast bin中空闲chunk单向链表的头指针赋值给p,如果p不为0,将当前fast bin链表的头指针赋值为0,即删除了该fast bin中的空闲chunk链表。
do {
check_inuse_chunk(av, p);
nextp = p->fd;
将空闲chunk链表的下一个chunk赋值给nextp。
/* 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的size,需要去除size中的PREV_INUSE和NON_MAIN_ARENA标志,并获取相邻的下一个chunk和下一个chunk的大小。
if (!prev_inuse(p)) {
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
unlink(p, bck, fwd);
}
如果当前chunk的前一个chunk空闲,则将当前chunk与前一个chunk合并成一个空闲chunk,由于前一个chunk空闲,则当前chunk的prev_size保存了前一个chunk的大小,计算出合并后的chunk大小,并获取前一个chunk的指针,将前一个chunk从空闲链表中删除。
if (nextchunk != av->top) {
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
如果与当前chunk相邻的下一个chunk不是分配区的top chunk,查看与当前chunk相邻的下一个chunk是否处于inuse状态。
if (!nextinuse) {
size += nextsize;
unlink(nextchunk, bck, fwd);
} else
clear_inuse_bit_at_offset(nextchunk, 0);
如果与当前chunk相邻的下一个chunk处于inuse状态,清除当前chunk的inuse状态,则当前chunk空闲了。否则,将相邻的下一个空闲chunk从空闲链表中删除,并计算当前chunk与下一个chunk合并后的chunk大小。
first_unsorted = unsorted_bin->fd;
unsorted_bin->fd = p;
first_unsorted->bk = p;
将合并后的chunk加入unsorted bin的双向循环链表中。
if (!in_smallbin_range (size)) {
p->fd_nextsize = NULL;
p->bk_nextsize = NULL;
}
如果合并后的chunk属于large bin,将chunk的fd_nextsize和bk_nextsize设置为NULL,因为在unsorted bin中这两个字段无用。
set_head(p, size | PREV_INUSE);
p->bk = unsorted_bin;
p->fd = first_unsorted;
set_foot(p, size);
设置合并后的空闲chunk大小,并标识前一个chunk处于inuse状态,因为必须保证不能有两个相邻的chunk都处于空闲状态。然后将合并后的chunk加入unsorted bin的双向循环链表中。最后设置合并后的空闲chunk的foot,chunk空闲时必须设置foot,该foot处于下一个chunk的prev_size中,只有chunk空闲是foot才是有效的。
}
else {
size += nextsize;
set_head(p, size | PREV_INUSE);
av->top = p;
}
如果当前chunk的下一个chunk为top chunk,则将当前chunk合并入top chunk,修改top chunk的大小。
} while ( (p = nextp) != 0);
直到遍历完当前fast bin中的所有空闲chunk。
}
} while (fb++ != maxfb);
直到遍历完所有的fast bins。
}
else {
malloc_init_state(av);
check_malloc_state(av);
如果ptmalloc没有初始化,初始化ptmalloc。
}
}
分享到:
相关推荐
NULL 博文链接:https://mqzhuang.iteye.com/blog/1064966
Glibc内存管理 Ptmalloc2 源代码分析
glibc内存管理ptmalloc源代码分析-电子资料-高清PDF版-pdf打印版
简介133.2.2内存管理的设计假设 143.2.3内存管理数据结构概述 143.2.4内存分配概述 193.2.5内存回收概述 213.2.6配置选项概述 2
淘宝网的研发人员写的文档,对了解GNU C的内存分配机制有很大的帮助!
该文档详细分析了c库中的内存管理细节,可广大程序员做参考。
简介133.2.2内存管理的设计假设 143.2.3内存管理数据结构概述 143.2.4内存分配概述 193.2.5内存回收概述 213.2.6配置选项概述 2
清晰版,对内存分析,程序设计非常有帮助。适合进阶的。
5. 源代码分析 5.1 边界标记法 5.2 分箱式内存管理 5.2.1 Small bins 5.2.2 Large bins 5.2.3 Unsorted bin 5.2.4 Fast bins 5.3 核心结构体分析 5.3.1 malloc_state 5.3.2 Malloc_par 5.3.3 分配区的初始...
glibc内存管理ptmalloc源代码分析.pdf
源代码分析 glibc的ptmalloc 分析
glibc内存管理ptmalloc源代码分析4.pdf
学习自《glibc内存管理ptmalloc源代码分析》庄明强 著 部分资料参考自互联网 chunk 描述: 当用户通过malloc等函数申请空间时,实际上是从堆中分配内存 目前 Linux 标准发行版中使用的是 glibc 中的堆分配器:...