From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-wr1-f65.google.com ([209.85.221.65]:37432 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726277AbeJWUnX (ORCPT ); Tue, 23 Oct 2018 16:43:23 -0400 Received: by mail-wr1-f65.google.com with SMTP id g9-v6so1464587wrq.4 for ; Tue, 23 Oct 2018 05:20:06 -0700 (PDT) Subject: Re: [PATCH 1/8] dma-buf: remove shared fence staging in reservation object From: =?UTF-8?Q?Christian_K=c3=b6nig?= To: amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, "linux-media@vger.kernel.org" , "linaro-mm-sig@lists.linaro.org" , Huang Rui , "Daenzer, Michel" Cc: Daniel Vetter , Chris Wilson , "Zhang, Jerry" References: <20181004131250.2373-1-christian.koenig@amd.com> <30ba1fc8-58d5-1c75-406e-d10e68ec4b18@gmail.com> Message-ID: <42ee3d74-9dac-6573-448c-c70ea28cb9ff@gmail.com> Date: Tue, 23 Oct 2018 14:20:02 +0200 MIME-Version: 1.0 In-Reply-To: <30ba1fc8-58d5-1c75-406e-d10e68ec4b18@gmail.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Sender: linux-media-owner@vger.kernel.org List-ID: Ping once more! Adding a few more AMD people. Any comments on this? Thanks, Christian. Am 12.10.18 um 10:22 schrieb Christian König: > Ping! Adding a few people directly and more mailing lists. > > Can I get an acked-by/rb for this? It's only a cleanup and not much > functional change. > > Regards, > Christian. > > Am 04.10.2018 um 15:12 schrieb Christian König: >> No need for that any more. Just replace the list when there isn't enough >> room any more for the additional fence. >> >> Signed-off-by: Christian König >> --- >>   drivers/dma-buf/reservation.c | 178 >> ++++++++++++++---------------------------- >>   include/linux/reservation.h   |   4 - >>   2 files changed, 58 insertions(+), 124 deletions(-) >> >> diff --git a/drivers/dma-buf/reservation.c >> b/drivers/dma-buf/reservation.c >> index 6c95f61a32e7..5825fc336a13 100644 >> --- a/drivers/dma-buf/reservation.c >> +++ b/drivers/dma-buf/reservation.c >> @@ -68,105 +68,23 @@ EXPORT_SYMBOL(reservation_seqcount_string); >>    */ >>   int reservation_object_reserve_shared(struct reservation_object *obj) >>   { >> -    struct reservation_object_list *fobj, *old; >> -    u32 max; >> +    struct reservation_object_list *old, *new; >> +    unsigned int i, j, k, max; >>         old = reservation_object_get_list(obj); >>         if (old && old->shared_max) { >> -        if (old->shared_count < old->shared_max) { >> -            /* perform an in-place update */ >> -            kfree(obj->staged); >> -            obj->staged = NULL; >> +        if (old->shared_count < old->shared_max) >>               return 0; >> -        } else >> +        else >>               max = old->shared_max * 2; >> -    } else >> -        max = 4; >> - >> -    /* >> -     * resize obj->staged or allocate if it doesn't exist, >> -     * noop if already correct size >> -     */ >> -    fobj = krealloc(obj->staged, offsetof(typeof(*fobj), shared[max]), >> -            GFP_KERNEL); >> -    if (!fobj) >> -        return -ENOMEM; >> - >> -    obj->staged = fobj; >> -    fobj->shared_max = max; >> -    return 0; >> -} >> -EXPORT_SYMBOL(reservation_object_reserve_shared); >> - >> -static void >> -reservation_object_add_shared_inplace(struct reservation_object *obj, >> -                      struct reservation_object_list *fobj, >> -                      struct dma_fence *fence) >> -{ >> -    struct dma_fence *signaled = NULL; >> -    u32 i, signaled_idx; >> - >> -    dma_fence_get(fence); >> - >> -    preempt_disable(); >> -    write_seqcount_begin(&obj->seq); >> - >> -    for (i = 0; i < fobj->shared_count; ++i) { >> -        struct dma_fence *old_fence; >> - >> -        old_fence = rcu_dereference_protected(fobj->shared[i], >> -                        reservation_object_held(obj)); >> - >> -        if (old_fence->context == fence->context) { >> -            /* memory barrier is added by write_seqcount_begin */ >> -            RCU_INIT_POINTER(fobj->shared[i], fence); >> -            write_seqcount_end(&obj->seq); >> -            preempt_enable(); >> - >> -            dma_fence_put(old_fence); >> -            return; >> -        } >> - >> -        if (!signaled && dma_fence_is_signaled(old_fence)) { >> -            signaled = old_fence; >> -            signaled_idx = i; >> -        } >> -    } >> - >> -    /* >> -     * memory barrier is added by write_seqcount_begin, >> -     * fobj->shared_count is protected by this lock too >> -     */ >> -    if (signaled) { >> -        RCU_INIT_POINTER(fobj->shared[signaled_idx], fence); >>       } else { >> -        BUG_ON(fobj->shared_count >= fobj->shared_max); >> - RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence); >> -        fobj->shared_count++; >> +        max = 4; >>       } >>   -    write_seqcount_end(&obj->seq); >> -    preempt_enable(); >> - >> -    dma_fence_put(signaled); >> -} >> - >> -static void >> -reservation_object_add_shared_replace(struct reservation_object *obj, >> -                      struct reservation_object_list *old, >> -                      struct reservation_object_list *fobj, >> -                      struct dma_fence *fence) >> -{ >> -    unsigned i, j, k; >> - >> -    dma_fence_get(fence); >> - >> -    if (!old) { >> -        RCU_INIT_POINTER(fobj->shared[0], fence); >> -        fobj->shared_count = 1; >> -        goto done; >> -    } >> +    new = kmalloc(offsetof(typeof(*new), shared[max]), GFP_KERNEL); >> +    if (!new) >> +        return -ENOMEM; >>         /* >>        * no need to bump fence refcounts, rcu_read access >> @@ -174,46 +92,45 @@ reservation_object_add_shared_replace(struct >> reservation_object *obj, >>        * references from the old struct are carried over to >>        * the new. >>        */ >> -    for (i = 0, j = 0, k = fobj->shared_max; i < old->shared_count; >> ++i) { >> -        struct dma_fence *check; >> +    for (i = 0, j = 0, k = max; i < (old ? old->shared_count : 0); >> ++i) { >> +        struct dma_fence *fence; >>   -        check = rcu_dereference_protected(old->shared[i], >> -                        reservation_object_held(obj)); >> - >> -        if (check->context == fence->context || >> -            dma_fence_is_signaled(check)) >> -            RCU_INIT_POINTER(fobj->shared[--k], check); >> +        fence = rcu_dereference_protected(old->shared[i], >> +                          reservation_object_held(obj)); >> +        if (dma_fence_is_signaled(fence)) >> +            RCU_INIT_POINTER(new->shared[--k], fence); >>           else >> -            RCU_INIT_POINTER(fobj->shared[j++], check); >> +            RCU_INIT_POINTER(new->shared[j++], fence); >>       } >> -    fobj->shared_count = j; >> -    RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence); >> -    fobj->shared_count++; >> +    new->shared_count = j; >> +    new->shared_max = max; >>   -done: >>       preempt_disable(); >>       write_seqcount_begin(&obj->seq); >>       /* >>        * RCU_INIT_POINTER can be used here, >>        * seqcount provides the necessary barriers >>        */ >> -    RCU_INIT_POINTER(obj->fence, fobj); >> +    RCU_INIT_POINTER(obj->fence, new); >>       write_seqcount_end(&obj->seq); >>       preempt_enable(); >>         if (!old) >> -        return; >> +        return 0; >>         /* Drop the references to the signaled fences */ >> -    for (i = k; i < fobj->shared_max; ++i) { >> -        struct dma_fence *f; >> +    for (i = k; i < new->shared_max; ++i) { >> +        struct dma_fence *fence; >>   -        f = rcu_dereference_protected(fobj->shared[i], >> -                          reservation_object_held(obj)); >> -        dma_fence_put(f); >> +        fence = rcu_dereference_protected(new->shared[i], >> +                          reservation_object_held(obj)); >> +        dma_fence_put(fence); >>       } >>       kfree_rcu(old, rcu); >> + >> +    return 0; >>   } >> +EXPORT_SYMBOL(reservation_object_reserve_shared); >>     /** >>    * reservation_object_add_shared_fence - Add a fence to a shared slot >> @@ -226,15 +143,39 @@ reservation_object_add_shared_replace(struct >> reservation_object *obj, >>   void reservation_object_add_shared_fence(struct reservation_object >> *obj, >>                        struct dma_fence *fence) >>   { >> -    struct reservation_object_list *old, *fobj = obj->staged; >> +    struct reservation_object_list *fobj; >> +    unsigned int i; >>   -    old = reservation_object_get_list(obj); >> -    obj->staged = NULL; >> +    dma_fence_get(fence); >> + >> +    fobj = reservation_object_get_list(obj); >>   -    if (!fobj) >> -        reservation_object_add_shared_inplace(obj, old, fence); >> -    else >> -        reservation_object_add_shared_replace(obj, old, fobj, fence); >> +    preempt_disable(); >> +    write_seqcount_begin(&obj->seq); >> + >> +    for (i = 0; i < fobj->shared_count; ++i) { >> +        struct dma_fence *old_fence; >> + >> +        old_fence = rcu_dereference_protected(fobj->shared[i], >> +                              reservation_object_held(obj)); >> +        if (old_fence->context == fence->context || >> +            dma_fence_is_signaled(old_fence)) { >> +            dma_fence_put(old_fence); >> +            goto replace; >> +        } >> +    } >> + >> +    BUG_ON(fobj->shared_count >= fobj->shared_max); >> +    fobj->shared_count++; >> + >> +replace: >> +    /* >> +     * memory barrier is added by write_seqcount_begin, >> +     * fobj->shared_count is protected by this lock too >> +     */ >> +    RCU_INIT_POINTER(fobj->shared[i], fence); >> +    write_seqcount_end(&obj->seq); >> +    preempt_enable(); >>   } >>   EXPORT_SYMBOL(reservation_object_add_shared_fence); >>   @@ -343,9 +284,6 @@ int reservation_object_copy_fences(struct >> reservation_object *dst, >>       new = dma_fence_get_rcu_safe(&src->fence_excl); >>       rcu_read_unlock(); >>   -    kfree(dst->staged); >> -    dst->staged = NULL; >> - >>       src_list = reservation_object_get_list(dst); >>       old = reservation_object_get_excl(dst); >>   diff --git a/include/linux/reservation.h b/include/linux/reservation.h >> index 02166e815afb..54cf6773a14c 100644 >> --- a/include/linux/reservation.h >> +++ b/include/linux/reservation.h >> @@ -68,7 +68,6 @@ struct reservation_object_list { >>    * @seq: sequence count for managing RCU read-side synchronization >>    * @fence_excl: the exclusive fence, if there is one currently >>    * @fence: list of current shared fences >> - * @staged: staged copy of shared fences for RCU updates >>    */ >>   struct reservation_object { >>       struct ww_mutex lock; >> @@ -76,7 +75,6 @@ struct reservation_object { >>         struct dma_fence __rcu *fence_excl; >>       struct reservation_object_list __rcu *fence; >> -    struct reservation_object_list *staged; >>   }; >>     #define reservation_object_held(obj) >> lockdep_is_held(&(obj)->lock.base) >> @@ -95,7 +93,6 @@ reservation_object_init(struct reservation_object >> *obj) >>       __seqcount_init(&obj->seq, reservation_seqcount_string, >> &reservation_seqcount_class); >>       RCU_INIT_POINTER(obj->fence, NULL); >>       RCU_INIT_POINTER(obj->fence_excl, NULL); >> -    obj->staged = NULL; >>   } >>     /** >> @@ -124,7 +121,6 @@ reservation_object_fini(struct reservation_object >> *obj) >>             kfree(fobj); >>       } >> -    kfree(obj->staged); >>         ww_mutex_destroy(&obj->lock); >>   } > From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?Q?Christian_K=c3=b6nig?= Subject: Re: [PATCH 1/8] dma-buf: remove shared fence staging in reservation object Date: Tue, 23 Oct 2018 14:20:02 +0200 Message-ID: <42ee3d74-9dac-6573-448c-c70ea28cb9ff@gmail.com> References: <20181004131250.2373-1-christian.koenig@amd.com> <30ba1fc8-58d5-1c75-406e-d10e68ec4b18@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <30ba1fc8-58d5-1c75-406e-d10e68ec4b18-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: amd-gfx-bounces-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org Sender: "amd-gfx" To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org, "linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" , "linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw@public.gmane.org" , Huang Rui , "Daenzer, Michel" Cc: "Zhang, Jerry" , Daniel Vetter , Chris Wilson List-Id: dri-devel@lists.freedesktop.org UGluZyBvbmNlIG1vcmUhIEFkZGluZyBhIGZldyBtb3JlIEFNRCBwZW9wbGUuCgpBbnkgY29tbWVu dHMgb24gdGhpcz8KClRoYW5rcywKQ2hyaXN0aWFuLgoKQW0gMTIuMTAuMTggdW0gMTA6MjIgc2No cmllYiBDaHJpc3RpYW4gS8O2bmlnOgo+IFBpbmchIEFkZGluZyBhIGZldyBwZW9wbGUgZGlyZWN0 bHkgYW5kIG1vcmUgbWFpbGluZyBsaXN0cy4KPgo+IENhbiBJIGdldCBhbiBhY2tlZC1ieS9yYiBm b3IgdGhpcz8gSXQncyBvbmx5IGEgY2xlYW51cCBhbmQgbm90IG11Y2ggCj4gZnVuY3Rpb25hbCBj aGFuZ2UuCj4KPiBSZWdhcmRzLAo+IENocmlzdGlhbi4KPgo+IEFtIDA0LjEwLjIwMTggdW0gMTU6 MTIgc2NocmllYiBDaHJpc3RpYW4gS8O2bmlnOgo+PiBObyBuZWVkIGZvciB0aGF0IGFueSBtb3Jl LiBKdXN0IHJlcGxhY2UgdGhlIGxpc3Qgd2hlbiB0aGVyZSBpc24ndCBlbm91Z2gKPj4gcm9vbSBh bnkgbW9yZSBmb3IgdGhlIGFkZGl0aW9uYWwgZmVuY2UuCj4+Cj4+IFNpZ25lZC1vZmYtYnk6IENo cmlzdGlhbiBLw7ZuaWcgPGNocmlzdGlhbi5rb2VuaWdAYW1kLmNvbT4KPj4gLS0tCj4+IMKgIGRy aXZlcnMvZG1hLWJ1Zi9yZXNlcnZhdGlvbi5jIHwgMTc4IAo+PiArKysrKysrKysrKysrKy0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPj4gwqAgaW5jbHVkZS9saW51eC9yZXNlcnZhdGlvbi5o wqDCoCB8wqDCoCA0IC0KPj4gwqAgMiBmaWxlcyBjaGFuZ2VkLCA1OCBpbnNlcnRpb25zKCspLCAx MjQgZGVsZXRpb25zKC0pCj4+Cj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS1idWYvcmVzZXJ2 YXRpb24uYyAKPj4gYi9kcml2ZXJzL2RtYS1idWYvcmVzZXJ2YXRpb24uYwo+PiBpbmRleCA2Yzk1 ZjYxYTMyZTcuLjU4MjVmYzMzNmExMyAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9kbWEtYnVmL3Jl c2VydmF0aW9uLmMKPj4gKysrIGIvZHJpdmVycy9kbWEtYnVmL3Jlc2VydmF0aW9uLmMKPj4gQEAg LTY4LDEwNSArNjgsMjMgQEAgRVhQT1JUX1NZTUJPTChyZXNlcnZhdGlvbl9zZXFjb3VudF9zdHJp bmcpOwo+PiDCoMKgICovCj4+IMKgIGludCByZXNlcnZhdGlvbl9vYmplY3RfcmVzZXJ2ZV9zaGFy ZWQoc3RydWN0IHJlc2VydmF0aW9uX29iamVjdCAqb2JqKQo+PiDCoCB7Cj4+IC3CoMKgwqAgc3Ry dWN0IHJlc2VydmF0aW9uX29iamVjdF9saXN0ICpmb2JqLCAqb2xkOwo+PiAtwqDCoMKgIHUzMiBt YXg7Cj4+ICvCoMKgwqAgc3RydWN0IHJlc2VydmF0aW9uX29iamVjdF9saXN0ICpvbGQsICpuZXc7 Cj4+ICvCoMKgwqAgdW5zaWduZWQgaW50IGksIGosIGssIG1heDsKPj4gwqAgwqDCoMKgwqDCoCBv bGQgPSByZXNlcnZhdGlvbl9vYmplY3RfZ2V0X2xpc3Qob2JqKTsKPj4gwqAgwqDCoMKgwqDCoCBp ZiAob2xkICYmIG9sZC0+c2hhcmVkX21heCkgewo+PiAtwqDCoMKgwqDCoMKgwqAgaWYgKG9sZC0+ c2hhcmVkX2NvdW50IDwgb2xkLT5zaGFyZWRfbWF4KSB7Cj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDC oMKgIC8qIHBlcmZvcm0gYW4gaW4tcGxhY2UgdXBkYXRlICovCj4+IC3CoMKgwqDCoMKgwqDCoMKg wqDCoMKgIGtmcmVlKG9iai0+c3RhZ2VkKTsKPj4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgb2Jq LT5zdGFnZWQgPSBOVUxMOwo+PiArwqDCoMKgwqDCoMKgwqAgaWYgKG9sZC0+c2hhcmVkX2NvdW50 IDwgb2xkLT5zaGFyZWRfbWF4KQo+PiDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCByZXR1cm4g MDsKPj4gLcKgwqDCoMKgwqDCoMKgIH0gZWxzZQo+PiArwqDCoMKgwqDCoMKgwqAgZWxzZQo+PiDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBtYXggPSBvbGQtPnNoYXJlZF9tYXggKiAyOwo+PiAt wqDCoMKgIH0gZWxzZQo+PiAtwqDCoMKgwqDCoMKgwqAgbWF4ID0gNDsKPj4gLQo+PiAtwqDCoMKg IC8qCj4+IC3CoMKgwqDCoCAqIHJlc2l6ZSBvYmotPnN0YWdlZCBvciBhbGxvY2F0ZSBpZiBpdCBk b2Vzbid0IGV4aXN0LAo+PiAtwqDCoMKgwqAgKiBub29wIGlmIGFscmVhZHkgY29ycmVjdCBzaXpl Cj4+IC3CoMKgwqDCoCAqLwo+PiAtwqDCoMKgIGZvYmogPSBrcmVhbGxvYyhvYmotPnN0YWdlZCwg b2Zmc2V0b2YodHlwZW9mKCpmb2JqKSwgc2hhcmVkW21heF0pLAo+PiAtwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCBHRlBfS0VSTkVMKTsKPj4gLcKgwqDCoCBpZiAoIWZvYmopCj4+IC3CoMKgwqDCoMKg wqDCoCByZXR1cm4gLUVOT01FTTsKPj4gLQo+PiAtwqDCoMKgIG9iai0+c3RhZ2VkID0gZm9iajsK Pj4gLcKgwqDCoCBmb2JqLT5zaGFyZWRfbWF4ID0gbWF4Owo+PiAtwqDCoMKgIHJldHVybiAwOwo+ PiAtfQo+PiAtRVhQT1JUX1NZTUJPTChyZXNlcnZhdGlvbl9vYmplY3RfcmVzZXJ2ZV9zaGFyZWQp Owo+PiAtCj4+IC1zdGF0aWMgdm9pZAo+PiAtcmVzZXJ2YXRpb25fb2JqZWN0X2FkZF9zaGFyZWRf aW5wbGFjZShzdHJ1Y3QgcmVzZXJ2YXRpb25fb2JqZWN0ICpvYmosCj4+IC3CoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgc3RydWN0IHJlc2VydmF0aW9uX29iamVjdF9s aXN0ICpmb2JqLAo+PiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg IHN0cnVjdCBkbWFfZmVuY2UgKmZlbmNlKQo+PiAtewo+PiAtwqDCoMKgIHN0cnVjdCBkbWFfZmVu Y2UgKnNpZ25hbGVkID0gTlVMTDsKPj4gLcKgwqDCoCB1MzIgaSwgc2lnbmFsZWRfaWR4Owo+PiAt Cj4+IC3CoMKgwqAgZG1hX2ZlbmNlX2dldChmZW5jZSk7Cj4+IC0KPj4gLcKgwqDCoCBwcmVlbXB0 X2Rpc2FibGUoKTsKPj4gLcKgwqDCoCB3cml0ZV9zZXFjb3VudF9iZWdpbigmb2JqLT5zZXEpOwo+ PiAtCj4+IC3CoMKgwqAgZm9yIChpID0gMDsgaSA8IGZvYmotPnNoYXJlZF9jb3VudDsgKytpKSB7 Cj4+IC3CoMKgwqDCoMKgwqDCoCBzdHJ1Y3QgZG1hX2ZlbmNlICpvbGRfZmVuY2U7Cj4+IC0KPj4g LcKgwqDCoMKgwqDCoMKgIG9sZF9mZW5jZSA9IHJjdV9kZXJlZmVyZW5jZV9wcm90ZWN0ZWQoZm9i ai0+c2hhcmVkW2ldLAo+PiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCByZXNlcnZhdGlvbl9vYmplY3RfaGVsZChvYmopKTsKPj4gLQo+PiAtwqDCoMKgwqDC oMKgwqAgaWYgKG9sZF9mZW5jZS0+Y29udGV4dCA9PSBmZW5jZS0+Y29udGV4dCkgewo+PiAtwqDC oMKgwqDCoMKgwqDCoMKgwqDCoCAvKiBtZW1vcnkgYmFycmllciBpcyBhZGRlZCBieSB3cml0ZV9z ZXFjb3VudF9iZWdpbiAqLwo+PiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBSQ1VfSU5JVF9QT0lO VEVSKGZvYmotPnNoYXJlZFtpXSwgZmVuY2UpOwo+PiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCB3 cml0ZV9zZXFjb3VudF9lbmQoJm9iai0+c2VxKTsKPj4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg cHJlZW1wdF9lbmFibGUoKTsKPj4gLQo+PiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBkbWFfZmVu Y2VfcHV0KG9sZF9mZW5jZSk7Cj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHJldHVybjsKPj4g LcKgwqDCoMKgwqDCoMKgIH0KPj4gLQo+PiAtwqDCoMKgwqDCoMKgwqAgaWYgKCFzaWduYWxlZCAm JiBkbWFfZmVuY2VfaXNfc2lnbmFsZWQob2xkX2ZlbmNlKSkgewo+PiAtwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCBzaWduYWxlZCA9IG9sZF9mZW5jZTsKPj4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg c2lnbmFsZWRfaWR4ID0gaTsKPj4gLcKgwqDCoMKgwqDCoMKgIH0KPj4gLcKgwqDCoCB9Cj4+IC0K Pj4gLcKgwqDCoCAvKgo+PiAtwqDCoMKgwqAgKiBtZW1vcnkgYmFycmllciBpcyBhZGRlZCBieSB3 cml0ZV9zZXFjb3VudF9iZWdpbiwKPj4gLcKgwqDCoMKgICogZm9iai0+c2hhcmVkX2NvdW50IGlz IHByb3RlY3RlZCBieSB0aGlzIGxvY2sgdG9vCj4+IC3CoMKgwqDCoCAqLwo+PiAtwqDCoMKgIGlm IChzaWduYWxlZCkgewo+PiAtwqDCoMKgwqDCoMKgwqAgUkNVX0lOSVRfUE9JTlRFUihmb2JqLT5z aGFyZWRbc2lnbmFsZWRfaWR4XSwgZmVuY2UpOwo+PiDCoMKgwqDCoMKgIH0gZWxzZSB7Cj4+IC3C oMKgwqDCoMKgwqDCoCBCVUdfT04oZm9iai0+c2hhcmVkX2NvdW50ID49IGZvYmotPnNoYXJlZF9t YXgpOwo+PiAtIFJDVV9JTklUX1BPSU5URVIoZm9iai0+c2hhcmVkW2ZvYmotPnNoYXJlZF9jb3Vu dF0sIGZlbmNlKTsKPj4gLcKgwqDCoMKgwqDCoMKgIGZvYmotPnNoYXJlZF9jb3VudCsrOwo+PiAr wqDCoMKgwqDCoMKgwqAgbWF4ID0gNDsKPj4gwqDCoMKgwqDCoCB9Cj4+IMKgIC3CoMKgwqAgd3Jp dGVfc2VxY291bnRfZW5kKCZvYmotPnNlcSk7Cj4+IC3CoMKgwqAgcHJlZW1wdF9lbmFibGUoKTsK Pj4gLQo+PiAtwqDCoMKgIGRtYV9mZW5jZV9wdXQoc2lnbmFsZWQpOwo+PiAtfQo+PiAtCj4+IC1z dGF0aWMgdm9pZAo+PiAtcmVzZXJ2YXRpb25fb2JqZWN0X2FkZF9zaGFyZWRfcmVwbGFjZShzdHJ1 Y3QgcmVzZXJ2YXRpb25fb2JqZWN0ICpvYmosCj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqAgc3RydWN0IHJlc2VydmF0aW9uX29iamVjdF9saXN0ICpvbGQsCj4+ IC3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgc3RydWN0IHJlc2Vy dmF0aW9uX29iamVjdF9saXN0ICpmb2JqLAo+PiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIHN0cnVjdCBkbWFfZmVuY2UgKmZlbmNlKQo+PiAtewo+PiAtwqDCoMKg IHVuc2lnbmVkIGksIGosIGs7Cj4+IC0KPj4gLcKgwqDCoCBkbWFfZmVuY2VfZ2V0KGZlbmNlKTsK Pj4gLQo+PiAtwqDCoMKgIGlmICghb2xkKSB7Cj4+IC3CoMKgwqDCoMKgwqDCoCBSQ1VfSU5JVF9Q T0lOVEVSKGZvYmotPnNoYXJlZFswXSwgZmVuY2UpOwo+PiAtwqDCoMKgwqDCoMKgwqAgZm9iai0+ c2hhcmVkX2NvdW50ID0gMTsKPj4gLcKgwqDCoMKgwqDCoMKgIGdvdG8gZG9uZTsKPj4gLcKgwqDC oCB9Cj4+ICvCoMKgwqAgbmV3ID0ga21hbGxvYyhvZmZzZXRvZih0eXBlb2YoKm5ldyksIHNoYXJl ZFttYXhdKSwgR0ZQX0tFUk5FTCk7Cj4+ICvCoMKgwqAgaWYgKCFuZXcpCj4+ICvCoMKgwqDCoMKg wqDCoCByZXR1cm4gLUVOT01FTTsKPj4gwqAgwqDCoMKgwqDCoCAvKgo+PiDCoMKgwqDCoMKgwqAg KiBubyBuZWVkIHRvIGJ1bXAgZmVuY2UgcmVmY291bnRzLCByY3VfcmVhZCBhY2Nlc3MKPj4gQEAg LTE3NCw0NiArOTIsNDUgQEAgcmVzZXJ2YXRpb25fb2JqZWN0X2FkZF9zaGFyZWRfcmVwbGFjZShz dHJ1Y3QgCj4+IHJlc2VydmF0aW9uX29iamVjdCAqb2JqLAo+PiDCoMKgwqDCoMKgwqAgKiByZWZl cmVuY2VzIGZyb20gdGhlIG9sZCBzdHJ1Y3QgYXJlIGNhcnJpZWQgb3ZlciB0bwo+PiDCoMKgwqDC oMKgwqAgKiB0aGUgbmV3Lgo+PiDCoMKgwqDCoMKgwqAgKi8KPj4gLcKgwqDCoCBmb3IgKGkgPSAw LCBqID0gMCwgayA9IGZvYmotPnNoYXJlZF9tYXg7IGkgPCBvbGQtPnNoYXJlZF9jb3VudDsgCj4+ ICsraSkgewo+PiAtwqDCoMKgwqDCoMKgwqAgc3RydWN0IGRtYV9mZW5jZSAqY2hlY2s7Cj4+ICvC oMKgwqAgZm9yIChpID0gMCwgaiA9IDAsIGsgPSBtYXg7IGkgPCAob2xkID8gb2xkLT5zaGFyZWRf Y291bnQgOiAwKTsgCj4+ICsraSkgewo+PiArwqDCoMKgwqDCoMKgwqAgc3RydWN0IGRtYV9mZW5j ZSAqZmVuY2U7Cj4+IMKgIC3CoMKgwqDCoMKgwqDCoCBjaGVjayA9IHJjdV9kZXJlZmVyZW5jZV9w cm90ZWN0ZWQob2xkLT5zaGFyZWRbaV0sCj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIHJlc2VydmF0aW9uX29iamVjdF9oZWxkKG9iaikpOwo+PiAtCj4+ IC3CoMKgwqDCoMKgwqDCoCBpZiAoY2hlY2stPmNvbnRleHQgPT0gZmVuY2UtPmNvbnRleHQgfHwK Pj4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZG1hX2ZlbmNlX2lzX3NpZ25hbGVkKGNoZWNrKSkK Pj4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgUkNVX0lOSVRfUE9JTlRFUihmb2JqLT5zaGFyZWRb LS1rXSwgY2hlY2spOwo+PiArwqDCoMKgwqDCoMKgwqAgZmVuY2UgPSByY3VfZGVyZWZlcmVuY2Vf cHJvdGVjdGVkKG9sZC0+c2hhcmVkW2ldLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcmVzZXJ2YXRpb25fb2JqZWN0X2hlbGQob2JqKSk7Cj4+ ICvCoMKgwqDCoMKgwqDCoCBpZiAoZG1hX2ZlbmNlX2lzX3NpZ25hbGVkKGZlbmNlKSkKPj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqAgUkNVX0lOSVRfUE9JTlRFUihuZXctPnNoYXJlZFstLWtdLCBm ZW5jZSk7Cj4+IMKgwqDCoMKgwqDCoMKgwqDCoCBlbHNlCj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDC oMKgIFJDVV9JTklUX1BPSU5URVIoZm9iai0+c2hhcmVkW2orK10sIGNoZWNrKTsKPj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAgUkNVX0lOSVRfUE9JTlRFUihuZXctPnNoYXJlZFtqKytdLCBmZW5j ZSk7Cj4+IMKgwqDCoMKgwqAgfQo+PiAtwqDCoMKgIGZvYmotPnNoYXJlZF9jb3VudCA9IGo7Cj4+ IC3CoMKgwqAgUkNVX0lOSVRfUE9JTlRFUihmb2JqLT5zaGFyZWRbZm9iai0+c2hhcmVkX2NvdW50 XSwgZmVuY2UpOwo+PiAtwqDCoMKgIGZvYmotPnNoYXJlZF9jb3VudCsrOwo+PiArwqDCoMKgIG5l dy0+c2hhcmVkX2NvdW50ID0gajsKPj4gK8KgwqDCoCBuZXctPnNoYXJlZF9tYXggPSBtYXg7Cj4+ IMKgIC1kb25lOgo+PiDCoMKgwqDCoMKgIHByZWVtcHRfZGlzYWJsZSgpOwo+PiDCoMKgwqDCoMKg IHdyaXRlX3NlcWNvdW50X2JlZ2luKCZvYmotPnNlcSk7Cj4+IMKgwqDCoMKgwqAgLyoKPj4gwqDC oMKgwqDCoMKgICogUkNVX0lOSVRfUE9JTlRFUiBjYW4gYmUgdXNlZCBoZXJlLAo+PiDCoMKgwqDC oMKgwqAgKiBzZXFjb3VudCBwcm92aWRlcyB0aGUgbmVjZXNzYXJ5IGJhcnJpZXJzCj4+IMKgwqDC oMKgwqDCoCAqLwo+PiAtwqDCoMKgIFJDVV9JTklUX1BPSU5URVIob2JqLT5mZW5jZSwgZm9iaik7 Cj4+ICvCoMKgwqAgUkNVX0lOSVRfUE9JTlRFUihvYmotPmZlbmNlLCBuZXcpOwo+PiDCoMKgwqDC oMKgIHdyaXRlX3NlcWNvdW50X2VuZCgmb2JqLT5zZXEpOwo+PiDCoMKgwqDCoMKgIHByZWVtcHRf ZW5hYmxlKCk7Cj4+IMKgIMKgwqDCoMKgwqAgaWYgKCFvbGQpCj4+IC3CoMKgwqDCoMKgwqDCoCBy ZXR1cm47Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gMDsKPj4gwqAgwqDCoMKgwqDCoCAvKiBE cm9wIHRoZSByZWZlcmVuY2VzIHRvIHRoZSBzaWduYWxlZCBmZW5jZXMgKi8KPj4gLcKgwqDCoCBm b3IgKGkgPSBrOyBpIDwgZm9iai0+c2hhcmVkX21heDsgKytpKSB7Cj4+IC3CoMKgwqDCoMKgwqDC oCBzdHJ1Y3QgZG1hX2ZlbmNlICpmOwo+PiArwqDCoMKgIGZvciAoaSA9IGs7IGkgPCBuZXctPnNo YXJlZF9tYXg7ICsraSkgewo+PiArwqDCoMKgwqDCoMKgwqAgc3RydWN0IGRtYV9mZW5jZSAqZmVu Y2U7Cj4+IMKgIC3CoMKgwqDCoMKgwqDCoCBmID0gcmN1X2RlcmVmZXJlbmNlX3Byb3RlY3RlZChm b2JqLT5zaGFyZWRbaV0sCj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCByZXNlcnZhdGlvbl9vYmplY3RfaGVsZChvYmopKTsKPj4gLcKgwqDCoMKg wqDCoMKgIGRtYV9mZW5jZV9wdXQoZik7Cj4+ICvCoMKgwqDCoMKgwqDCoCBmZW5jZSA9IHJjdV9k ZXJlZmVyZW5jZV9wcm90ZWN0ZWQobmV3LT5zaGFyZWRbaV0sCj4+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCByZXNlcnZhdGlvbl9vYmplY3RfaGVs ZChvYmopKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGRtYV9mZW5jZV9wdXQoZmVuY2UpOwo+PiDCoMKg wqDCoMKgIH0KPj4gwqDCoMKgwqDCoCBrZnJlZV9yY3Uob2xkLCByY3UpOwo+PiArCj4+ICvCoMKg wqAgcmV0dXJuIDA7Cj4+IMKgIH0KPj4gK0VYUE9SVF9TWU1CT0wocmVzZXJ2YXRpb25fb2JqZWN0 X3Jlc2VydmVfc2hhcmVkKTsKPj4gwqAgwqAgLyoqCj4+IMKgwqAgKiByZXNlcnZhdGlvbl9vYmpl Y3RfYWRkX3NoYXJlZF9mZW5jZSAtIEFkZCBhIGZlbmNlIHRvIGEgc2hhcmVkIHNsb3QKPj4gQEAg LTIyNiwxNSArMTQzLDM5IEBAIHJlc2VydmF0aW9uX29iamVjdF9hZGRfc2hhcmVkX3JlcGxhY2Uo c3RydWN0IAo+PiByZXNlcnZhdGlvbl9vYmplY3QgKm9iaiwKPj4gwqAgdm9pZCByZXNlcnZhdGlv bl9vYmplY3RfYWRkX3NoYXJlZF9mZW5jZShzdHJ1Y3QgcmVzZXJ2YXRpb25fb2JqZWN0IAo+PiAq b2JqLAo+PiDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBzdHJ1 Y3QgZG1hX2ZlbmNlICpmZW5jZSkKPj4gwqAgewo+PiAtwqDCoMKgIHN0cnVjdCByZXNlcnZhdGlv bl9vYmplY3RfbGlzdCAqb2xkLCAqZm9iaiA9IG9iai0+c3RhZ2VkOwo+PiArwqDCoMKgIHN0cnVj dCByZXNlcnZhdGlvbl9vYmplY3RfbGlzdCAqZm9iajsKPj4gK8KgwqDCoCB1bnNpZ25lZCBpbnQg aTsKPj4gwqAgLcKgwqDCoCBvbGQgPSByZXNlcnZhdGlvbl9vYmplY3RfZ2V0X2xpc3Qob2JqKTsK Pj4gLcKgwqDCoCBvYmotPnN0YWdlZCA9IE5VTEw7Cj4+ICvCoMKgwqAgZG1hX2ZlbmNlX2dldChm ZW5jZSk7Cj4+ICsKPj4gK8KgwqDCoCBmb2JqID0gcmVzZXJ2YXRpb25fb2JqZWN0X2dldF9saXN0 KG9iaik7Cj4+IMKgIC3CoMKgwqAgaWYgKCFmb2JqKQo+PiAtwqDCoMKgwqDCoMKgwqAgcmVzZXJ2 YXRpb25fb2JqZWN0X2FkZF9zaGFyZWRfaW5wbGFjZShvYmosIG9sZCwgZmVuY2UpOwo+PiAtwqDC oMKgIGVsc2UKPj4gLcKgwqDCoMKgwqDCoMKgIHJlc2VydmF0aW9uX29iamVjdF9hZGRfc2hhcmVk X3JlcGxhY2Uob2JqLCBvbGQsIGZvYmosIGZlbmNlKTsKPj4gK8KgwqDCoCBwcmVlbXB0X2Rpc2Fi bGUoKTsKPj4gK8KgwqDCoCB3cml0ZV9zZXFjb3VudF9iZWdpbigmb2JqLT5zZXEpOwo+PiArCj4+ ICvCoMKgwqAgZm9yIChpID0gMDsgaSA8IGZvYmotPnNoYXJlZF9jb3VudDsgKytpKSB7Cj4+ICvC oMKgwqDCoMKgwqDCoCBzdHJ1Y3QgZG1hX2ZlbmNlICpvbGRfZmVuY2U7Cj4+ICsKPj4gK8KgwqDC oMKgwqDCoMKgIG9sZF9mZW5jZSA9IHJjdV9kZXJlZmVyZW5jZV9wcm90ZWN0ZWQoZm9iai0+c2hh cmVkW2ldLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCByZXNlcnZhdGlvbl9vYmplY3RfaGVsZChvYmopKTsKPj4gK8KgwqDCoMKg wqDCoMKgIGlmIChvbGRfZmVuY2UtPmNvbnRleHQgPT0gZmVuY2UtPmNvbnRleHQgfHwKPj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqAgZG1hX2ZlbmNlX2lzX3NpZ25hbGVkKG9sZF9mZW5jZSkpIHsK Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZG1hX2ZlbmNlX3B1dChvbGRfZmVuY2UpOwo+PiAr wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBnb3RvIHJlcGxhY2U7Cj4+ICvCoMKgwqDCoMKgwqDCoCB9 Cj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgQlVHX09OKGZvYmotPnNoYXJlZF9jb3VudCA+ PSBmb2JqLT5zaGFyZWRfbWF4KTsKPj4gK8KgwqDCoCBmb2JqLT5zaGFyZWRfY291bnQrKzsKPj4g Kwo+PiArcmVwbGFjZToKPj4gK8KgwqDCoCAvKgo+PiArwqDCoMKgwqAgKiBtZW1vcnkgYmFycmll ciBpcyBhZGRlZCBieSB3cml0ZV9zZXFjb3VudF9iZWdpbiwKPj4gK8KgwqDCoMKgICogZm9iai0+ c2hhcmVkX2NvdW50IGlzIHByb3RlY3RlZCBieSB0aGlzIGxvY2sgdG9vCj4+ICvCoMKgwqDCoCAq Lwo+PiArwqDCoMKgIFJDVV9JTklUX1BPSU5URVIoZm9iai0+c2hhcmVkW2ldLCBmZW5jZSk7Cj4+ ICvCoMKgwqAgd3JpdGVfc2VxY291bnRfZW5kKCZvYmotPnNlcSk7Cj4+ICvCoMKgwqAgcHJlZW1w dF9lbmFibGUoKTsKPj4gwqAgfQo+PiDCoCBFWFBPUlRfU1lNQk9MKHJlc2VydmF0aW9uX29iamVj dF9hZGRfc2hhcmVkX2ZlbmNlKTsKPj4gwqAgQEAgLTM0Myw5ICsyODQsNiBAQCBpbnQgcmVzZXJ2 YXRpb25fb2JqZWN0X2NvcHlfZmVuY2VzKHN0cnVjdCAKPj4gcmVzZXJ2YXRpb25fb2JqZWN0ICpk c3QsCj4+IMKgwqDCoMKgwqAgbmV3ID0gZG1hX2ZlbmNlX2dldF9yY3Vfc2FmZSgmc3JjLT5mZW5j ZV9leGNsKTsKPj4gwqDCoMKgwqDCoCByY3VfcmVhZF91bmxvY2soKTsKPj4gwqAgLcKgwqDCoCBr ZnJlZShkc3QtPnN0YWdlZCk7Cj4+IC3CoMKgwqAgZHN0LT5zdGFnZWQgPSBOVUxMOwo+PiAtCj4+ IMKgwqDCoMKgwqAgc3JjX2xpc3QgPSByZXNlcnZhdGlvbl9vYmplY3RfZ2V0X2xpc3QoZHN0KTsK Pj4gwqDCoMKgwqDCoCBvbGQgPSByZXNlcnZhdGlvbl9vYmplY3RfZ2V0X2V4Y2woZHN0KTsKPj4g wqAgZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvcmVzZXJ2YXRpb24uaCBiL2luY2x1ZGUvbGlu dXgvcmVzZXJ2YXRpb24uaAo+PiBpbmRleCAwMjE2NmU4MTVhZmIuLjU0Y2Y2NzczYTE0YyAxMDA2 NDQKPj4gLS0tIGEvaW5jbHVkZS9saW51eC9yZXNlcnZhdGlvbi5oCj4+ICsrKyBiL2luY2x1ZGUv bGludXgvcmVzZXJ2YXRpb24uaAo+PiBAQCAtNjgsNyArNjgsNiBAQCBzdHJ1Y3QgcmVzZXJ2YXRp b25fb2JqZWN0X2xpc3Qgewo+PiDCoMKgICogQHNlcTogc2VxdWVuY2UgY291bnQgZm9yIG1hbmFn aW5nIFJDVSByZWFkLXNpZGUgc3luY2hyb25pemF0aW9uCj4+IMKgwqAgKiBAZmVuY2VfZXhjbDog dGhlIGV4Y2x1c2l2ZSBmZW5jZSwgaWYgdGhlcmUgaXMgb25lIGN1cnJlbnRseQo+PiDCoMKgICog QGZlbmNlOiBsaXN0IG9mIGN1cnJlbnQgc2hhcmVkIGZlbmNlcwo+PiAtICogQHN0YWdlZDogc3Rh Z2VkIGNvcHkgb2Ygc2hhcmVkIGZlbmNlcyBmb3IgUkNVIHVwZGF0ZXMKPj4gwqDCoCAqLwo+PiDC oCBzdHJ1Y3QgcmVzZXJ2YXRpb25fb2JqZWN0IHsKPj4gwqDCoMKgwqDCoCBzdHJ1Y3Qgd3dfbXV0 ZXggbG9jazsKPj4gQEAgLTc2LDcgKzc1LDYgQEAgc3RydWN0IHJlc2VydmF0aW9uX29iamVjdCB7 Cj4+IMKgIMKgwqDCoMKgwqAgc3RydWN0IGRtYV9mZW5jZSBfX3JjdSAqZmVuY2VfZXhjbDsKPj4g wqDCoMKgwqDCoCBzdHJ1Y3QgcmVzZXJ2YXRpb25fb2JqZWN0X2xpc3QgX19yY3UgKmZlbmNlOwo+ PiAtwqDCoMKgIHN0cnVjdCByZXNlcnZhdGlvbl9vYmplY3RfbGlzdCAqc3RhZ2VkOwo+PiDCoCB9 Owo+PiDCoCDCoCAjZGVmaW5lIHJlc2VydmF0aW9uX29iamVjdF9oZWxkKG9iaikgCj4+IGxvY2tk ZXBfaXNfaGVsZCgmKG9iaiktPmxvY2suYmFzZSkKPj4gQEAgLTk1LDcgKzkzLDYgQEAgcmVzZXJ2 YXRpb25fb2JqZWN0X2luaXQoc3RydWN0IHJlc2VydmF0aW9uX29iamVjdCAKPj4gKm9iaikKPj4g wqDCoMKgwqDCoCBfX3NlcWNvdW50X2luaXQoJm9iai0+c2VxLCByZXNlcnZhdGlvbl9zZXFjb3Vu dF9zdHJpbmcsIAo+PiAmcmVzZXJ2YXRpb25fc2VxY291bnRfY2xhc3MpOwo+PiDCoMKgwqDCoMKg IFJDVV9JTklUX1BPSU5URVIob2JqLT5mZW5jZSwgTlVMTCk7Cj4+IMKgwqDCoMKgwqAgUkNVX0lO SVRfUE9JTlRFUihvYmotPmZlbmNlX2V4Y2wsIE5VTEwpOwo+PiAtwqDCoMKgIG9iai0+c3RhZ2Vk ID0gTlVMTDsKPj4gwqAgfQo+PiDCoCDCoCAvKioKPj4gQEAgLTEyNCw3ICsxMjEsNiBAQCByZXNl cnZhdGlvbl9vYmplY3RfZmluaShzdHJ1Y3QgcmVzZXJ2YXRpb25fb2JqZWN0IAo+PiAqb2JqKQo+ PiDCoCDCoMKgwqDCoMKgwqDCoMKgwqAga2ZyZWUoZm9iaik7Cj4+IMKgwqDCoMKgwqAgfQo+PiAt wqDCoMKgIGtmcmVlKG9iai0+c3RhZ2VkKTsKPj4gwqAgwqDCoMKgwqDCoCB3d19tdXRleF9kZXN0 cm95KCZvYmotPmxvY2spOwo+PiDCoCB9Cj4KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fCmFtZC1nZnggbWFpbGluZyBsaXN0CmFtZC1nZnhAbGlzdHMuZnJl ZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGlu Zm8vYW1kLWdmeAo=