From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.1 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_MUTT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3BD7CC31E4B for ; Fri, 14 Jun 2019 18:24:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E63502177E for ; Fri, 14 Jun 2019 18:24:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=ffwll.ch header.i=@ffwll.ch header.b="bVmkBS2j" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726541AbfFNSYd (ORCPT ); Fri, 14 Jun 2019 14:24:33 -0400 Received: from mail-ed1-f68.google.com ([209.85.208.68]:46016 "EHLO mail-ed1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726028AbfFNSYd (ORCPT ); Fri, 14 Jun 2019 14:24:33 -0400 Received: by mail-ed1-f68.google.com with SMTP id a14so4720430edv.12 for ; Fri, 14 Jun 2019 11:24:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=sender:date:from:to:cc:subject:message-id:mail-followup-to :references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=Bik4fyHxboBXR92RW9HCfZ7+c9s6bxmlh2Q2rMmWiHw=; b=bVmkBS2jisCkHksnNDuo09tYLsagcC/ctzMSXA3UCuSrjIuhuBBItZI7cWiacVOuJS HMeDeOXj2H3fMcK1H50lBYTCXtZsqQ3PlTOz++l6OFe81ryzf6Cy9Za3bAlkclBr7gMr cC2GVq5e0kEpm/pDsmZFay84KlJES3Im2Ise4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=Bik4fyHxboBXR92RW9HCfZ7+c9s6bxmlh2Q2rMmWiHw=; b=eEFgnC61hv9fspnB+wYIA/iWLLi2iOBCGoCIokSHdLtkEgDnNgcJqLYSk+MCeh3gX4 4mO4LSHD6pP6d+MYnVdSDT9XInBsjtkQbOu+ReggJ1x8SN6zPXZT9mUJA9mmmZds1gT7 Hh/ssCYOtPS3sZ4R2wSBC4d+it7vhTAOrHrIqva+n1QHqoy22zxptagSWVzyd0hTc+F7 5JHI4MhawQOdz1NkwLKRNK5/etzXfvLSiRq6q7Fu2B1fQDEArKG+6D6jEpAwjALFQfrZ RCM8016sDjqRw7bohWJ+U4A1LoX53gRjIPvc+iHGOYs4gFIABzVtzVxJywwgRPan/Erw 2EfA== X-Gm-Message-State: APjAAAWpqOdpLs6oT27z39zG5OZeElpaMElGA3+iAkWliyE6DAjPyc7e e88fJ3pheG0/Jjz1Z0q3PzX5iQ== X-Google-Smtp-Source: APXvYqxu2G4yQDUtjpvg6r9kNR1LFXoiZ6I4EhpXDYO3aBnyr6O8u5qqbMKQ2cU2Lyap9yA9fp+YKw== X-Received: by 2002:a17:907:20db:: with SMTP id qq27mr63221217ejb.30.1560536670462; Fri, 14 Jun 2019 11:24:30 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:569e:0:3106:d637:d723:e855]) by smtp.gmail.com with ESMTPSA id d5sm717021ejk.71.2019.06.14.11.24.29 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Fri, 14 Jun 2019 11:24:29 -0700 (PDT) Date: Fri, 14 Jun 2019 20:24:27 +0200 From: Daniel Vetter To: Christian =?iso-8859-1?Q?K=F6nig?= Cc: Peter Zijlstra , Lucas Stach , Russell King , Christian Gmeiner , Qiang Yu , "Anholt, Eric" , Thomas Hellstrom , dri-devel , Linux Kernel Mailing List , The etnaviv authors , lima@lists.freedesktop.org Subject: Re: [PATCH 3/6] drm/gem: use new ww_mutex_(un)lock_for_each macros Message-ID: Mail-Followup-To: Christian =?iso-8859-1?Q?K=F6nig?= , Peter Zijlstra , Lucas Stach , Russell King , Christian Gmeiner , Qiang Yu , "Anholt, Eric" , Thomas Hellstrom , dri-devel , Linux Kernel Mailing List , The etnaviv authors , lima@lists.freedesktop.org References: <20190614124125.124181-1-christian.koenig@amd.com> <20190614124125.124181-4-christian.koenig@amd.com> <20190614131916.GQ3436@hirez.programming.kicks-ass.net> <20190614152242.GC23020@phenom.ffwll.local> <094da0f7-a0f0-9ed4-d2da-8c6e6d165380@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <094da0f7-a0f0-9ed4-d2da-8c6e6d165380@gmail.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jun 14, 2019 at 8:10 PM Christian König wrote: > > Am 14.06.19 um 17:22 schrieb Daniel Vetter: > > On Fri, Jun 14, 2019 at 03:19:16PM +0200, Peter Zijlstra wrote: > >> On Fri, Jun 14, 2019 at 02:41:22PM +0200, Christian König wrote: > >>> Use the provided macros instead of implementing deadlock handling on our own. > >>> > >>> Signed-off-by: Christian König > >>> --- > >>> drivers/gpu/drm/drm_gem.c | 49 ++++++++++----------------------------- > >>> 1 file changed, 12 insertions(+), 37 deletions(-) > >>> > >>> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c > >>> index 50de138c89e0..6e4623d3bee2 100644 > >>> --- a/drivers/gpu/drm/drm_gem.c > >>> +++ b/drivers/gpu/drm/drm_gem.c > >>> @@ -1307,51 +1307,26 @@ int > >>> drm_gem_lock_reservations(struct drm_gem_object **objs, int count, > >>> struct ww_acquire_ctx *acquire_ctx) > >>> { > >>> - int contended = -1; > >>> + struct ww_mutex *contended; > >>> int i, ret; > >>> > >>> ww_acquire_init(acquire_ctx, &reservation_ww_class); > >>> > >>> -retry: > >>> - if (contended != -1) { > >>> - struct drm_gem_object *obj = objs[contended]; > >>> - > >>> - ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock, > >>> - acquire_ctx); > >>> - if (ret) { > >>> - ww_acquire_done(acquire_ctx); > >>> - return ret; > >>> - } > >>> - } > >>> - > >>> - for (i = 0; i < count; i++) { > >>> - if (i == contended) > >>> - continue; > >>> - > >>> - ret = ww_mutex_lock_interruptible(&objs[i]->resv->lock, > >>> - acquire_ctx); > >>> - if (ret) { > >>> - int j; > >>> - > >>> - for (j = 0; j < i; j++) > >>> - ww_mutex_unlock(&objs[j]->resv->lock); > >>> - > >>> - if (contended != -1 && contended >= i) > >>> - ww_mutex_unlock(&objs[contended]->resv->lock); > >>> - > >>> - if (ret == -EDEADLK) { > >>> - contended = i; > >>> - goto retry; > >>> - } > >>> - > >>> - ww_acquire_done(acquire_ctx); > >>> - return ret; > >>> - } > >>> - } > >> I note all the sites you use this on are simple idx iterators; so how > >> about something like so: > >> > >> int ww_mutex_unlock_all(int count, void *data, struct ww_mutex *(*func)(int, void *)) > >> { > >> int i; > >> > >> for (i = 0; i < count; i++) { > >> lock = func(i, data); > >> ww_mutex_unlock(lock); > >> } > >> } > >> > >> int ww_mutex_lock_all(int count, struct ww_acquire_context *acquire_ctx, bool intr, > >> void *data, struct ww_mutex *(*func)(int, void *)) > >> { > >> int i, ret, contended = -1; > >> struct ww_mutex *lock; > >> > >> retry: > >> if (contended != -1) { > >> lock = func(contended, data); > >> if (intr) > >> ret = ww_mutex_lock_slow_interruptible(lock, acquire_ctx); > >> else > >> ret = ww_mutex_lock_slow(lock, acquire_ctx), 0; > >> > >> if (ret) { > >> ww_acquire_done(acquire_ctx); > >> return ret; > >> } > >> } > >> > >> for (i = 0; i < count; i++) { > >> if (i == contended) > >> continue; > >> > >> lock = func(i, data); > >> if (intr) > >> ret = ww_mutex_lock_interruptible(lock, acquire_ctx); > >> else > >> ret = ww_mutex_lock(lock, acquire_ctx), 0; > >> > >> if (ret) { > >> ww_mutex_unlock_all(i, data, func); > >> if (contended > i) { > >> lock = func(contended, data); > >> ww_mutex_unlock(lock); > >> } > >> > >> if (ret == -EDEADLK) { > >> contended = i; > >> goto retry; > >> } > >> > >> ww_acquire_done(acquire_ctx); > >> return ret; > >> } > >> } > >> > >> ww_acquire_done(acquire_ctx); > >> return 0; > >> } > >> > >>> + ww_mutex_lock_for_each(for (i = 0; i < count; i++), > >>> + &objs[i]->resv->lock, contended, ret, true, > >>> + acquire_ctx) > >>> + if (ret) > >>> + goto error; > >> which then becomes: > >> > >> struct ww_mutex *gem_ww_mutex_func(int i, void *data) > >> { > >> struct drm_gem_object **objs = data; > >> return &objs[i]->resv->lock; > >> } > >> > >> ret = ww_mutex_lock_all(count, acquire_ctx, true, objs, gem_ww_mutex_func); > >> > >>> ww_acquire_done(acquire_ctx); > >>> > >>> return 0; > >>> + > >>> +error: > >>> + ww_mutex_unlock_for_each(for (i = 0; i < count; i++), > >>> + &objs[i]->resv->lock, contended); > >>> + ww_acquire_done(acquire_ctx); > >>> + return ret; > >>> } > >>> EXPORT_SYMBOL(drm_gem_lock_reservations); > > Another idea, entirely untested (I guess making sure that we can use the > > same iterator for both locking and unlocking in the contended case will be > > fun), but maybe something like this: > > > > WW_MUTEX_LOCK_BEGIN(); > > driver_for_each_loop (iter, pos) { > > WW_MUTEX_LOCK(&pos->ww_mutex); > > } > > WW_MUTEX_LOCK_END(); > > > > That way we can reuse any and all iterators that'll ever show up at least. > > It's still horrible because the macros need to jump around between all of > > them. > > Yeah, I tried this as well and that's exactly the reason why I discarded > this approach. > > There is this hack with goto *void we could use, but I'm pretty sure > that is actually not part of any C standard. Nah, just invisible jump labels + the all uppercase macro names to scream that into your face. You essentially trade one set of horrors for another, and this one allows you to open-code any kind of loop or other algorithim to find all the ww_mutexes you need. > > Would also make this useful for more cases, where maybe you need to > > trylock some lru lock to get at your next ww_mutex, or do some > > kref_get_unless_zero. Buffer eviction loops tend to acquire these, and > > that would all get ugly real fast if we'd need to stuff it into some > > iterator argument. > > Well I don't see a use case with eviction in general. The dance there > requires something different as far as I can see. Current ttm doesn't really bother with multi-threaded contention for all of memory. You're fixing that, but I think in the end we need a slow-reclaim which eats up the entire lru using the full ww_mutex dance. Rougly WW_MUTEX_LOCK_BEGIN() lock(lru_lock); while (bo = list_first(lru)) { if (kref_get_unless_zero(bo)) { unlock(lru_lock); WW_MUTEX_LOCK(bo->ww_mutex); lock(lru_lock); } else { /* bo is getting freed, steal it from the freeing process * or just ignore */ } } unlock(lru_lock) WW_MUTEX_LOCK_END; Also I think if we allow this we could perhaps use this to implement the modeset macros too. -Daniel > > This is kinda what we went with for modeset locks with > > DRM_MODESET_LOCK_ALL_BEGIN/END, you can grab more locks in between the > > pair at least. But it's a lot more limited use-cases, maybe too fragile an > > idea for ww_mutex in full generality. > > > > Not going to type this out because too much w/e mode here already, but I > > can give it a stab next week. > > -Daniel > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: Re: [PATCH 3/6] drm/gem: use new ww_mutex_(un)lock_for_each macros Date: Fri, 14 Jun 2019 20:24:27 +0200 Message-ID: References: <20190614124125.124181-1-christian.koenig@amd.com> <20190614124125.124181-4-christian.koenig@amd.com> <20190614131916.GQ3436@hirez.programming.kicks-ass.net> <20190614152242.GC23020@phenom.ffwll.local> <094da0f7-a0f0-9ed4-d2da-8c6e6d165380@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail-ed1-x541.google.com (mail-ed1-x541.google.com [IPv6:2a00:1450:4864:20::541]) by gabe.freedesktop.org (Postfix) with ESMTPS id D756A89B5F for ; Fri, 14 Jun 2019 18:24:31 +0000 (UTC) Received: by mail-ed1-x541.google.com with SMTP id i11so4805114edq.0 for ; Fri, 14 Jun 2019 11:24:31 -0700 (PDT) Content-Disposition: inline In-Reply-To: <094da0f7-a0f0-9ed4-d2da-8c6e6d165380@gmail.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Christian =?iso-8859-1?Q?K=F6nig?= Cc: Thomas Hellstrom , lima@lists.freedesktop.org, Peter Zijlstra , Linux Kernel Mailing List , dri-devel , The etnaviv authors , Qiang Yu , Russell King List-Id: dri-devel@lists.freedesktop.org CgpPbiBGcmksIEp1biAxNCwgMjAxOSBhdCA4OjEwIFBNIENocmlzdGlhbiBLw7ZuaWcgPGNrb2Vu aWcubGVpY2h0enVtZXJrZW5AZ21haWwuY29tPiB3cm90ZToKPgo+IEFtIDE0LjA2LjE5IHVtIDE3 OjIyIHNjaHJpZWIgRGFuaWVsIFZldHRlcjoKPiA+IE9uIEZyaSwgSnVuIDE0LCAyMDE5IGF0IDAz OjE5OjE2UE0gKzAyMDAsIFBldGVyIFppamxzdHJhIHdyb3RlOgo+ID4+IE9uIEZyaSwgSnVuIDE0 LCAyMDE5IGF0IDAyOjQxOjIyUE0gKzAyMDAsIENocmlzdGlhbiBLw7ZuaWcgd3JvdGU6Cj4gPj4+ IFVzZSB0aGUgcHJvdmlkZWQgbWFjcm9zIGluc3RlYWQgb2YgaW1wbGVtZW50aW5nIGRlYWRsb2Nr IGhhbmRsaW5nIG9uIG91ciBvd24uCj4gPj4+Cj4gPj4+IFNpZ25lZC1vZmYtYnk6IENocmlzdGlh biBLw7ZuaWcgPGNocmlzdGlhbi5rb2VuaWdAYW1kLmNvbT4KPiA+Pj4gLS0tCj4gPj4+ICAgZHJp dmVycy9ncHUvZHJtL2RybV9nZW0uYyB8IDQ5ICsrKysrKysrKystLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLQo+ID4+PiAgIDEgZmlsZSBjaGFuZ2VkLCAxMiBpbnNlcnRpb25zKCspLCAzNyBk ZWxldGlvbnMoLSkKPiA+Pj4KPiA+Pj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9kcm1f Z2VtLmMgYi9kcml2ZXJzL2dwdS9kcm0vZHJtX2dlbS5jCj4gPj4+IGluZGV4IDUwZGUxMzhjODll MC4uNmU0NjIzZDNiZWUyIDEwMDY0NAo+ID4+PiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vZHJtX2dl bS5jCj4gPj4+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9kcm1fZ2VtLmMKPiA+Pj4gQEAgLTEzMDcs NTEgKzEzMDcsMjYgQEAgaW50Cj4gPj4+ICAgZHJtX2dlbV9sb2NrX3Jlc2VydmF0aW9ucyhzdHJ1 Y3QgZHJtX2dlbV9vYmplY3QgKipvYmpzLCBpbnQgY291bnQsCj4gPj4+ICAgICAgICAgICAgICAg ICAgICAgICBzdHJ1Y3Qgd3dfYWNxdWlyZV9jdHggKmFjcXVpcmVfY3R4KQo+ID4+PiAgIHsKPiA+ Pj4gLSAgIGludCBjb250ZW5kZWQgPSAtMTsKPiA+Pj4gKyAgIHN0cnVjdCB3d19tdXRleCAqY29u dGVuZGVkOwo+ID4+PiAgICAgaW50IGksIHJldDsKPiA+Pj4gIAo+ID4+PiAgICAgd3dfYWNxdWly ZV9pbml0KGFjcXVpcmVfY3R4LCAmcmVzZXJ2YXRpb25fd3dfY2xhc3MpOwo+ID4+PiAgCj4gPj4+ IC1yZXRyeToKPiA+Pj4gLSAgIGlmIChjb250ZW5kZWQgIT0gLTEpIHsKPiA+Pj4gLSAgICAgICAg ICAgc3RydWN0IGRybV9nZW1fb2JqZWN0ICpvYmogPSBvYmpzW2NvbnRlbmRlZF07Cj4gPj4+IC0K PiA+Pj4gLSAgICAgICAgICAgcmV0ID0gd3dfbXV0ZXhfbG9ja19zbG93X2ludGVycnVwdGlibGUo Jm9iai0+cmVzdi0+bG9jaywKPiA+Pj4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgYWNxdWlyZV9jdHgpOwo+ID4+PiAtICAgICAgICAgICBpZiAocmV0 KSB7Cj4gPj4+IC0gICAgICAgICAgICAgICAgICAgd3dfYWNxdWlyZV9kb25lKGFjcXVpcmVfY3R4 KTsKPiA+Pj4gLSAgICAgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+ID4+PiAtICAgICAgICAg ICB9Cj4gPj4+IC0gICB9Cj4gPj4+IC0KPiA+Pj4gLSAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsg aSsrKSB7Cj4gPj4+IC0gICAgICAgICAgIGlmIChpID09IGNvbnRlbmRlZCkKPiA+Pj4gLSAgICAg ICAgICAgICAgICAgICBjb250aW51ZTsKPiA+Pj4gLQo+ID4+PiAtICAgICAgICAgICByZXQgPSB3 d19tdXRleF9sb2NrX2ludGVycnVwdGlibGUoJm9ianNbaV0tPnJlc3YtPmxvY2ssCj4gPj4+IC0g ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3F1aXJlX2N0eCk7 Cj4gPj4+IC0gICAgICAgICAgIGlmIChyZXQpIHsKPiA+Pj4gLSAgICAgICAgICAgICAgICAgICBp bnQgajsKPiA+Pj4gLQo+ID4+PiAtICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBp OyBqKyspCj4gPj4+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICB3d19tdXRleF91bmxvY2so Jm9ianNbal0tPnJlc3YtPmxvY2spOwo+ID4+PiAtCj4gPj4+IC0gICAgICAgICAgICAgICAgICAg aWYgKGNvbnRlbmRlZCAhPSAtMSAmJiBjb250ZW5kZWQgPj0gaSkKPiA+Pj4gLSAgICAgICAgICAg ICAgICAgICAgICAgICAgIHd3X211dGV4X3VubG9jaygmb2Jqc1tjb250ZW5kZWRdLT5yZXN2LT5s b2NrKTsKPiA+Pj4gLQo+ID4+PiAtICAgICAgICAgICAgICAgICAgIGlmIChyZXQgPT0gLUVERUFE TEspIHsKPiA+Pj4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbmRlZCA9IGk7Cj4g Pj4+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICBnb3RvIHJldHJ5Owo+ID4+PiAtICAgICAg ICAgICAgICAgICAgIH0KPiA+Pj4gLQo+ID4+PiAtICAgICAgICAgICAgICAgICAgIHd3X2FjcXVp cmVfZG9uZShhY3F1aXJlX2N0eCk7Cj4gPj4+IC0gICAgICAgICAgICAgICAgICAgcmV0dXJuIHJl dDsKPiA+Pj4gLSAgICAgICAgICAgfQo+ID4+PiAtICAgfQo+ID4+IEkgbm90ZSBhbGwgdGhlIHNp dGVzIHlvdSB1c2UgdGhpcyBvbiBhcmUgc2ltcGxlIGlkeCBpdGVyYXRvcnM7IHNvIGhvdwo+ID4+ IGFib3V0IHNvbWV0aGluZyBsaWtlIHNvOgo+ID4+Cj4gPj4gaW50IHd3X211dGV4X3VubG9ja19h bGwoaW50IGNvdW50LCB2b2lkICpkYXRhLCBzdHJ1Y3Qgd3dfbXV0ZXggKigqZnVuYykoaW50LCB2 b2lkICopKQo+ID4+IHsKPiA+PiAgICAgIGludCBpOwo+ID4+Cj4gPj4gICAgICBmb3IgKGkgPSAw OyBpIDwgY291bnQ7IGkrKykgewo+ID4+ICAgICAgICAgICAgICBsb2NrID0gZnVuYyhpLCBkYXRh KTsKPiA+PiAgICAgICAgICAgICAgd3dfbXV0ZXhfdW5sb2NrKGxvY2spOwo+ID4+ICAgICAgfQo+ ID4+IH0KPiA+Pgo+ID4+IGludCB3d19tdXRleF9sb2NrX2FsbChpbnQgY291bnQsIHN0cnVjdCB3 d19hY3F1aXJlX2NvbnRleHQgKmFjcXVpcmVfY3R4LCBib29sIGludHIsCj4gPj4gICAgICAgICAg ICAgICAgICAgIHZvaWQgKmRhdGEsIHN0cnVjdCB3d19tdXRleCAqKCpmdW5jKShpbnQsIHZvaWQg KikpCj4gPj4gewo+ID4+ICAgICAgaW50IGksIHJldCwgY29udGVuZGVkID0gLTE7Cj4gPj4gICAg ICBzdHJ1Y3Qgd3dfbXV0ZXggKmxvY2s7Cj4gPj4KPiA+PiByZXRyeToKPiA+PiAgICAgIGlmIChj b250ZW5kZWQgIT0gLTEpIHsKPiA+PiAgICAgICAgICAgICAgbG9jayA9IGZ1bmMoY29udGVuZGVk LCBkYXRhKTsKPiA+PiAgICAgICAgICAgICAgaWYgKGludHIpCj4gPj4gICAgICAgICAgICAgICAg ICAgICAgcmV0ID0gd3dfbXV0ZXhfbG9ja19zbG93X2ludGVycnVwdGlibGUobG9jaywgYWNxdWly ZV9jdHgpOwo+ID4+ICAgICAgICAgICAgICBlbHNlCj4gPj4gICAgICAgICAgICAgICAgICAgICAg cmV0ID0gd3dfbXV0ZXhfbG9ja19zbG93KGxvY2ssIGFjcXVpcmVfY3R4KSwgMDsKPiA+Pgo+ID4+ ICAgICAgICAgICAgICBpZiAocmV0KSB7Cj4gPj4gICAgICAgICAgICAgICAgICAgICAgd3dfYWNx dWlyZV9kb25lKGFjcXVpcmVfY3R4KTsKPiA+PiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4g cmV0Owo+ID4+ICAgICAgICAgICAgICB9Cj4gPj4gICAgICB9Cj4gPj4KPiA+PiAgICAgIGZvciAo aSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7Cj4gPj4gICAgICAgICAgICAgIGlmIChpID09IGNvbnRl bmRlZCkKPiA+PiAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKPiA+Pgo+ID4+ICAgICAg ICAgICAgICBsb2NrID0gZnVuYyhpLCBkYXRhKTsKPiA+PiAgICAgICAgICAgICAgaWYgKGludHIp Cj4gPj4gICAgICAgICAgICAgICAgICAgICAgcmV0ID0gd3dfbXV0ZXhfbG9ja19pbnRlcnJ1cHRp YmxlKGxvY2ssIGFjcXVpcmVfY3R4KTsKPiA+PiAgICAgICAgICAgICAgZWxzZQo+ID4+ICAgICAg ICAgICAgICAgICAgICAgIHJldCA9IHd3X211dGV4X2xvY2sobG9jaywgYWNxdWlyZV9jdHgpLCAw Owo+ID4+Cj4gPj4gICAgICAgICAgICAgIGlmIChyZXQpIHsKPiA+PiAgICAgICAgICAgICAgICAg ICAgICB3d19tdXRleF91bmxvY2tfYWxsKGksIGRhdGEsIGZ1bmMpOwo+ID4+ICAgICAgICAgICAg ICAgICAgICAgIGlmIChjb250ZW5kZWQgPiBpKSB7Cj4gPj4gICAgICAgICAgICAgICAgICAgICAg ICAgICAgICBsb2NrID0gZnVuYyhjb250ZW5kZWQsIGRhdGEpOwo+ID4+ICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgd3dfbXV0ZXhfdW5sb2NrKGxvY2spOwo+ID4+ICAgICAgICAgICAgICAg ICAgICAgIH0KPiA+Pgo+ID4+ICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXQgPT0gLUVERUFE TEspIHsKPiA+PiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbmRlZCA9IGk7Cj4g Pj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb3RvIHJldHJ5Owo+ID4+ICAgICAgICAg ICAgICAgICAgICAgIH0KPiA+Pgo+ID4+ICAgICAgICAgICAgICAgICAgICAgIHd3X2FjcXVpcmVf ZG9uZShhY3F1aXJlX2N0eCk7Cj4gPj4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldDsK PiA+PiAgICAgICAgICAgICAgfQo+ID4+ICAgICAgfQo+ID4+Cj4gPj4gICAgICB3d19hY3F1aXJl X2RvbmUoYWNxdWlyZV9jdHgpOwo+ID4+ICAgICAgcmV0dXJuIDA7Cj4gPj4gfQo+ID4+Cj4gPj4+ ICsgICB3d19tdXRleF9sb2NrX2Zvcl9lYWNoKGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSwK PiA+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgJm9ianNbaV0tPnJlc3YtPmxvY2ssIGNv bnRlbmRlZCwgcmV0LCB0cnVlLAo+ID4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICBhY3F1 aXJlX2N0eCkKPiA+Pj4gKyAgICAgICAgICAgaWYgKHJldCkKPiA+Pj4gKyAgICAgICAgICAgICAg ICAgICBnb3RvIGVycm9yOwo+ID4+IHdoaWNoIHRoZW4gYmVjb21lczoKPiA+Pgo+ID4+IHN0cnVj dCB3d19tdXRleCAqZ2VtX3d3X211dGV4X2Z1bmMoaW50IGksIHZvaWQgKmRhdGEpCj4gPj4gewo+ ID4+ICAgICAgc3RydWN0IGRybV9nZW1fb2JqZWN0ICoqb2JqcyA9IGRhdGE7Cj4gPj4gICAgICBy ZXR1cm4gJm9ianNbaV0tPnJlc3YtPmxvY2s7Cj4gPj4gfQo+ID4+Cj4gPj4gICAgICByZXQgPSB3 d19tdXRleF9sb2NrX2FsbChjb3VudCwgYWNxdWlyZV9jdHgsIHRydWUsIG9ianMsIGdlbV93d19t dXRleF9mdW5jKTsKPiA+Pgo+ID4+PiAgICAgd3dfYWNxdWlyZV9kb25lKGFjcXVpcmVfY3R4KTsK PiA+Pj4gIAo+ID4+PiAgICAgcmV0dXJuIDA7Cj4gPj4+ICsKPiA+Pj4gK2Vycm9yOgo+ID4+PiAr ICAgd3dfbXV0ZXhfdW5sb2NrX2Zvcl9lYWNoKGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSwK PiA+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAmb2Jqc1tpXS0+cmVzdi0+bG9jaywg Y29udGVuZGVkKTsKPiA+Pj4gKyAgIHd3X2FjcXVpcmVfZG9uZShhY3F1aXJlX2N0eCk7Cj4gPj4+ ICsgICByZXR1cm4gcmV0Owo+ID4+PiAgIH0KPiA+Pj4gICBFWFBPUlRfU1lNQk9MKGRybV9nZW1f bG9ja19yZXNlcnZhdGlvbnMpOwo+ID4gQW5vdGhlciBpZGVhLCBlbnRpcmVseSB1bnRlc3RlZCAo SSBndWVzcyBtYWtpbmcgc3VyZSB0aGF0IHdlIGNhbiB1c2UgdGhlCj4gPiBzYW1lIGl0ZXJhdG9y IGZvciBib3RoIGxvY2tpbmcgYW5kIHVubG9ja2luZyBpbiB0aGUgY29udGVuZGVkIGNhc2Ugd2ls bCBiZQo+ID4gZnVuKSwgYnV0IG1heWJlIHNvbWV0aGluZyBsaWtlIHRoaXM6Cj4gPgo+ID4gICAg ICAgV1dfTVVURVhfTE9DS19CRUdJTigpOwo+ID4gICAgICAgZHJpdmVyX2Zvcl9lYWNoX2xvb3Ag KGl0ZXIsIHBvcykgewo+ID4gICAgICAgICAgICAgICBXV19NVVRFWF9MT0NLKCZwb3MtPnd3X211 dGV4KTsKPiA+ICAgICAgIH0KPiA+ICAgICAgIFdXX01VVEVYX0xPQ0tfRU5EKCk7Cj4gPgo+ID4g VGhhdCB3YXkgd2UgY2FuIHJldXNlIGFueSBhbmQgYWxsIGl0ZXJhdG9ycyB0aGF0J2xsIGV2ZXIg c2hvdyB1cCBhdCBsZWFzdC4KPiA+IEl0J3Mgc3RpbGwgaG9ycmlibGUgYmVjYXVzZSB0aGUgbWFj cm9zIG5lZWQgdG8ganVtcCBhcm91bmQgYmV0d2VlbiBhbGwgb2YKPiA+IHRoZW0uCj4KPiBZZWFo LCBJIHRyaWVkIHRoaXMgYXMgd2VsbCBhbmQgdGhhdCdzIGV4YWN0bHkgdGhlIHJlYXNvbiB3aHkg SSBkaXNjYXJkZWQKPiB0aGlzIGFwcHJvYWNoLgo+Cj4gVGhlcmUgaXMgdGhpcyBoYWNrIHdpdGgg Z290byAqdm9pZCB3ZSBjb3VsZCB1c2UsIGJ1dCBJJ20gcHJldHR5IHN1cmUKPiB0aGF0IGlzIGFj dHVhbGx5IG5vdCBwYXJ0IG9mIGFueSBDIHN0YW5kYXJkLgoKTmFoLCBqdXN0IGludmlzaWJsZSBq dW1wIGxhYmVscyArIHRoZSBhbGwgdXBwZXJjYXNlIG1hY3JvIG5hbWVzIHRvIHNjcmVhbQp0aGF0 IGludG8geW91ciBmYWNlLiBZb3UgZXNzZW50aWFsbHkgdHJhZGUgb25lIHNldCBvZiBob3Jyb3Jz IGZvciBhbm90aGVyLAphbmQgdGhpcyBvbmUgYWxsb3dzIHlvdSB0byBvcGVuLWNvZGUgYW55IGtp bmQgb2YgbG9vcCBvciBvdGhlciBhbGdvcml0aGltCnRvIGZpbmQgYWxsIHRoZSB3d19tdXRleGVz IHlvdSBuZWVkLgoKPiA+IFdvdWxkIGFsc28gbWFrZSB0aGlzIHVzZWZ1bCBmb3IgbW9yZSBjYXNl cywgd2hlcmUgbWF5YmUgeW91IG5lZWQgdG8KPiA+IHRyeWxvY2sgc29tZSBscnUgbG9jayB0byBn ZXQgYXQgeW91ciBuZXh0IHd3X211dGV4LCBvciBkbyBzb21lCj4gPiBrcmVmX2dldF91bmxlc3Nf emVyby4gQnVmZmVyIGV2aWN0aW9uIGxvb3BzIHRlbmQgdG8gYWNxdWlyZSB0aGVzZSwgYW5kCj4g PiB0aGF0IHdvdWxkIGFsbCBnZXQgdWdseSByZWFsIGZhc3QgaWYgd2UnZCBuZWVkIHRvIHN0dWZm IGl0IGludG8gc29tZQo+ID4gaXRlcmF0b3IgYXJndW1lbnQuCj4KPiBXZWxsIEkgZG9uJ3Qgc2Vl IGEgdXNlIGNhc2Ugd2l0aCBldmljdGlvbiBpbiBnZW5lcmFsLiBUaGUgZGFuY2UgdGhlcmUKPiBy ZXF1aXJlcyBzb21ldGhpbmcgZGlmZmVyZW50IGFzIGZhciBhcyBJIGNhbiBzZWUuCgpDdXJyZW50 IHR0bSBkb2Vzbid0IHJlYWxseSBib3RoZXIgd2l0aCBtdWx0aS10aHJlYWRlZCBjb250ZW50aW9u IGZvciBhbGwKb2YgbWVtb3J5LiBZb3UncmUgZml4aW5nIHRoYXQsIGJ1dCBJIHRoaW5rIGluIHRo ZSBlbmQgd2UgbmVlZCBhCnNsb3ctcmVjbGFpbSB3aGljaCBlYXRzIHVwIHRoZSBlbnRpcmUgbHJ1 IHVzaW5nIHRoZSBmdWxsIHd3X211dGV4IGRhbmNlLgpSb3VnbHkKCldXX01VVEVYX0xPQ0tfQkVH SU4oKQoKbG9jayhscnVfbG9jayk7Cgp3aGlsZSAoYm8gPSBsaXN0X2ZpcnN0KGxydSkpIHsKCWlm IChrcmVmX2dldF91bmxlc3NfemVybyhibykpIHsKCQl1bmxvY2sobHJ1X2xvY2spOwoJCVdXX01V VEVYX0xPQ0soYm8tPnd3X211dGV4KTsKCQlsb2NrKGxydV9sb2NrKTsKCX0gZWxzZSB7CgkJLyog Ym8gaXMgZ2V0dGluZyBmcmVlZCwgc3RlYWwgaXQgZnJvbSB0aGUgZnJlZWluZyBwcm9jZXNzCgkJ ICogb3IganVzdCBpZ25vcmUgKi8KCX0KfQp1bmxvY2sobHJ1X2xvY2spCgpXV19NVVRFWF9MT0NL X0VORDsKCgpBbHNvIEkgdGhpbmsgaWYgd2UgYWxsb3cgdGhpcyB3ZSBjb3VsZCBwZXJoYXBzIHVz ZSB0aGlzIHRvIGltcGxlbWVudCB0aGUKbW9kZXNldCBtYWNyb3MgdG9vLgotRGFuaWVsCgoKCgo+ ID4gVGhpcyBpcyBraW5kYSB3aGF0IHdlIHdlbnQgd2l0aCBmb3IgbW9kZXNldCBsb2NrcyB3aXRo Cj4gPiBEUk1fTU9ERVNFVF9MT0NLX0FMTF9CRUdJTi9FTkQsIHlvdSBjYW4gZ3JhYiBtb3JlIGxv Y2tzIGluIGJldHdlZW4gdGhlCj4gPiBwYWlyIGF0IGxlYXN0LiBCdXQgaXQncyBhIGxvdCBtb3Jl IGxpbWl0ZWQgdXNlLWNhc2VzLCBtYXliZSB0b28gZnJhZ2lsZSBhbgo+ID4gaWRlYSBmb3Igd3df bXV0ZXggaW4gZnVsbCBnZW5lcmFsaXR5Lgo+ID4KPiA+IE5vdCBnb2luZyB0byB0eXBlIHRoaXMg b3V0IGJlY2F1c2UgdG9vIG11Y2ggdy9lIG1vZGUgaGVyZSBhbHJlYWR5LCBidXQgSQo+ID4gY2Fu IGdpdmUgaXQgYSBzdGFiIG5leHQgd2Vlay4KPiA+IC1EYW5pZWwKPgo+IF9fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCj4gZHJpLWRldmVsIG1haWxpbmcgbGlz dAo+IGRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKPiBodHRwczovL2xpc3RzLmZyZWVk ZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAoKCgotLSAKRGFuaWVsIFZldHRl cgpTb2Z0d2FyZSBFbmdpbmVlciwgSW50ZWwgQ29ycG9yYXRpb24KKzQxICgwKSA3OSAzNjUgNTcg NDggLSBodHRwOi8vYmxvZy5mZndsbC5jaApfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fXwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5m cmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0 aW5mby9kcmktZGV2ZWw=