\sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget,/translations/zh_CN/mm/split_page_table_lockmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/zh_TW/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/it_IT/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/ja_JP/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/ko_KR/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/sp_SP/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(hSplit page table lockh]hSplit page table lock}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhF/var/lib/git/docbuild/linux/Documentation/mm/split_page_table_lock.rsthKubh paragraph)}(hX Originally, mm->page_table_lock spinlock protected all page tables of the mm_struct. But this approach leads to poor page fault scalability of multi-threaded applications due to high contention on the lock. To improve scalability, split page table lock was introduced.h]hX Originally, mm->page_table_lock spinlock protected all page tables of the mm_struct. But this approach leads to poor page fault scalability of multi-threaded applications due to high contention on the lock. To improve scalability, split page table lock was introduced.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hWith split page table lock we have separate per-table lock to serialize access to the table. At the moment we use split lock for PTE and PMD tables. Access to higher level tables protected by mm->page_table_lock.h]hWith split page table lock we have separate per-table lock to serialize access to the table. At the moment we use split lock for PTE and PMD tables. Access to higher level tables protected by mm->page_table_lock.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hFThere are helpers to lock/unlock a table and other accessor functions:h]hFThere are helpers to lock/unlock a table and other accessor functions:}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh block_quote)}(hX- pte_offset_map_lock() maps PTE and takes PTE table lock, returns pointer to PTE with pointer to its PTE table lock, or returns NULL if no PTE table; - pte_offset_map_ro_nolock() maps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken), or returns NULL if no PTE table; - pte_offset_map_rw_nolock() maps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken) and the value of its pmd entry, or returns NULL if no PTE table; - pte_offset_map() maps PTE, returns pointer to PTE, or returns NULL if no PTE table; - pte_unmap() unmaps PTE table; - pte_unmap_unlock() unlocks and unmaps PTE table; - pte_alloc_map_lock() allocates PTE table if needed and takes its lock, returns pointer to PTE with pointer to its lock, or returns NULL if allocation failed; - pmd_lock() takes PMD table lock, returns pointer to taken lock; - pmd_lockptr() returns pointer to PMD table lock; h]h bullet_list)}(hhh](h list_item)}(hpte_offset_map_lock() maps PTE and takes PTE table lock, returns pointer to PTE with pointer to its PTE table lock, or returns NULL if no PTE table;h]hdefinition_list)}(hhh]hdefinition_list_item)}(hpte_offset_map_lock() maps PTE and takes PTE table lock, returns pointer to PTE with pointer to its PTE table lock, or returns NULL if no PTE table;h](hterm)}(hpte_offset_map_lock()h]hpte_offset_map_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhubh definition)}(hhh]h)}(h~maps PTE and takes PTE table lock, returns pointer to PTE with pointer to its PTE table lock, or returns NULL if no PTE table;h]h~maps PTE and takes PTE table lock, returns pointer to PTE with pointer to its PTE table lock, or returns NULL if no PTE table;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubah}(h]h ]h"]h$]h&]uh1hhhubh)}(hpte_offset_map_ro_nolock() maps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken), or returns NULL if no PTE table;h]h)}(hhh]h)}(hpte_offset_map_ro_nolock() maps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken), or returns NULL if no PTE table;h](j)}(hpte_offset_map_ro_nolock()h]hpte_offset_map_ro_nolock()}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAubj)}(hhh]h)}(hqmaps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken), or returns NULL if no PTE table;h]hqmaps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken), or returns NULL if no PTE table;}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjSubah}(h]h ]h"]h$]h&]uh1jhjAubeh}(h]h ]h"]h$]h&]uh1hhhhKhj>ubah}(h]h ]h"]h$]h&]uh1hhj:ubah}(h]h ]h"]h$]h&]uh1hhhubh)}(hpte_offset_map_rw_nolock() maps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken) and the value of its pmd entry, or returns NULL if no PTE table;h]h)}(hhh]h)}(hpte_offset_map_rw_nolock() maps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken) and the value of its pmd entry, or returns NULL if no PTE table;h](j)}(hpte_offset_map_rw_nolock()h]hpte_offset_map_rw_nolock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hhh]h)}(hmaps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken) and the value of its pmd entry, or returns NULL if no PTE table;h]hmaps PTE, returns pointer to PTE with pointer to its PTE table lock (not taken) and the value of its pmd entry, or returns NULL if no PTE table;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhj|ubah}(h]h ]h"]h$]h&]uh1hhhubh)}(hXpte_offset_map() maps PTE, returns pointer to PTE, or returns NULL if no PTE table;h]h)}(hhh]h)}(hSpte_offset_map() maps PTE, returns pointer to PTE, or returns NULL if no PTE table;h](j)}(hpte_offset_map()h]hpte_offset_map()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hhh]h)}(hBmaps PTE, returns pointer to PTE, or returns NULL if no PTE table;h]hBmaps PTE, returns pointer to PTE, or returns NULL if no PTE table;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h"pte_unmap() unmaps PTE table;h]h)}(hhh]h)}(hpte_unmap() unmaps PTE table;h](j)}(h pte_unmap()h]h pte_unmap()}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hhh]h)}(hunmaps PTE table;h]hunmaps PTE table;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h5pte_unmap_unlock() unlocks and unmaps PTE table;h]h)}(hhh]h)}(h0pte_unmap_unlock() unlocks and unmaps PTE table;h](j)}(hpte_unmap_unlock()h]hpte_unmap_unlock()}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjIubj)}(hhh]h)}(hunlocks and unmaps PTE table;h]hunlocks and unmaps PTE table;}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj[ubah}(h]h ]h"]h$]h&]uh1jhjIubeh}(h]h ]h"]h$]h&]uh1hhhhKhjFubah}(h]h ]h"]h$]h&]uh1hhjBubah}(h]h ]h"]h$]h&]uh1hhhubh)}(hpte_alloc_map_lock() allocates PTE table if needed and takes its lock, returns pointer to PTE with pointer to its lock, or returns NULL if allocation failed;h]h)}(hhh]h)}(hpte_alloc_map_lock() allocates PTE table if needed and takes its lock, returns pointer to PTE with pointer to its lock, or returns NULL if allocation failed;h](j)}(hpte_alloc_map_lock()h]hpte_alloc_map_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK!hjubj)}(hhh]h)}(hallocates PTE table if needed and takes its lock, returns pointer to PTE with pointer to its lock, or returns NULL if allocation failed;h]hallocates PTE table if needed and takes its lock, returns pointer to PTE with pointer to its lock, or returns NULL if allocation failed;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK!hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK!hjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubh)}(hDpmd_lock() takes PMD table lock, returns pointer to taken lock;h]h)}(hhh]h)}(h?pmd_lock() takes PMD table lock, returns pointer to taken lock;h](j)}(h pmd_lock()h]h pmd_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK#hjubj)}(hhh]h)}(h4takes PMD table lock, returns pointer to taken lock;h]h4takes PMD table lock, returns pointer to taken lock;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK#hjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h6pmd_lockptr() returns pointer to PMD table lock; h]h)}(hhh]h)}(h1pmd_lockptr() returns pointer to PMD table lock; h](j)}(h pmd_lockptr()h]h pmd_lockptr()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK&hjubj)}(hhh]h)}(h"returns pointer to PMD table lock;h]h"returns pointer to PMD table lock;}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK&hj!ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK&hj ubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]bullet-uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hSplit page table lock for PTE tables is enabled compile-time if CONFIG_SPLIT_PTLOCK_CPUS (usually 4) is less or equal to NR_CPUS. If split lock is disabled, all tables are guarded by mm->page_table_lock.h]hSplit page table lock for PTE tables is enabled compile-time if CONFIG_SPLIT_PTLOCK_CPUS (usually 4) is less or equal to NR_CPUS. If split lock is disabled, all tables are guarded by mm->page_table_lock.}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK(hhhhubh)}(h}Split page table lock for PMD tables is enabled, if it's enabled for PTE tables and the architecture supports it (see below).h]hSplit page table lock for PMD tables is enabled, if it’s enabled for PTE tables and the architecture supports it (see below).}(hjfhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK,hhhhubh)}(hhh](h)}(h!Hugetlb and split page table lockh]h!Hugetlb and split page table lock}(hjwhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjthhhhhK0ubh)}(h^Hugetlb can support several page sizes. We use split lock only for PMD level, but not for PUD.h]h^Hugetlb can support several page sizes. We use split lock only for PMD level, but not for PUD.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK2hjthhubh)}(hHugetlb-specific helpers:h]hHugetlb-specific helpers:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK5hjthhubh)}(h- huge_pte_lock() takes pmd split lock for PMD_SIZE page, mm->page_table_lock otherwise; - huge_pte_lockptr() returns pointer to table lock; h]h)}(hhh](h)}(h`huge_pte_lock() takes pmd split lock for PMD_SIZE page, mm->page_table_lock otherwise;h]h)}(hhh]h)}(hVhuge_pte_lock() takes pmd split lock for PMD_SIZE page, mm->page_table_lock otherwise;h](j)}(hhuge_pte_lock()h]hhuge_pte_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK8hjubj)}(hhh]h)}(hFtakes pmd split lock for PMD_SIZE page, mm->page_table_lock otherwise;h]hFtakes pmd split lock for PMD_SIZE page, mm->page_table_lock otherwise;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK8hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK8hjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h7huge_pte_lockptr() returns pointer to table lock; h]h)}(hhh]h)}(h2huge_pte_lockptr() returns pointer to table lock; h](j)}(hhuge_pte_lockptr()h]hhuge_pte_lockptr()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjubj)}(hhh]h)}(hreturns pointer to table lock;h]hreturns pointer to table lock;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK;hjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]jPjQuh1hhhhK7hjubah}(h]h ]h"]h$]h&]uh1hhhhK7hjthhubeh}(h]!hugetlb-and-split-page-table-lockah ]h"]!hugetlb and split page table lockah$]h&]uh1hhhhhhhhK0ubh)}(hhh](h)}(h3Support of split page table lock by an architectureh]h3Support of split page table lock by an architecture}(hjChhhNhNubah}(h]h ]h"]h$]h&]uh1hhj@hhhhhK>ubh)}(hThere's no need in special enabling of PTE split page table lock: everything required is done by pagetable_pte_ctor() and pagetable_dtor(), which must be called on PTE table allocation / freeing.h]hThere’s no need in special enabling of PTE split page table lock: everything required is done by pagetable_pte_ctor() and pagetable_dtor(), which must be called on PTE table allocation / freeing.}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK@hj@hhubh)}(hMake sure the architecture doesn't use slab allocator for page table allocation: slab uses page->slab_cache for its pages. This field shares storage with page->ptl.h]hMake sure the architecture doesn’t use slab allocator for page table allocation: slab uses page->slab_cache for its pages. This field shares storage with page->ptl.}(hj_hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKDhj@hhubh)}(hLPMD split lock only makes sense if you have more than two page table levels.h]hLPMD split lock only makes sense if you have more than two page table levels.}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKHhj@hhubh)}(hsPMD split lock enabling requires pagetable_pmd_ctor() call on PMD table allocation and pagetable_dtor() on freeing.h]hsPMD split lock enabling requires pagetable_pmd_ctor() call on PMD table allocation and pagetable_dtor() on freeing.}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKKhj@hhubh)}(hAllocation usually happens in pmd_alloc_one(), freeing in pmd_free() and pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().h]hAllocation usually happens in pmd_alloc_one(), freeing in pmd_free() and pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKNhj@hhubh)}(hIWith everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.h]hIWith everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKRhj@hhubh)}(h\NOTE: pagetable_pte_ctor() and pagetable_pmd_ctor() can fail -- it must be handled properly.h]h\NOTE: pagetable_pte_ctor() and pagetable_pmd_ctor() can fail -- it must be handled properly.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKThj@hhubeh}(h]3support-of-split-page-table-lock-by-an-architectureah ]h"]3support of split page table lock by an architectureah$]h&]uh1hhhhhhhhK>ubh)}(hhh](h)}(h page->ptlh]h page->ptl}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKXubh)}(hpage->ptl is used to access split page table lock, where 'page' is struct page of page containing the table. It shares storage with page->private (and few other fields in union).h]hpage->ptl is used to access split page table lock, where ‘page’ is struct page of page containing the table. It shares storage with page->private (and few other fields in union).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKZhjhhubh)}(hRTo avoid increasing size of struct page and have best performance, we use a trick:h]hRTo avoid increasing size of struct page and have best performance, we use a trick:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK^hjhhubh)}(hX{- if spinlock_t fits into long, we use page->ptr as spinlock, so we can avoid indirect access and save a cache line. - if size of spinlock_t is bigger then size of long, we use page->ptl as pointer to spinlock_t and allocate it dynamically. This allows to use split lock with enabled DEBUG_SPINLOCK or DEBUG_LOCK_ALLOC, but costs one more cache line for indirect access; h]h)}(hhh](h)}(hrif spinlock_t fits into long, we use page->ptr as spinlock, so we can avoid indirect access and save a cache line.h]h)}(hrif spinlock_t fits into long, we use page->ptr as spinlock, so we can avoid indirect access and save a cache line.h]hrif spinlock_t fits into long, we use page->ptr as spinlock, so we can avoid indirect access and save a cache line.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKahjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(hif size of spinlock_t is bigger then size of long, we use page->ptl as pointer to spinlock_t and allocate it dynamically. This allows to use split lock with enabled DEBUG_SPINLOCK or DEBUG_LOCK_ALLOC, but costs one more cache line for indirect access; h]h)}(hif size of spinlock_t is bigger then size of long, we use page->ptl as pointer to spinlock_t and allocate it dynamically. This allows to use split lock with enabled DEBUG_SPINLOCK or DEBUG_LOCK_ALLOC, but costs one more cache line for indirect access;h]hif size of spinlock_t is bigger then size of long, we use page->ptl as pointer to spinlock_t and allocate it dynamically. This allows to use split lock with enabled DEBUG_SPINLOCK or DEBUG_LOCK_ALLOC, but costs one more cache line for indirect access;}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKchjubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]jPjQuh1hhhhKahjubah}(h]h ]h"]h$]h&]uh1hhhhKahjhhubh)}(hiThe spinlock_t allocated in pagetable_pte_ctor() for PTE table and in pagetable_pmd_ctor() for PMD table.h]hiThe spinlock_t allocated in pagetable_pte_ctor() for PTE table and in pagetable_pmd_ctor() for PMD table.}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhjhhubh)}(hBPlease, never access page->ptl directly -- use appropriate helper.h]hBPlease, never access page->ptl directly -- use appropriate helper.}(hj9hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKkhjhhubeh}(h]page-ptlah ]h"] page->ptlah$]h&]uh1hhhhhhhhKXubeh}(h]split-page-table-lockah ]h"]split page table lockah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjzerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jTjQj=j:jjjLjIu nametypes}(jTj=jjLuh}(jQhj:jtjj@jIju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.