malloc読んでみた3 mallocの中のデータ型
mallocで使われるデータ型はまずarenaがあります。
arenaはarena_bin_tの配列を持っています。
struct arena_s {
...
arena_bin_t bins[1]; /* Dynamically sized. */
};
arena_binはarena_runの赤黒木を持っています。
struct arena_bin_s {
arena_run_t *runcur;
/*
* Tree of non-full runs. This tree is used when looking for an
* existing run when runcur is no longer usable. We choose the
* non-full run that is lowest in memory; this policy tends to keep
* objects packed well, and it can also help reduce the number of
* almost-empty chunks.
*/
arena_run_tree_t runs;
...
};
arena_newの中でarena->binsが準備されていきます。
i = 0;
/* (2^n)-spaced tiny bins. */
for (; i < ntbins; i++) {
bin = &arena->bins[i];
bin->runcur = NULL;
arena_run_tree_new(&bin->runs);
bin->reg_size = (1U << (TINY_MIN_2POW + i));
prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
....
}
それぞれのbinの中にtreeを作り
bin->reg_sizeを設定します。
arena_bin_run_size_calc内ではなるべく大きなrun_sizeを探し
bin->run_size
bin->nregs
bin->regs_mask_nelms
bin->reg0_offset
を設定します。
arena_bin_nonfull_run_getでbin->runsから使用可能なrunをもってきます。ない場合はarena_run_allocでrunを作ります。
bin->runsizeはarena_run_allocのsizeに使われます。
arena_run_allocではarena->runs_availから探し返します。無い場合はarena_chunk_allocをしてその先頭をrunとして返します。
chunk = arena_chunk_alloc(arena);
if (chunk == NULL)
return (NULL);
run = (arena_run_t *) ( (uintptr_t)chunk + (arena_chunk_header_npages < <
PAGE_SHIFT));
/* Update page map. */
arena_run_split(arena, run, size, large, zero);
return (run); (2720)
mallocが呼ばれた時のsizeに応じてbinを探し出します。 例えば
arena_malloc_small(arena_t *arena, size_t size, bool zero)
{
...
binind = size2bin[size];
...
bin = &arena->bins[binind];
size = bin->reg_size;
...
のようになります。そしてarena_bin_nonfull_run_getを呼びそのbinからrunを取ります。そのrunからメモリーをarena_run_reg_allocで取り出します。
arenaとbinとrunの関係がわかりました。次はchunkについて見てみましょう。