アリーナは malloc をマルチスレッド対応するために作った仕組みです。
アリーナは malloc が使う 3 つの階層の最上位の構造体みたいなものです。
アリーナからヒープ、ヒープからチャンクというように分岐していき、単位が小さくなると考えれば良いでしょう。
ちなみにチャンクは単にメモリー領域を割り当てただけのアドレス範囲に過ぎませんが大きく分けると 2 種類が存在しますね。
原則としてスレッドに一つアリーナがあるみたいな考えで良いです。
アリーナにはスレッドロックの機能がついているので、アリーナにアクセスするには一部の領域を除いて、複数のスレッドからの同時処理がおきないように排他制御されます。
まあCPUコアの 8 倍がアリーナ数の限度らしいとも聞くので、スレッドを増やしすぎるとアリーナへのアクセスが混雑するらしいです。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c).
#define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
このマクロは 32 ビットなら CPU コア数の 2 倍が限度で 64 ビットなら CPU コア数の 8 倍が限度となります。
それでアリーナには 2 種類があります。
メインアリーナのインスタンス( main_arena )はプログラムを実行すると自動的に作られます。
この main_arena の中身は malloc() をコールするであっても GDB でチェックです。
empty.c.
1 int main(){ 2 return 0; 3 }
ビルドと実行結果.
$ gcc empty.c -g $ gdb ./a.out (gdb) break main (gdb) run Breakpoint 1, main () at empty.c:2 2 return 0; (gdb) p main_arena $1 = {mutex = 0, flags = 0, have_fastchunks = 0, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x0, last_remainder = 0x0, bins = {0x0 <repeats 254 times>}, binmap = {0, 0, 0, 0}, next = 0x7ffff7bcac40 <main_arena>, next_free = 0x0, attached_threads = 1, system_mem = 0, max_system_mem = 0}
mutex というのが同時アクセスからロックするための排他制御オブジェクトですね、
flag とか bins とか next とかありますが、これは後で説明しますね。
スレッドアリーナは mmap() が割り当てるメモリー領域に作られます。
図の「紐付けられた領域」の部分がスレッドアリーナに割り当てられます。
まあ mmap() は後で詳しく説明しますね。
それで malloc は C 言語で記述されているので、ソースコードを読めば挙動はわかりますが、その中でも抑えておきたいものが以下のリストです。
特に malloc_state / heap_info / malloc_chunk は malloc() の理解をする上で不可欠となります。
Copyright 2018-2019, by Masaki Komatsu