From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ua1-x92d.google.com (mail-ua1-x92d.google.com [IPv6:2607:f8b0:4864:20::92d]) by sourceware.org (Postfix) with ESMTPS id 29DB8383D02C; Mon, 2 Aug 2021 13:29:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 29DB8383D02C Received: by mail-ua1-x92d.google.com with SMTP id 67so1151607uaq.4; Mon, 02 Aug 2021 06:29:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Vxl/HbShZqjTROa44CFsBRkHhJVRuBUVqjz09ZMV/Mc=; b=CKYUNbF7rab4QgGHv5rw4jXOwdupvp7YmaYCoLpA5OdfzlFH9g9Y7U6ix7+bA8xYnc 1o3fXBSHWEKiAutkqdF90MG2e+xkgjw/Ii097JTq7+fMDdFGZOdditFIpuGTZY5RyBQB I1Z0sf0q2hvCR+EfZowIlEpckZwI9Ov8KC/z0AHF0vXZosbfMCLOVxuogovaTPvCqZt3 +hTIwJy5/irl2M9wbX5IMXkZEN2jtSvw7m1ICGXWGYsTXyx8hb+5ZaiWHmuA3WWwfsR8 FW6xSuvTjSCNLd1yMsj7o7V1Po/5uH6ysZTnClXELu0ylEmGaWAdQV2LUyrNi+v44lPC l8Xg== X-Gm-Message-State: AOAM533OMSivgS37PYC4/s/C4xX0juj6gH1Uv8XTa+KOPoI+mL6gehEN OIT3aYKKwTOPfeSBJC3KiYhU1T63o7fqWHjqJyw= X-Google-Smtp-Source: ABdhPJyUxwH/vzT0E50dh72Kkj8ciWqYOggZ1xGCM9QsxPwKSU9nHB1sL57foxb5UQw8oSPsHmcmQIJH9KepBloh4wE= X-Received: by 2002:ab0:2ea1:: with SMTP id y1mr10295578uay.3.1627910972573; Mon, 02 Aug 2021 06:29:32 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Maged Michael Date: Mon, 2 Aug 2021 09:29:21 -0400 Message-ID: Subject: Re: [PATCH] libstdc++: Skip atomic instructions in _Sp_counted_base::_M_release when both counts are 1 To: Jonathan Wakely Cc: "libstdc++" , gcc-patches Content-Type: multipart/mixed; boundary="0000000000003f25b805c8938f8d" X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, KAM_NUMSUBJECT, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 02 Aug 2021 13:29:36 -0000 --0000000000003f25b805c8938f8d Content-Type: text/plain; charset="UTF-8" This is the right patch. The previous one is missing noexcept. Sorry. On Mon, Aug 2, 2021 at 9:23 AM Maged Michael wrote: > Please find attached an updated patch after incorporating Jonathan's > suggestions. > > Changes from the last patch include: > - Add a TSAN macro to bits/c++config. > - Use separate constexpr bool-s for the conditions for lock-freedom, > double-width and alignment. > - Move the code in the optimized path to a separate function > _M_release_double_width_cas. > > Thanks, > Maged > > > On Fri, Jul 16, 2021 at 11:55 AM Maged Michael > wrote: > >> Thank you, Jonathan, for the detailed comments! I'll update the patch >> accordingly. >> >> On Fri, Jul 16, 2021 at 9:55 AM Jonathan Wakely >> wrote: >> >>> On Thu, 17 Dec 2020 at 20:51, Maged Michael wrote: >>> > >>> > Please find a proposed patch for _Sp_counted_base::_M_release to skip >>> the >>> > two atomic instructions that decrement each of the use count and the >>> weak >>> > count when both are 1. I proposed the general idea in an earlier >>> thread ( >>> > https://gcc.gnu.org/pipermail/libstdc++/2020-December/051642.html) >>> and got >>> > useful feedback on a draft patch and responses to related questions >>> about >>> > multi-granular atomicity and alignment. This patch is based on that >>> > feedback. >>> > >>> > >>> > I added a check for thread sanitizer to use the current algorithm in >>> that >>> > case because TSAN does not support multi-granular atomicity. I'd like >>> to >>> > add a check of __has_feature(thread_sanitizer) for building using >>> LLVM. I >>> > found examples of __has_feature in libstdc++ >>> >>> There are no uses of __has_feature in libstdc++. We do use >>> __has_builtin (which GCC also supports) and Clang's __is_identifier >>> (which GCC doesn't support) to work around some weird semantics of >>> __has_builtin in older versions of Clang. >>> >>> >>> > but it doesn't seem to be >>> > recognized in shared_ptr_base.h. Any guidance on how to check >>> > __has_feature(thread_sanitizer) in this patch? >>> >>> I think we want to do something like this in include/bits/c++config >>> >>> #if __SANITIZE_THREAD__ >>> # define _GLIBCXX_TSAN 1 >>> #elif defined __has_feature >>> # if __has_feature(thread_sanitizer) >>> # define _GLIBCXX_TSAN 1 >>> # endif >>> #endif >>> >>> Then in bits/shared_ptr_base.h >>> >>> #if _GLIBCXX_TSAN >>> _M_release_orig(); >>> return; >>> #endif >>> >>> >>> >>> > GCC generates code for _M_release that is larger and more complex than >>> that >>> > generated by LLVM. I'd like to file a bug report about that. Jonathan, >>> >>> Is this the same issue as https://gcc.gnu.org/PR101406 ? >>> >>> Partly yes. Even when using __atomic_add_dispatch I noticed that clang >> generated less code than gcc. I see in the response to the issue that the >> new glibc is expected to optimize better. So maybe this will eliminate the >> issue. >> >> >>> > would you please create a bugzilla account for me ( >>> > https://gcc.gnu.org/bugzilla/) using my gmail address. Thank you. >>> >>> Done (sorry, I didn't notice the request in this mail until coming >>> back to it to review the patch properly). >>> >>> Thank you! >> >> >>> >>> >>> > >>> > >>> > Information about the patch: >>> > >>> > - Benefits of the patch: Save the cost of the last atomic decrements of >>> > each of the use count and the weak count in _Sp_counted_base. Atomic >>> > instructions are significantly slower than regular loads and stores >>> across >>> > major architectures. >>> > >>> > - How current code works: _M_release() atomically decrements the use >>> count, >>> > checks if it was 1, if so calls _M_dispose(), atomically decrements the >>> > weak count, checks if it was 1, and if so calls _M_destroy(). >>> > >>> > - How the proposed patch works: _M_release() loads both use count and >>> weak >>> > count together atomically (when properly aligned), checks if the value >>> is >>> > equal to the value of both counts equal to 1 (e.g., 0x100000001), and >>> if so >>> > calls _M_dispose() and _M_destroy(). Otherwise, it follows the original >>> > algorithm. >>> > >>> > - Why it works: When the current thread executing _M_release() finds >>> each >>> > of the counts is equal to 1, then (when _lock_policy is _S_atomic) no >>> other >>> > threads could possibly hold use or weak references to this control >>> block. >>> > That is, no other threads could possibly access the counts or the >>> protected >>> > object. >>> > >>> > - The proposed patch is intended to interact correctly with current >>> code >>> > (under certain conditions: _Lock_policy is _S_atomic, proper >>> alignment, and >>> > native lock-free support for atomic operations). That is, multiple >>> threads >>> > using different versions of the code with and without the patch >>> operating >>> > on the same objects should always interact correctly. The intent for >>> the >>> > patch is to be ABI compatible with the current implementation. >>> > >>> > - The proposed patch involves a performance trade-off between saving >>> the >>> > costs of two atomic instructions when the counts are both 1 vs adding >>> the >>> > cost of loading the combined counts and comparison with two ones (e.g., >>> > 0x100000001). >>> > >>> > - The patch has been in use (built using LLVM) in a large environment >>> for >>> > many months. The performance gains outweigh the losses (roughly 10 to >>> 1) >>> > across a large variety of workloads. >>> > >>> > >>> > I'd appreciate feedback on the patch and any suggestions for checking >>> > __has_feature(thread_sanitizer). >>> >>> N.B. gmail completely mangles patches unless you send them as >>> attachments. >>> >>> >>> > diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h >>> > b/libstdc++-v3/include/bits/shared_ptr_base.h >>> > >>> > index 368b2d7379a..a8fc944af5f 100644 >>> > >>> > --- a/libstdc++-v3/include/bits/shared_ptr_base.h >>> > >>> > +++ b/libstdc++-v3/include/bits/shared_ptr_base.h >>> > >>> > @@ -153,20 +153,78 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >>> > >>> > if (!_M_add_ref_lock_nothrow()) >>> > >>> > __throw_bad_weak_ptr(); >>> > >>> > } >>> > >>> > >>> > bool >>> > >>> > _M_add_ref_lock_nothrow() noexcept; >>> > >>> > >>> > void >>> > >>> > _M_release() noexcept >>> > >>> > { >>> > >>> > +#if __SANITIZE_THREAD__ >>> > >>> > + _M_release_orig(); >>> > >>> > + return; >>> > >>> > +#endif >>> > >>> > + if (!__atomic_always_lock_free(sizeof(long long), 0) || >>> >>> The line break should come before the logical operator, not after. >>> This makes it easier to see which operator it is, because it's at a >>> predictable position, not off on the right edge somewhere. >>> >>> i.e. >>> >>> if (!__atomic_always_lock_free(sizeof(long long), 0) >>> || !__atomic_always_lock_free(sizeof(_Atomic_word), 0) >>> || sizeof(long long) < (2 * sizeof(_Atomic_word)) >>> || sizeof(long long) > (sizeof(void*))) >>> >>> But I think I'd like to see this condition expressed differently >>> anyway, see below. >>> >>> > >>> > + !__atomic_always_lock_free(sizeof(_Atomic_word), 0) || >>> > >>> > + sizeof(long long) < (2 * sizeof(_Atomic_word)) || >>> >>> Shouldn't this be != instead of < ? >>> >>> On a big endian target where sizeof(long long) > sizeof(_Atomic_word) >>> loading two _Atomic_word objects will fill the high bits of the long >>> long, and so the (1LL + (1LL << (8 * 4))) calculation won't match what >>> got loaded into the long long. >>> >>> > >>> > + sizeof(long long) > (sizeof(void*))) >>> >>> This is checking the alignment, right? I think we can do so more >>> reliably, and should comment it. >>> >>> I think I'd like to see this condition defined as a number of >>> constexpr booleans, with comments. Maybe: >>> >>> constexpr bool __lock_free >>> = __atomic_always_lock_free(sizeof(long long), 0) >>> && __atomic_always_lock_free(sizeof(_Atomic_word), 0); >>> constexpr bool __double_word >>> = sizeof(long long) == 2 * sizeof(_Atomic_word); >>> // The ref-count members follow the vptr, so are aligned to >>> alignof(void*). >>> constexpr bool __aligned = alignof(long long) <= alignof(void*); >>> >>> if _GLIBCXX17_CONSTEXPR >>> (__lock_free && __double_word && __aligned) >>> { >>> _M_release_double_width_cas(); >>> return; >>> } >>> else >>> { >>> // ... original body of _M_release(); >>> } >>> >>> > + { >>> > >>> > + _M_release_orig(); >>> > >>> > + return; >>> > >>> > + } >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count); >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); >>> > >>> > + if (__atomic_load_n((long long*)(&_M_use_count), >>> __ATOMIC_ACQUIRE) >>> > >>> > + == (1LL + (1LL << (8 * sizeof(_Atomic_word))))) >>> >>> This should use __CHAR_BIT__ instead of 8. >>> >>> >>> > >>> > + { >>> > >>> > + // Both counts are 1, so there are no weak references and >>> > >>> > + // we are releasing the last strong reference. No other >>> > >>> > + // threads can observe the effects of this _M_release() >>> > >>> > + // call (e.g. calling use_count()) without a data race. >>> > >>> > + *(long long*)(&_M_use_count) = 0; >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count); >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); >>> > >>> > + _M_dispose(); >>> > >>> > + _M_destroy(); >>> > >>> > + } >>> > >>> > + else >>> > >>> > + { >>> > >>> > + if ((__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == >>> 1)) >>> > >>> > + { >>> > >>> > + _M_release_last_use(); >>> > >>> > + } >>> > >>> > + } >>> > >>> > + } >>> > >>> > + >>> > >>> > + void >>> > >>> > + __attribute__ ((noinline)) >>> > >>> > + _M_release_last_use() noexcept >>> > >>> > + { >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count); >>> > >>> > + _M_dispose(); >>> > >>> > + if (_Mutex_base<_Lp>::_S_need_barriers) >>> > >>> > + { >>> > >>> > + __atomic_thread_fence (__ATOMIC_ACQ_REL); >>> > >>> > + } >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); >>> > >>> > + if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, >>> > >>> > + -1) == 1) >>> > >>> > + { >>> > >>> > + _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); >>> > >>> > + _M_destroy(); >>> > >>> > + } >>> > >>> > + } >>> > >>> > + >>> > >>> > + void >>> > >>> > + _M_release_orig() noexcept >>> > >>> > + { >>> > >>> > // Be race-detector-friendly. For more info see >>> bits/c++config. >>> > >>> > _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count); >>> > >>> > if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) >>> == 1) >>> > >>> > { >>> > >>> > _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count); >>> > >>> > _M_dispose(); >>> > >>> > // There must be a memory barrier between dispose() and >>> > destroy() >>> > >>> > // to ensure that the effects of dispose() are observed in >>> the >>> > >>> > // thread that runs destroy(). >>> > >>> > // See >>> http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html >>> > >>> > @@ -279,20 +337,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >>> > >>> > _Sp_counted_base<_S_single>::_M_release() noexcept >>> > >>> > { >>> > >>> > if (--_M_use_count == 0) >>> > >>> > { >>> > >>> > _M_dispose(); >>> > >>> > if (--_M_weak_count == 0) >>> > >>> > _M_destroy(); >>> > >>> > } >>> > >>> > } >>> > >>> > >>> > + template<> >>> > >>> > + inline void >>> > >>> > + _Sp_counted_base<_S_mutex>::_M_release() noexcept >>> > >>> > + { >>> > >>> > + _M_release_orig(); >>> > >>> > + } >>> > >>> > + >>> > >>> > template<> >>> > >>> > inline void >>> > >>> > _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept >>> > >>> > { ++_M_weak_count; } >>> > >>> > >>> > template<> >>> > >>> > inline void >>> > >>> > _Sp_counted_base<_S_single>::_M_weak_release() noexcept >>> > >>> > { >>> > >>> > if (--_M_weak_count == 0) >>> >> --0000000000003f25b805c8938f8d Content-Type: text/plain; charset="US-ASCII"; name="patch.txt" Content-Disposition: attachment; filename="patch.txt" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_kruo553f0 ZGlmZiAtLWdpdCBhL2xpYnN0ZGMrKy12My9pbmNsdWRlL2JpdHMvYysrY29uZmlnIGIvbGlic3Rk YysrLXYzL2luY2x1ZGUvYml0cy9jKytjb25maWcKaW5kZXggNjlhY2UzODZkZDcuLjU0M2ZhYzI2 OGI0IDEwMDY0NAotLS0gYS9saWJzdGRjKystdjMvaW5jbHVkZS9iaXRzL2MrK2NvbmZpZworKysg Yi9saWJzdGRjKystdjMvaW5jbHVkZS9iaXRzL2MrK2NvbmZpZwpAQCAtMTI2LDIwICsxMjYsMjkg QEAKICMgZGVmaW5lIF9HTElCQ1hYX0FCSV9UQUdfQ1hYMTEgX19hdHRyaWJ1dGUgKChfX2FiaV90 YWdfXyAoImN4eDExIikpKQogI2VuZGlmCiAKIC8vIE1hY3JvIHRvIHdhcm4gYWJvdXQgdW51c2Vk IHJlc3VsdHMuCiAjaWYgX19jcGx1c3BsdXMgPj0gMjAxNzAzTAogIyBkZWZpbmUgX0dMSUJDWFhf Tk9ESVNDQVJEIFtbX19ub2Rpc2NhcmRfX11dCiAjZWxzZQogIyBkZWZpbmUgX0dMSUJDWFhfTk9E SVNDQVJECiAjZW5kaWYKIAorLy8gTWFjcm8gZm9yIFRTQU4uCisjaWYgX19TQU5JVElaRV9USFJF QURfXworIyAgZGVmaW5lIF9HTElCQ1hYX1RTQU4gMQorI2VsaWYgZGVmaW5lZCBfX2hhc19mZWF0 dXJlCisjIGlmIF9faGFzX2ZlYXR1cmUodGhyZWFkX3Nhbml0aXplcikKKyMgIGRlZmluZSBfR0xJ QkNYWF9UU0FOIDEKKyMgZW5kaWYKKyNlbmRpZgorCiAKIAogI2lmIF9fY3BsdXNwbHVzCiAKIC8v IE1hY3JvIGZvciBjb25zdGV4cHIsIHRvIHN1cHBvcnQgaW4gbWl4ZWQgMDMvMHggbW9kZS4KICNp Zm5kZWYgX0dMSUJDWFhfQ09OU1RFWFBSCiAjIGlmIF9fY3BsdXNwbHVzID49IDIwMTEwM0wKICMg IGRlZmluZSBfR0xJQkNYWF9DT05TVEVYUFIgY29uc3RleHByCiAjICBkZWZpbmUgX0dMSUJDWFhf VVNFX0NPTlNURVhQUiBjb25zdGV4cHIKICMgZWxzZQpkaWZmIC0tZ2l0IGEvbGlic3RkYysrLXYz L2luY2x1ZGUvYml0cy9zaGFyZWRfcHRyX2Jhc2UuaCBiL2xpYnN0ZGMrKy12My9pbmNsdWRlL2Jp dHMvc2hhcmVkX3B0cl9iYXNlLmgKaW5kZXggNWJlOTM1ZDE3NGQuLjgzNGNhMTNiZGM2IDEwMDY0 NAotLS0gYS9saWJzdGRjKystdjMvaW5jbHVkZS9iaXRzL3NoYXJlZF9wdHJfYmFzZS5oCisrKyBi L2xpYnN0ZGMrKy12My9pbmNsdWRlL2JpdHMvc2hhcmVkX3B0cl9iYXNlLmgKQEAgLTE1MywyMCAr MTUzLDkzIEBAIF9HTElCQ1hYX0JFR0lOX05BTUVTUEFDRV9WRVJTSU9OCiAJaWYgKCFfTV9hZGRf cmVmX2xvY2tfbm90aHJvdygpKQogCSAgX190aHJvd19iYWRfd2Vha19wdHIoKTsKICAgICAgIH0K IAogICAgICAgYm9vbAogICAgICAgX01fYWRkX3JlZl9sb2NrX25vdGhyb3coKSBub2V4Y2VwdDsK IAogICAgICAgdm9pZAogICAgICAgX01fcmVsZWFzZSgpIG5vZXhjZXB0CiAgICAgICB7CisjaWYg X0dMSUJDWFhfVFNBTgorICAgICAgICBfTV9yZWxlYXNlX29yaWcoKTsKKyAgICAgICAgcmV0dXJu OworI2VuZGlmCisgICAgICAgIGNvbnN0ZXhwciBib29sIF9fbG9ja19mcmVlCisgICAgICAgICAg PSBfX2F0b21pY19hbHdheXNfbG9ja19mcmVlKHNpemVvZihsb25nIGxvbmcpLCAwKQorICAgICAg ICAgICYmIF9fYXRvbWljX2Fsd2F5c19sb2NrX2ZyZWUoc2l6ZW9mKF9BdG9taWNfd29yZCksIDAp OworICAgICAgICBjb25zdGV4cHIgYm9vbCBfX2RvdWJsZV93b3JkCisgICAgICAgICAgPSBzaXpl b2YobG9uZyBsb25nKSA9PSAyICogc2l6ZW9mKF9BdG9taWNfd29yZCk7CisgICAgICAgIC8vIFRo ZSByZWYtY291bnQgbWVtYmVycyBmb2xsb3cgdGhlIHZwdHIsIHNvIGFyZSBhbGlnbmVkIHRvCisg ICAgICAgIC8vIGFsaWdub2Yodm9pZCopLgorICAgICAgICBjb25zdGV4cHIgYm9vbCBfX2FsaWdu ZWQgPSBhbGlnbm9mKGxvbmcgbG9uZykgPD0gYWxpZ25vZih2b2lkKik7CisgICAgICAgIGlmIF9H TElCQ1hYMTdfQ09OU1RFWFBSCisgICAgICAgICAgKF9fbG9ja19mcmVlICYmIF9fZG91YmxlX3dv cmQgJiYgX19hbGlnbmVkKQorICAgICAgICAgIHsKKyAgICAgICAgICAgIF9NX3JlbGVhc2VfZG91 YmxlX3dpZHRoX2NhcygpOworICAgICAgICAgICAgcmV0dXJuOworICAgICAgICAgIH0KKyAgICAg ICAgZWxzZQorICAgICAgICAgIHsKKyAgICAgICAgICAgIF9NX3JlbGVhc2Vfb3JpZygpOworICAg ICAgICAgIH0KKyAgICAgIH0KKworICAgICAgdm9pZAorICAgICAgX01fcmVsZWFzZV9kb3VibGVf d2lkdGhfY2FzKCkgbm9leGNlcHQKKyAgICAgIHsKKyAgICAgICAgX0dMSUJDWFhfU1lOQ0hST05J WkFUSU9OX0hBUFBFTlNfQkVGT1JFKCZfTV91c2VfY291bnQpOworICAgICAgICBfR0xJQkNYWF9T WU5DSFJPTklaQVRJT05fSEFQUEVOU19CRUZPUkUoJl9NX3dlYWtfY291bnQpOworICAgICAgICBp ZiAoX19hdG9taWNfbG9hZF9uKChsb25nIGxvbmcqKSgmX01fdXNlX2NvdW50KSwgX19BVE9NSUNf QUNRVUlSRSkKKyAgICAgICAgICAgID09ICgxTEwgKyAoMUxMIDw8IChfX0NIQVJfQklUX18gKiBz aXplb2YoX0F0b21pY193b3JkKSkpKSkKKyAgICAgICAgICB7CisgICAgICAgICAgICAvLyBCb3Ro IGNvdW50cyBhcmUgMSwgc28gdGhlcmUgYXJlIG5vIHdlYWsgcmVmZXJlbmNlcyBhbmQKKyAgICAg ICAgICAgIC8vIHdlIGFyZSByZWxlYXNpbmcgdGhlIGxhc3Qgc3Ryb25nIHJlZmVyZW5jZS4gTm8g b3RoZXIKKyAgICAgICAgICAgIC8vIHRocmVhZHMgY2FuIG9ic2VydmUgdGhlIGVmZmVjdHMgb2Yg dGhpcyBfTV9yZWxlYXNlKCkKKyAgICAgICAgICAgIC8vIGNhbGwgKGUuZy4gY2FsbGluZyB1c2Vf Y291bnQoKSkgd2l0aG91dCBhIGRhdGEgcmFjZS4KKyAgICAgICAgICAgICoobG9uZyBsb25nKiko Jl9NX3VzZV9jb3VudCkgPSAwOworICAgICAgICAgICAgX0dMSUJDWFhfU1lOQ0hST05JWkFUSU9O X0hBUFBFTlNfQUZURVIoJl9NX3VzZV9jb3VudCk7CisgICAgICAgICAgICBfR0xJQkNYWF9TWU5D SFJPTklaQVRJT05fSEFQUEVOU19BRlRFUigmX01fd2Vha19jb3VudCk7CisgICAgICAgICAgICBf TV9kaXNwb3NlKCk7CisgICAgICAgICAgICBfTV9kZXN0cm95KCk7CisgICAgICAgICAgfQorICAg ICAgICBlbHNlCisgICAgICAgICAgeworICAgICAgICAgICAgaWYgKChfX2dudV9jeHg6Ol9fZXhj aGFuZ2VfYW5kX2FkZCgmX01fdXNlX2NvdW50LCAtMSkgPT0gMSkpCisgICAgICAgICAgICAgIHsK KyAgICAgICAgICAgICAgICBfTV9yZWxlYXNlX2xhc3RfdXNlKCk7CisgICAgICAgICAgICAgIH0K KyAgICAgICAgICB9CisgICAgICB9CisKKyAgICAgIHZvaWQKKyAgICAgIF9fYXR0cmlidXRlX18g KChub2lubGluZSkpCisgICAgICBfTV9yZWxlYXNlX2xhc3RfdXNlKCkgbm9leGNlcHQKKyAgICAg IHsKKyAgICAgICAgX0dMSUJDWFhfU1lOQ0hST05JWkFUSU9OX0hBUFBFTlNfQUZURVIoJl9NX3Vz ZV9jb3VudCk7CisgICAgICAgIF9NX2Rpc3Bvc2UoKTsKKyAgICAgICAgaWYgKF9NdXRleF9iYXNl PF9McD46Ol9TX25lZWRfYmFycmllcnMpCisgICAgICAgICAgeworICAgICAgICAgICAgX19hdG9t aWNfdGhyZWFkX2ZlbmNlIChfX0FUT01JQ19BQ1FfUkVMKTsKKyAgICAgICAgICB9CisgICAgICAg IF9HTElCQ1hYX1NZTkNIUk9OSVpBVElPTl9IQVBQRU5TX0JFRk9SRSgmX01fd2Vha19jb3VudCk7 CisgICAgICAgIGlmIChfX2dudV9jeHg6Ol9fZXhjaGFuZ2VfYW5kX2FkZF9kaXNwYXRjaCgmX01f d2Vha19jb3VudCwKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIC0xKSA9PSAxKQorICAgICAgICAgIHsKKyAgICAgICAgICAgIF9HTElCQ1hYX1NZTkNI Uk9OSVpBVElPTl9IQVBQRU5TX0FGVEVSKCZfTV93ZWFrX2NvdW50KTsKKyAgICAgICAgICAgIF9N X2Rlc3Ryb3koKTsKKyAgICAgICAgICB9CisgICAgICB9CisKKyAgICAgIHZvaWQKKyAgICAgIF9N X3JlbGVhc2Vfb3JpZygpIG5vZXhjZXB0CisgICAgICB7CiAgICAgICAgIC8vIEJlIHJhY2UtZGV0 ZWN0b3ItZnJpZW5kbHkuICBGb3IgbW9yZSBpbmZvIHNlZSBiaXRzL2MrK2NvbmZpZy4KICAgICAg ICAgX0dMSUJDWFhfU1lOQ0hST05JWkFUSU9OX0hBUFBFTlNfQkVGT1JFKCZfTV91c2VfY291bnQp OwogCWlmIChfX2dudV9jeHg6Ol9fZXhjaGFuZ2VfYW5kX2FkZF9kaXNwYXRjaCgmX01fdXNlX2Nv dW50LCAtMSkgPT0gMSkKIAkgIHsKICAgICAgICAgICAgIF9HTElCQ1hYX1NZTkNIUk9OSVpBVElP Tl9IQVBQRU5TX0FGVEVSKCZfTV91c2VfY291bnQpOwogCSAgICBfTV9kaXNwb3NlKCk7CiAJICAg IC8vIFRoZXJlIG11c3QgYmUgYSBtZW1vcnkgYmFycmllciBiZXR3ZWVuIGRpc3Bvc2UoKSBhbmQg ZGVzdHJveSgpCiAJICAgIC8vIHRvIGVuc3VyZSB0aGF0IHRoZSBlZmZlY3RzIG9mIGRpc3Bvc2Uo KSBhcmUgb2JzZXJ2ZWQgaW4gdGhlCiAJICAgIC8vIHRocmVhZCB0aGF0IHJ1bnMgZGVzdHJveSgp LgogCSAgICAvLyBTZWUgaHR0cDovL2djYy5nbnUub3JnL21sL2xpYnN0ZGMrKy8yMDA1LTExL21z ZzAwMTM2Lmh0bWwKQEAgLTI3OSwyMCArMzUyLDI3IEBAIF9HTElCQ1hYX0JFR0lOX05BTUVTUEFD RV9WRVJTSU9OCiAgICAgX1NwX2NvdW50ZWRfYmFzZTxfU19zaW5nbGU+OjpfTV9yZWxlYXNlKCkg bm9leGNlcHQKICAgICB7CiAgICAgICBpZiAoLS1fTV91c2VfY291bnQgPT0gMCkKICAgICAgICAg ewogICAgICAgICAgIF9NX2Rpc3Bvc2UoKTsKICAgICAgICAgICBpZiAoLS1fTV93ZWFrX2NvdW50 ID09IDApCiAgICAgICAgICAgICBfTV9kZXN0cm95KCk7CiAgICAgICAgIH0KICAgICB9CiAKKyAg dGVtcGxhdGU8PgorICAgIGlubGluZSB2b2lkCisgICAgX1NwX2NvdW50ZWRfYmFzZTxfU19tdXRl eD46Ol9NX3JlbGVhc2UoKSBub2V4Y2VwdAorICAgIHsKKyAgICAgIF9NX3JlbGVhc2Vfb3JpZygp OworICAgIH0KKwogICB0ZW1wbGF0ZTw+CiAgICAgaW5saW5lIHZvaWQKICAgICBfU3BfY291bnRl ZF9iYXNlPF9TX3NpbmdsZT46Ol9NX3dlYWtfYWRkX3JlZigpIG5vZXhjZXB0CiAgICAgeyArK19N X3dlYWtfY291bnQ7IH0KIAogICB0ZW1wbGF0ZTw+CiAgICAgaW5saW5lIHZvaWQKICAgICBfU3Bf Y291bnRlZF9iYXNlPF9TX3NpbmdsZT46Ol9NX3dlYWtfcmVsZWFzZSgpIG5vZXhjZXB0CiAgICAg ewogICAgICAgaWYgKC0tX01fd2Vha19jb3VudCA9PSAwKQ== --0000000000003f25b805c8938f8d--