new_slab_objects()がfreelistを確保するためにnew_slab()を呼んで、それが戻ってきたらという辺りのメモです。
大まかにはslub:slab objectの作成処理を見ていく - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモで書いたりしているんだけど流れが見えてきたのでもう一度。
new_slab()を呼んだということはpageをallocateした場合です。 ちょっと思い出すために、new_slab()の最後の処理を見てみます。
1417 page->freelist = start; 1418 page->inuse = page->objects; 1419 page->frozen = 1;
page->freelistにはslab objetの領域の先頭アドレスが入ります。そうすると適当な絵にするとこんな風になるかと。
そしてnew_slab()から戻ってnew_slab_objects()。cはper_cpu領域にあるデータ。古いデータがあった場合は値の入れ替えが行われる。flushっていうとキャッシュのflushを想像しちゃうけど処理内容としてはメンバ変数の入れ替え。flush_slab()は別の時に読もう。
2175 page = new_slab(s, flags, node); 2176 if (page) { 2177 c = raw_cpu_ptr(s->cpu_slab); 2178 if (c->page) 2179 flush_slab(s, c); 2180
次に行うのはfreelistをpageから外す作業。これでpageからはfreelistが参照できない。コメントにもあるけど、この時点だと誰もpage->freelistを参照していないでcmpxchg(実際は__cmpxchg_double_slabだと思うけど)を使わずに変数の更新が可能と。
2181 /* 2182 * No other reference to the page yet so we can 2183 * muck around with it freely without cmpxchg 2184 */ 2185 freelist = page->freelist; 2186 page->freelist = NULL; 2187
stat()はCONFIG_SLUB_STATSがyの時の処理。内容はs->cpu_slab(struct kmem_cache_cpu)のstat配列をALLOC_SLABをインデックスとして参照して、そこの値をインクリメントする。
2188 stat(s, ALLOC_SLAB);
struct kmem_cache_cpuのメンバ変数のpageにpageを設定。
2189 c->page = page;
pcはstruct kmem_cache_cpuでnew_slab_object()の4番目の引数として渡ってきたもの。
2190 *pc = c; 2191 } else
このpcは呼び出し元の__slab_alloc()でこのように取ったもの。CONFIG_PREEMPTはyな前提で。
2268 #ifdef CONFIG_PREEMPT 2269 /* 2270 * We may have been preempted and rescheduled on a different 2271 * cpu before disabling interrupts. Need to reload cpu area 2272 * pointer. 2273 */ 2274 c = this_cpu_ptr(s->cpu_slab); 2275 #endif
new_slab_objects()は戻り値としてfreelistを返す。
2198 2199 return freelist; 2200 }
new_slab_objects()から戻る時にはnew_slab()で確保したpageはほぼそのままper_cpuなほうのcpu_slabのpageに設定される。
ついでなのでnew_slab_object()から__slab_alloc()に戻ってからの処理も見てみます。 返ってきたfreelistがNULLだった場合の処理を飛ばすとここに。特に問題がなければload_freelistラベルにジャンプ。
2347 page = c->page; 2348 if (likely(!kmem_cache_debug(s) && pfmemalloc_match(page, gfpflags))) 2349 goto load_freelist; 2350
load_freelistはこのような処理。new_slab_object()で設定しなかったkmem_cache_cpuの変数を設定。
先ほどpage->freelistをNULLにしていたけど、ここではkmem_cache_cpuのfreelistを設定する。freelistをそのままc->freelistに入れないのはslab objectの先頭を飛ばす必要がある場合があるため。これはslub: kmem_cache構造体とslab object作成時のめも - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモで見たようにs->offsetを足してポインタをsetしたりgetしたりする。
2317 load_freelist: 2318 /* 2319 * freelist is pointing to the list of objects to be used. 2320 * page is pointing to the page from which the objects are obtained. 2321 * That page must be frozen for per cpu allocations to work. 2322 */ 2323 VM_BUG_ON(!c->page->frozen); 2324 c->freelist = get_freepointer(s, freelist);
tidはスレッドIDではなくてGlobally unique transaction id とのこと。最後にローカルIRQの割り込みを有効にしてfreelistを返す。
2325 c->tid = next_tid(c->tid); 2326 local_irq_restore(flags); 2327 return freelist;
tidは__slab_alloc()の呼び出し元のslab_alloc_node()で以下のように書かれています。
2400 /* 2401 * The transaction ids are globally unique per cpu and per operation on 2402 * a per cpu queue. Thus they can be guarantee that the cmpxchg_double 2403 * occurs on the right processor and that there was no operation on the 2404 * linked list in between. 2405 */
Rubyのしくみ -Ruby Under a Microscope-
- 作者: Pat Shaughnessy,島田浩二,角谷信太郎
- 出版社/メーカー: オーム社
- 発売日: 2014/11/29
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る