€•BEŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ(/translations/zh_CN/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/zh_TW/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/it_IT/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/ja_JP/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/ko_KR/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/pt_BR/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/sp_SP/userspace-api/futex2”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒB/var/lib/git/docbuild/linux/Documentation/userspace-api/futex2.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒfutex2”h]”hŒfutex2”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ field_list”“”)”}”(hhh]”hŒfield”“”)”}”(hhh]”(hŒ field_name”“”)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hhéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hçhhäh³hÇh´KubhŒ field_body”“”)”}”(hŒ+André Almeida ”h]”hŒ paragraph”“”)”}”(hŒ*André Almeida ”h]”(hŒAndré Almeida <”…””}”(hhÿh²hh³Nh´NubhŒ reference”“”)”}”(hŒandrealmeid@collabora.com”h]”hŒandrealmeid@collabora.com”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œ mailto:andrealmeid@collabora.com”uh1jhhÿubhŒ>”…””}”(hhÿh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khhùubah}”(h]”h ]”h"]”h$]”h&]”uh1h÷hhäubeh}”(h]”h ]”h"]”h$]”h&]”uh1hâh³hÇh´Khhßh²hubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝhhÊh²hh³hÇh´Kubhþ)”}”(hX#futex, or fast user mutex, is a set of syscalls to allow userspace to create performant synchronization mechanisms, such as mutexes, semaphores and conditional variables in userspace. C standard libraries, like glibc, uses it as a means to implement more high level interfaces like pthreads.”h]”hX#futex, or fast user mutex, is a set of syscalls to allow userspace to create performant synchronization mechanisms, such as mutexes, semaphores and conditional variables in userspace. C standard libraries, like glibc, uses it as a means to implement more high level interfaces like pthreads.”…””}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K hhÊh²hubhþ)”}”(hŒvfutex2 is a followup version of the initial futex syscall, designed to overcome limitations of the original interface.”h]”hŒvfutex2 is a followup version of the initial futex syscall, designed to overcome limitations of the original interface.”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KhhÊh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒUser API”h]”hŒUser API”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjQh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ``futex_waitv()``”h]”hŒliteral”“”)”}”(hjgh]”hŒ futex_waitv()”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjeubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjbh²hh³hÇh´Kubhþ)”}”(hŒ*Wait on an array of futexes, wake on any::”h]”hŒ)Wait on an array of futexes, wake on any:”…””}”(hj~h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khjbh²hubhŒ literal_block”“”)”}”(hŒöfutex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes, unsigned int flags, struct timespec *timeout, clockid_t clockid) struct futex_waitv { __u64 val; __u64 uaddr; __u32 flags; __u32 __reserved; };”h]”hŒöfutex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes, unsigned int flags, struct timespec *timeout, clockid_t clockid) struct futex_waitv { __u64 val; __u64 uaddr; __u32 flags; __u32 __reserved; };”…””}”hjŽsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jŒh³hÇh´Khjbh²hubhþ)”}”(hXµUserspace sets an array of struct futex_waitv (up to a max of 128 entries), using ``uaddr`` for the address to wait for, ``val`` for the expected value and ``flags`` to specify the type (e.g. private) and size of futex. ``__reserved`` needs to be 0, but it can be used for future extension. The pointer for the first item of the array is passed as ``waiters``. An invalid address for ``waiters`` or for any ``uaddr`` returns ``-EFAULT``.”h]”(hŒRUserspace sets an array of struct futex_waitv (up to a max of 128 entries), using ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ ``uaddr``”h]”hŒuaddr”…””}”(hj¤h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ for the address to wait for, ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ``val``”h]”hŒval”…””}”(hj¶h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ for the expected value and ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ ``flags``”h]”hŒflags”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ7 to specify the type (e.g. private) and size of futex. ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ``__reserved``”h]”hŒ __reserved”…””}”(hjÚh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒr needs to be 0, but it can be used for future extension. The pointer for the first item of the array is passed as ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ ``waiters``”h]”hŒwaiters”…””}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ. An invalid address for ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ ``waiters``”h]”hŒwaiters”…””}”(hjþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ or for any ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ ``uaddr``”h]”hŒuaddr”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ returns ”…””}”(hjœh²hh³Nh´Nubjj)”}”(hŒ ``-EFAULT``”h]”hŒ-EFAULT”…””}”(hj"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjœubhŒ.”…””}”(hjœh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K#hjbh²hubhþ)”}”(hŒ®If userspace has 32-bit pointers, it should do a explicit cast to make sure the upper bits are zeroed. ``uintptr_t`` does the tricky and it works for both 32/64-bit pointers.”h]”(hŒgIf userspace has 32-bit pointers, it should do a explicit cast to make sure the upper bits are zeroed. ”…””}”(hj:h²hh³Nh´Nubjj)”}”(hŒ ``uintptr_t``”h]”hŒ uintptr_t”…””}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj:ubhŒ: does the tricky and it works for both 32/64-bit pointers.”…””}”(hj:h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K*hjbh²hubhþ)”}”(hŒz``nr_futexes`` specifies the size of the array. Numbers out of [1, 128] interval will make the syscall return ``-EINVAL``.”h]”(jj)”}”(hŒ``nr_futexes``”h]”hŒ nr_futexes”…””}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjZubhŒ` specifies the size of the array. Numbers out of [1, 128] interval will make the syscall return ”…””}”(hjZh²hh³Nh´Nubjj)”}”(hŒ ``-EINVAL``”h]”hŒ-EINVAL”…””}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjZubhŒ.”…””}”(hjZh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K.hjbh²hubhþ)”}”(hŒ]The ``flags`` argument of the syscall needs to be 0, but it can be used for future extension.”h]”(hŒThe ”…””}”(hjˆh²hh³Nh´Nubjj)”}”(hŒ ``flags``”h]”hŒflags”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjˆubhŒP argument of the syscall needs to be 0, but it can be used for future extension.”…””}”(hjˆh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K1hjbh²hubhþ)”}”(hX For each entry in ``waiters`` array, the current value at ``uaddr`` is compared to ``val``. If it's different, the syscall undo all the work done so far and return ``-EAGAIN``. If all tests and verifications succeeds, syscall waits until one of the following happens:”h]”(hŒFor each entry in ”…””}”(hj¨h²hh³Nh´Nubjj)”}”(hŒ ``waiters``”h]”hŒwaiters”…””}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj¨ubhŒ array, the current value at ”…””}”(hj¨h²hh³Nh´Nubjj)”}”(hŒ ``uaddr``”h]”hŒuaddr”…””}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj¨ubhŒ is compared to ”…””}”(hj¨h²hh³Nh´Nubjj)”}”(hŒ``val``”h]”hŒval”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj¨ubhŒL. If it’s different, the syscall undo all the work done so far and return ”…””}”(hj¨h²hh³Nh´Nubjj)”}”(hŒ ``-EAGAIN``”h]”hŒ-EAGAIN”…””}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj¨ubhŒ\. If all tests and verifications succeeds, syscall waits until one of the following happens:”…””}”(hj¨h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K4hjbh²hubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ-The timeout expires, returning ``-ETIMEOUT``.”h]”hþ)”}”(hjh]”(hŒThe timeout expires, returning ”…””}”(hj h²hh³Nh´Nubjj)”}”(hŒ ``-ETIMEOUT``”h]”hŒ -ETIMEOUT”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj ubhŒ.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K9hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubj)”}”(hŒCA signal was sent to the sleeping task, returning ``-ERESTARTSYS``.”h]”hþ)”}”(hj0h]”(hŒ2A signal was sent to the sleeping task, returning ”…””}”(hj2h²hh³Nh´Nubjj)”}”(hŒ``-ERESTARTSYS``”h]”hŒ -ERESTARTSYS”…””}”(hj9h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj2ubhŒ.”…””}”(hj2h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K:hj.ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubj)”}”(hŒKSome futex at the list was woken, returning the index of some waked futex. ”h]”hþ)”}”(hŒJSome futex at the list was woken, returning the index of some waked futex.”h]”hŒJSome futex at the list was woken, returning the index of some waked futex.”…””}”(hj[h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K;hjWubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jþh³hÇh´K9hjbh²hubhþ)”}”(hŒrAn example of how to use the interface can be found at ``tools/testing/selftests/futex/functional/futex_waitv.c``.”h]”(hŒ7An example of how to use the interface can be found at ”…””}”(hjwh²hh³Nh´Nubjj)”}”(hŒ:``tools/testing/selftests/futex/functional/futex_waitv.c``”h]”hŒ6tools/testing/selftests/futex/functional/futex_waitv.c”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjwubhŒ.”…””}”(hjwh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K=hjbh²hubeh}”(h]”Œ futex-waitv”ah ]”h"]”Œ futex_waitv()”ah$]”h&]”uh1hÈhjQh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒTimeout”h]”hŒTimeout”…””}”(hj¢h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjŸh²hh³hÇh´K@ubhþ)”}”(hX``struct timespec *timeout`` argument is an optional argument that points to an absolute timeout. You need to specify the type of clock being used at ``clockid`` argument. ``CLOCK_MONOTONIC`` and ``CLOCK_REALTIME`` are supported. This syscall accepts only 64bit timespec structs.”h]”(jj)”}”(hŒ``struct timespec *timeout``”h]”hŒstruct timespec *timeout”…””}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj°ubhŒz argument is an optional argument that points to an absolute timeout. You need to specify the type of clock being used at ”…””}”(hj°h²hh³Nh´Nubjj)”}”(hŒ ``clockid``”h]”hŒclockid”…””}”(hjÆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj°ubhŒ argument. ”…””}”(hj°h²hh³Nh´Nubjj)”}”(hŒ``CLOCK_MONOTONIC``”h]”hŒCLOCK_MONOTONIC”…””}”(hjØh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj°ubhŒ and ”…””}”(hj°h²hh³Nh´Nubjj)”}”(hŒ``CLOCK_REALTIME``”h]”hŒCLOCK_REALTIME”…””}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj°ubhŒA are supported. This syscall accepts only 64bit timespec structs.”…””}”(hj°h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KBhjŸh²hubeh}”(h]”Œtimeout”ah ]”h"]”Œtimeout”ah$]”h&]”uh1hÈhjQh²hh³hÇh´K@ubhÉ)”}”(hhh]”(hÎ)”}”(hŒTypes of futex”h]”hŒTypes of futex”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj h²hh³hÇh´KHubhþ)”}”(hXA futex can be either private or shared. Private is used for processes that shares the same memory space and the virtual address of the futex will be the same for all processes. This allows for optimizations in the kernel. To use private futexes, it's necessary to specify ``FUTEX_PRIVATE_FLAG`` in the futex flag. For processes that doesn't share the same memory space and therefore can have different virtual addresses for the same futex (using, for instance, a file-backed shared memory) requires different internal mechanisms to be get properly enqueued. This is the default behavior, and it works with both private and shared futexes.”h]”(hXA futex can be either private or shared. Private is used for processes that shares the same memory space and the virtual address of the futex will be the same for all processes. This allows for optimizations in the kernel. To use private futexes, it’s necessary to specify ”…””}”(hjh²hh³Nh´Nubjj)”}”(hŒ``FUTEX_PRIVATE_FLAG``”h]”hŒFUTEX_PRIVATE_FLAG”…””}”(hj#h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihjubhXZ in the futex flag. For processes that doesn’t share the same memory space and therefore can have different virtual addresses for the same futex (using, for instance, a file-backed shared memory) requires different internal mechanisms to be get properly enqueued. This is the default behavior, and it works with both private and shared futexes.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KJhj h²hubhþ)”}”(hŒ¦Futexes can be of different sizes: 8, 16, 32 or 64 bits. Currently, the only supported one is 32 bit sized futex, and it need to be specified using ``FUTEX_32`` flag.”h]”(hŒ”Futexes can be of different sizes: 8, 16, 32 or 64 bits. Currently, the only supported one is 32 bit sized futex, and it need to be specified using ”…””}”(hj;h²hh³Nh´Nubjj)”}”(hŒ ``FUTEX_32``”h]”hŒFUTEX_32”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jihj;ubhŒ flag.”…””}”(hj;h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KThj h²hubeh}”(h]”Œtypes-of-futex”ah ]”h"]”Œtypes of futex”ah$]”h&]”uh1hÈhjQh²hh³hÇh´KHubeh}”(h]”Œuser-api”ah ]”h"]”Œuser api”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´Kubeh}”(h]”Œfutex2”ah ]”h"]”Œfutex2”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j–Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jpjmjhjejœj™jjj`j]uŒ nametypes”}”(jp‰jh‰jœ‰j‰j`‰uh}”(jmhÊjejQj™jbjjŸj]j uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.