1ee65728eSMike Rapoport:Original: Documentation/mm/split_page_table_lock.rst 2ee65728eSMike Rapoport 3ee65728eSMike Rapoport:翻译: 4ee65728eSMike Rapoport 5ee65728eSMike Rapoport 司延腾 Yanteng Si <siyanteng@loongson.cn> 6ee65728eSMike Rapoport 7ee65728eSMike Rapoport:校译: 8ee65728eSMike Rapoport 9ee65728eSMike Rapoport 10ee65728eSMike Rapoport================================= 11ee65728eSMike Rapoport分页表锁(split page table lock) 12ee65728eSMike Rapoport================================= 13ee65728eSMike Rapoport 14ee65728eSMike Rapoport最初,mm->page_table_lock spinlock保护了mm_struct的所有页表。但是这种方 15ee65728eSMike Rapoport法导致了多线程应用程序的缺页异常可扩展性差,因为对锁的争夺很激烈。为了提高可扩 16ee65728eSMike Rapoport展性,我们引入了分页表锁。 17ee65728eSMike Rapoport 18ee65728eSMike Rapoport有了分页表锁,我们就有了单独的每张表锁来顺序化对表的访问。目前,我们对PTE和 19ee65728eSMike RapoportPMD表使用分页锁。对高层表的访问由mm->page_table_lock保护。 20ee65728eSMike Rapoport 21ee65728eSMike Rapoport有一些辅助工具来锁定/解锁一个表和其他访问器函数: 22ee65728eSMike Rapoport 23ee65728eSMike Rapoport - pte_offset_map_lock() 24ee65728eSMike Rapoport 映射pte并获取PTE表锁,返回所取锁的指针; 25ee65728eSMike Rapoport - pte_unmap_unlock() 26ee65728eSMike Rapoport 解锁和解映射PTE表; 27ee65728eSMike Rapoport - pte_alloc_map_lock() 28ee65728eSMike Rapoport 如果需要的话,分配PTE表并获取锁,如果分配失败,返回已获取的锁的指针 29ee65728eSMike Rapoport 或NULL; 30ee65728eSMike Rapoport - pte_lockptr() 31ee65728eSMike Rapoport 返回指向PTE表锁的指针; 32ee65728eSMike Rapoport - pmd_lock() 33ee65728eSMike Rapoport 取得PMD表锁,返回所取锁的指针。 34ee65728eSMike Rapoport - pmd_lockptr() 35ee65728eSMike Rapoport 返回指向PMD表锁的指针; 36ee65728eSMike Rapoport 37ee65728eSMike Rapoport如果CONFIG_SPLIT_PTLOCK_CPUS(通常为4)小于或等于NR_CPUS,则在编译 38ee65728eSMike Rapoport时启用PTE表的分页表锁。如果分页锁被禁用,所有的表都由mm->page_table_lock 39ee65728eSMike Rapoport来保护。 40ee65728eSMike Rapoport 41ee65728eSMike Rapoport如果PMD表启用了分页锁,并且架构支持它,那么PMD表的分页锁就会被启用(见 42ee65728eSMike Rapoport下文)。 43ee65728eSMike Rapoport 44ee65728eSMike RapoportHugetlb 和分页表锁 45ee65728eSMike Rapoport================== 46ee65728eSMike Rapoport 47ee65728eSMike RapoportHugetlb可以支持多种页面大小。我们只对PMD级别使用分页锁,但不对PUD使用。 48ee65728eSMike Rapoport 49ee65728eSMike RapoportHugetlb特定的辅助函数: 50ee65728eSMike Rapoport 51ee65728eSMike Rapoport - huge_pte_lock() 52ee65728eSMike Rapoport 对PMD_SIZE页面采取pmd分割锁,否则mm->page_table_lock; 53ee65728eSMike Rapoport - huge_pte_lockptr() 54ee65728eSMike Rapoport 返回指向表锁的指针。 55ee65728eSMike Rapoport 56ee65728eSMike Rapoport架构对分页表锁的支持 57ee65728eSMike Rapoport==================== 58ee65728eSMike Rapoport 59*9a4bbd8dSVishal Moola (Oracle)没有必要特别启用PTE分页表锁:所有需要的东西都由pagetable_pte_ctor() 60*9a4bbd8dSVishal Moola (Oracle)和pagetable_pte_dtor()完成,它们必须在PTE表分配/释放时被调用。 61ee65728eSMike Rapoport 62ee65728eSMike Rapoport确保架构不使用slab分配器来分配页表:slab使用page->slab_cache来分配其页 63ee65728eSMike Rapoport面。这个区域与page->ptl共享存储。 64ee65728eSMike Rapoport 65ee65728eSMike RapoportPMD分页锁只有在你有两个以上的页表级别时才有意义。 66ee65728eSMike Rapoport 67*9a4bbd8dSVishal Moola (Oracle)启用PMD分页锁需要在PMD表分配时调用pagetable_pmd_ctor(),在释放时调 68*9a4bbd8dSVishal Moola (Oracle)用pagetable_pmd_dtor()。 69ee65728eSMike Rapoport 70ee65728eSMike Rapoport分配通常发生在pmd_alloc_one()中,释放发生在pmd_free()和pmd_free_tlb() 71ee65728eSMike Rapoport中,但要确保覆盖所有的PMD表分配/释放路径:即X86_PAE在pgd_alloc()中预先 72ee65728eSMike Rapoport分配一些PMD。 73ee65728eSMike Rapoport 74ee65728eSMike Rapoport一切就绪后,你可以设置CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK。 75ee65728eSMike Rapoport 76*9a4bbd8dSVishal Moola (Oracle)注意:pagetable_pte_ctor()和pagetable_pmd_ctor()可能失败--必 77ee65728eSMike Rapoport须正确处理。 78ee65728eSMike Rapoport 79ee65728eSMike Rapoportpage->ptl 80ee65728eSMike Rapoport========= 81ee65728eSMike Rapoport 82ee65728eSMike Rapoportpage->ptl用于访问分割页表锁,其中'page'是包含该表的页面struct page。它 83ee65728eSMike Rapoport与page->private(以及union中的其他几个字段)共享存储。 84ee65728eSMike Rapoport 85ee65728eSMike Rapoport为了避免增加struct page的大小并获得最佳性能,我们使用了一个技巧: 86ee65728eSMike Rapoport 87ee65728eSMike Rapoport - 如果spinlock_t适合于long,我们使用page->ptr作为spinlock,这样我们 88ee65728eSMike Rapoport 就可以避免间接访问并节省一个缓存行。 89ee65728eSMike Rapoport - 如果spinlock_t的大小大于long的大小,我们使用page->ptl作为spinlock_t 90ee65728eSMike Rapoport 的指针并动态分配它。这允许在启用DEBUG_SPINLOCK或DEBUG_LOCK_ALLOC的 91ee65728eSMike Rapoport 情况下使用分页锁,但由于间接访问而多花了一个缓存行。 92ee65728eSMike Rapoport 93*9a4bbd8dSVishal Moola (Oracle)PTE表的spinlock_t分配在pagetable_pte_ctor()中,PMD表的spinlock_t 94*9a4bbd8dSVishal Moola (Oracle)分配在pagetable_pmd_ctor()中。 95ee65728eSMike Rapoport 96ee65728eSMike Rapoport请不要直接访问page->ptl - -使用适当的辅助函数。 97