前回はPGD周りをみたので今回はPUD周りを。PUDを作るのはpuc_alloc()でこれはいくつかの呼び出しパターンがあるのだけど(lxrでIdentifier Searchした結果からして)、一番基本であろうページフォルトの時で調べる。
ページフォルト発生時は__handle_mm_fault()内でpud_alloc()が呼ばれる。ここまでの流れは以下のようなフロー。ページフォルトが起きてarch依存部分からmmのほうに処理が流れていってます。
do_page_fault() @arch/x86/mm/fault.c -> __do_page_fault() @arch/x86/mm/fault.c -> handle_mm_fault() @mm/memory.c -> __handle_mm_fault() @mm/memory.c -> pud_alloc() @linux/mm.h
pud_alloc()はこのような関数で、pud_alloc()でpudの領域を作成してページフォルトが起きたアドレス(address)の該当するpudを返します。というわけで、pud_alloc()がここでのメイン処理ですね。
1379 static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) 1380 { 1381 return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address))? 1382 NULL: pud_offset(pgd, address); 1383 } 1384
__pud_alloc()はこのような処理です。大雑把に言うと、最初にpud_tの変数を作成するんだけど、もしpgtが既に設定されているならそれを使うので新規に作成したpudは破棄し、そうじゃない場合は、pgdに対して今作ったpudが設定される。
3990 int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) 3991 { 3992 pud_t *new = pud_alloc_one(mm, address); 3993 if (!new) 3994 return -ENOMEM; 3995 3996 smp_wmb(); /* See comment in __pte_alloc */ 3997 3998 spin_lock(&mm->page_table_lock); 3999 if (pgd_present(*pgd)) /* Another has populated it */ 4000 pud_free(mm, new); 4001 else 4002 pgd_populate(mm, pgd, new); 4003 spin_unlock(&mm->page_table_lock); 4004 return 0; 4005 }
pgd_populate()はこのような関数。
120 static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) 121 { 122 paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT); 123 set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))); 124 }
pmdもpudと同じような感じなんだけどそんなの面白いこともなさそうなのでこの辺で良いかな。。PGDをいつ作ってるのか?ってのが知りたかったというのが最初の目的だし。
ところで、__pud_alloc()で気になったのは何でpgd_present()で調べる前にpudをallocしてるのかってところなんですね。メモリバリアを張っている箇所のコメントに__pte_alloc()を見ろと書いてあるので確認をしてみます。
561 int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, 562 pmd_t *pmd, unsigned long address) 563 { 564 spinlock_t *ptl; 565 pgtable_t new = pte_alloc_one(mm, address); 566 int wait_split_huge_page; 567 if (!new) 568 return -ENOMEM; 569 570 /* 571 * Ensure all pte setup (eg. pte page lock and page clearing) are 572 * visible before the pte is made visible to other CPUs by being 573 * put into page tables. 574 * 575 * The other side of the story is the pointer chasing in the page 576 * table walking code (when walking the page table without locking; 577 * ie. most of the time). Fortunately, these data accesses consist 578 * of a chain of data-dependent loads, meaning most CPUs (alpha 579 * being the notable exception) will already guarantee loads are 580 * seen in-order. See the alpha page table accessors for the 581 * smp_read_barrier_depends() barriers in page table walking code. 582 */ 583 smp_wmb(); /* Could be smp_wmb__xxx(before|after)_spin_lock */ 584
fmfm。どうなんだろ。 確実に言えるのはpudのallocはget_zeroed_page()を使っていて、この時のGFPフラグにGFP_KERNELを使っているので必要に応じてにsleepできるんだけど、そうするとpgd_present()を行った時にはスピンロックを取っているので寝るわけには行かない。というわけでロックを取る前にallocの処理をして不要ならfree()という感じかなあ。
126 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) 127 { 128 return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); 129 }
ぱわーおぶすまいる。 (3) (まんがタイムKRコミックス)
- 作者: ウロ
- 出版社/メーカー: 芳文社
- 発売日: 2014/05/27
- メディア: コミック
- この商品を含むブログ (2件) を見る