:Original: Documentation/mm/split_page_table_lock.rst :翻译: å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn> :æ ¡è¯‘: ================================= 分页表é”(split page table lock) ================================= 最åˆï¼Œmm->page_table_lock spinlockä¿æŠ¤äº†mm_struct的所有页表。但是这ç§æ–¹ 法导致了多线程应用程åºçš„缺页异常å¯æ‰©å±•æ€§å·®ï¼Œå› 为对é”的争夺很激烈。为了æ高å¯æ‰© 展性,我们引入了分页表é”。 有了分页表é”,我们就有了å•ç‹¬çš„æ¯å¼ 表é”æ¥é¡ºåºåŒ–对表的访问。目å‰ï¼Œæˆ‘们对PTEå’Œ PMD表使用分页é”。对高层表的访问由mm->page_table_lockä¿æŠ¤ã€‚ 有一些辅助工具æ¥é”定/解é”一个表和其他访问器函数: - pte_offset_map_lock() æ˜ å°„pte并获å–PTE表é”,返回所å–é”的指针; - pte_unmap_unlock() 解é”å’Œè§£æ˜ å°„PTE表; - pte_alloc_map_lock() 如果需è¦çš„è¯ï¼Œåˆ†é…PTE表并获å–é”,如果分é…失败,返回已获å–çš„é”的指针 或NULLï¼› - pte_lockptr() 返回指å‘PTE表é”的指针; - pmd_lock() å–å¾—PMD表é”,返回所å–é”的指针。 - pmd_lockptr() 返回指å‘PMD表é”的指针; 如果CONFIG_SPLIT_PTLOCK_CPUS(通常为4)å°äºŽæˆ–ç‰äºŽNR_CPUS,则在编译 æ—¶å¯ç”¨PTE表的分页表é”。如果分页é”被ç¦ç”¨ï¼Œæ‰€æœ‰çš„表都由mm->page_table_lock æ¥ä¿æŠ¤ã€‚ 如果PMD表å¯ç”¨äº†åˆ†é¡µé”,并且架构支æŒå®ƒï¼Œé‚£ä¹ˆPMD表的分页é”就会被å¯ç”¨ï¼ˆè§ 下文)。 Hugetlb å’Œåˆ†é¡µè¡¨é” ================== Hugetlbå¯ä»¥æ”¯æŒå¤šç§é¡µé¢å¤§å°ã€‚我们åªå¯¹PMD级别使用分页é”,但ä¸å¯¹PUD使用。 Hugetlb特定的辅助函数: - huge_pte_lock() 对PMD_SIZE页é¢é‡‡å–pmd分割é”,å¦åˆ™mm->page_table_lockï¼› - huge_pte_lockptr() 返回指å‘表é”的指针。 架构对分页表é”çš„æ”¯æŒ ==================== 没有必è¦ç‰¹åˆ«å¯ç”¨PTE分页表é”:所有需è¦çš„东西都由pgtable_pte_page_ctor() å’Œpgtable_pte_page_dtor()完æˆï¼Œå®ƒä»¬å¿…须在PTE表分é…/释放时被调用。 ç¡®ä¿æž¶æž„ä¸ä½¿ç”¨slab分é…器æ¥åˆ†é…页表:slab使用page->slab_cacheæ¥åˆ†é…其页 é¢ã€‚这个区域与page->ptl共享å˜å‚¨ã€‚ PMD分页é”åªæœ‰åœ¨ä½ 有两个以上的页表级别时æ‰æœ‰æ„义。 å¯ç”¨PMD分页é”需è¦åœ¨PMD表分é…时调用pgtable_pmd_page_ctor(),在释放时调 用pgtable_pmd_page_dtor()。 分é…通常å‘生在pmd_alloc_one()ä¸ï¼Œé‡Šæ”¾å‘生在pmd_free()å’Œpmd_free_tlb() ä¸ï¼Œä½†è¦ç¡®ä¿è¦†ç›–所有的PMD表分é…/释放路径:å³X86_PAE在pgd_alloc()ä¸é¢„å…ˆ 分é…一些PMD。 一切就绪åŽï¼Œä½ å¯ä»¥è®¾ç½®CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK。 注æ„:pgtable_pte_page_ctor()å’Œpgtable_pmd_page_ctor()å¯èƒ½å¤±è´¥--å¿… é¡»æ£ç¡®å¤„ç†ã€‚ page->ptl ========= page->ptl用于访问分割页表é”,其ä¸'page'是包å«è¯¥è¡¨çš„页é¢struct page。它 与page->private(以åŠunionä¸çš„å…¶ä»–å‡ ä¸ªå—段)共享å˜å‚¨ã€‚ 为了é¿å…å¢žåŠ struct page的大å°å¹¶èŽ·å¾—最佳性能,我们使用了一个技巧: - 如果spinlock_t适åˆäºŽlong,我们使用page->ptr作为spinlockï¼Œè¿™æ ·æˆ‘ä»¬ å°±å¯ä»¥é¿å…间接访问并节çœä¸€ä¸ªç¼“å˜è¡Œã€‚ - 如果spinlock_t的大å°å¤§äºŽlong的大å°ï¼Œæˆ‘们使用page->ptl作为spinlock_t 的指针并动æ€åˆ†é…它。这å…许在å¯ç”¨DEBUG_SPINLOCK或DEBUG_LOCK_ALLOCçš„ 情况下使用分页é”,但由于间接访问而多花了一个缓å˜è¡Œã€‚ PTE表的spinlock_t分é…在pgtable_pte_page_ctor()ä¸ï¼ŒPMD表的spinlock_t 分é…在pgtable_pmd_page_ctor()ä¸ã€‚ 请ä¸è¦ç›´æŽ¥è®¿é—®page->ptl - -使用适当的辅助函数。