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=-2.0 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=no 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 1EE57CA9EB9 for ; Tue, 22 Oct 2019 07:57:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D66C221872 for ; Tue, 22 Oct 2019 07:57:42 +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="CBb48fDU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387614AbfJVH5m (ORCPT ); Tue, 22 Oct 2019 03:57:42 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:50190 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387999AbfJVH5l (ORCPT ); Tue, 22 Oct 2019 03:57:41 -0400 Received: by mail-wm1-f65.google.com with SMTP id q13so5964623wmj.0 for ; Tue, 22 Oct 2019 00:57:38 -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=ROh4rdNDqXOhRRdO284KPkGzZyY++utv+oGYDMQe5MU=; b=CBb48fDUyTRQMv9HvwoxGfLenOC40zL3DrVPS/y/X0lpnxGaEbBd6CvNglLC88n0nm H2S3nHw5RAiDUKsFcOCAo16yGxKfcB3KblwNeRUSbQpswczeghaDIjPJmbnOPri9UZGo 0xkMKv5HA2iYR4s8pU8+gACjEJj2rhE47sB+o= 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=ROh4rdNDqXOhRRdO284KPkGzZyY++utv+oGYDMQe5MU=; b=uYaxGrdklnYeUiNTJYNm/vWni+BcXf0MBgUvpspeRCozu0I2g2nVIoOUgnqh3KtXNp kPys/oTzuTDGvGcSIw/ce3vAZ09ptIlbbunheuf4XxLCZ6BIlmHmThQOoJfn2RutC3ET W5rzwzbrJQsdQPuApTaMSEmot+DxNtVUQ7O6EXWlQtGSq5DStnZvsHGeENULnoh2aOTT FMIcHSu8VkLrrcBmbk9tr+CXT4WJDyrwAO6jdFx2AdaX+2KPMjUOsGenbGt0KfCffCxd EWpUGbbP0TWrnbGImOZi66eB0O4g3LZnD8VhNkMiaPyPU32284AAegnDKnuJ4khqj+DV sTlw== X-Gm-Message-State: APjAAAXtEFop7Pgm5FRYeHXbKNC97KHS1OY+wyio98Qjnoxr2T4JuVF1 N3X8hW5xEvQw+h/xNulcI/tq1w== X-Google-Smtp-Source: APXvYqzKrxZLRkZGIn/j/6GXzN01h0XlQ1NZaDTvcyCGyqNp2p/Kw3f/rv9PyApcC7hMNit/dkHghw== X-Received: by 2002:a7b:c3c8:: with SMTP id t8mr1558153wmj.87.1571731058043; Tue, 22 Oct 2019 00:57:38 -0700 (PDT) Received: from phenom.ffwll.local (212-51-149-96.fiber7.init7.net. [212.51.149.96]) by smtp.gmail.com with ESMTPSA id p7sm16093245wma.34.2019.10.22.00.57.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Oct 2019 00:57:37 -0700 (PDT) Date: Tue, 22 Oct 2019 09:57:35 +0200 From: Daniel Vetter To: Jason Gunthorpe Cc: "Koenig, Christian" , Andrea Arcangeli , "Yang, Philip" , Ralph Campbell , "linux-rdma@vger.kernel.org" , John Hubbard , "Kuehling, Felix" , "amd-gfx@lists.freedesktop.org" , "linux-mm@kvack.org" , Jerome Glisse , "dri-devel@lists.freedesktop.org" , Ben Skeggs Subject: Re: [PATCH hmm 00/15] Consolidate the mmu notifier interval_tree and locking Message-ID: <20191022075735.GV11828@phenom.ffwll.local> Mail-Followup-To: Jason Gunthorpe , "Koenig, Christian" , Andrea Arcangeli , "Yang, Philip" , Ralph Campbell , "linux-rdma@vger.kernel.org" , John Hubbard , "Kuehling, Felix" , "amd-gfx@lists.freedesktop.org" , "linux-mm@kvack.org" , Jerome Glisse , "dri-devel@lists.freedesktop.org" , Ben Skeggs References: <20191016160444.GB3430@mellanox.com> <2df298e2-ee91-ef40-5da9-2bc1af3a17be@gmail.com> <2046e0b4-ba05-0683-5804-e9bbf903658d@amd.com> <20191018203608.GA5670@mellanox.com> <20191021135744.GA25164@mellanox.com> <20191021151221.GC25164@mellanox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20191021151221.GC25164@mellanox.com> X-Operating-System: Linux phenom 5.2.0-2-amd64 User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org On Mon, Oct 21, 2019 at 03:12:26PM +0000, Jason Gunthorpe wrote: > On Mon, Oct 21, 2019 at 02:28:46PM +0000, Koenig, Christian wrote: > > Am 21.10.19 um 15:57 schrieb Jason Gunthorpe: > > > On Sun, Oct 20, 2019 at 02:21:42PM +0000, Koenig, Christian wrote: > > >> Am 18.10.19 um 22:36 schrieb Jason Gunthorpe: > > >>> On Thu, Oct 17, 2019 at 04:47:20PM +0000, Koenig, Christian wrote: > > >>> [SNIP] > > >>> > > >>>> So again how are they serialized? > > >>> The 'driver lock' thing does it, read the hmm documentation, the hmm > > >>> approach is basically the only approach that was correct of all the > > >>> drivers.. > > >> Well that's what I've did, but what HMM does still doesn't looks correct > > >> to me. > > > It has a bug, but the basic flow seems to work. > > > > > > https://patchwork.kernel.org/patch/11191 > > > > Maybe wrong link? That link looks like an unrelated discussion on kernel > > image relocation. > > Sorry, it got corrupted: > > https://patchwork.kernel.org/patch/11191397/ > > > >>> So long as the 'driver lock' is held the range cannot become > > >>> invalidated as the 'driver lock' prevents progress of invalidation. > > >> Correct, but the problem is it doesn't wait for ongoing operations to > > >> complete. > > >> > > >> See I'm talking about the following case: > > >> > > >> Thread A    Thread B > > >> invalidate_range_start() > > >> mmu_range_read_begin() > > >> get_user_pages()/hmm_range_fault() > > >> grab_driver_lock() > > >> Updating the ptes > > >> invalidate_range_end() > > >> > > >> As far as I can see in invalidate_range_start() the driver lock is taken > > >> to make sure that we can't start any invalidation while the driver is > > >> using the pages for a command submission. > > > Again, this uses the seqlock like scheme *and* the driver lock. > > > > > > In this case after grab_driver_lock() mmu_range_read_retry() will > > > return false if Thread A has progressed to 'updating the ptes. > > > > > > For instance here is how the concurrency resolves for retry: > > > > > > CPU1 CPU2 > > > seq = mmu_range_read_begin() > > > invalidate_range_start() > > > invalidate_seq++ > > > > How that was order was what confusing me. But I've read up on the code > > in mmu_range_read_begin() and found the lines I was looking for: > > > > +    if (is_invalidating) > > +        wait_event(mmn_mm->wq, > > +               READ_ONCE(mmn_mm->invalidate_seq) != seq); > > > > [SNIP] > > Right, the basic design is that the 'seq' returned by > mmu_range_read_begin() is never currently under invalidation. > > Thus if the starting seq is not invalidating, then if it doesn't > change we are guaranteed the ptes haven't changed either. > > > > For the above I've simplified the mechanics of the invalidate_seq, you > > > need to look through the patch to see how it actually works. > > > > Yea, that you also allow multiple write sides is pretty neat. > > Complicated, but necessary to make the non-blocking OOM stuff able to > read the interval tree under all conditions :\ > > > > One of the motivations for this work is to squash that bug by adding a > > > seqlock like pattern. But the basic hmm flow and collision-retry > > > approach seems sound. > > > > > > Do you see a problem with this patch? > > > > No, not any more. > > Okay, great, thanks > > > Essentially you are doing the same thing I've tried to do with the > > original amdgpu implementation. The difference is that you don't try to > > use a per range sequence (which is a good idea, we never got that fully > > working) and you allow multiple writers at the same time. > > Yes, ODP had the per-range sequence and it never worked right > either. Keeping track of things during the invalidate_end was too complex > > > Feel free to stitch an Acked-by: Christian König > > on patch #2, > > Thanks! Can you also take some review and test for the AMD related > patches? These were quite hard to make, it is very likely I've made an > error.. > > > but you still doing a bunch of things in there which are way beyond > > my understanding (e.g. where are all the SMP barriers?). > > The only non-locked data is 'struct mmu_range_notifier->invalidate_seq' > > On the write side it uses a WRITE_ONCE. The 'seq' it writes is > generated under the mmn_mm->lock spinlock (held before and after the > WRITE_ONCE) such that all concurrent WRITE_ONCE's are storing the same > value. > > Essentially the spinlock is providing the barrier to order write: > > invalidate_range_start(): > spin_lock(&mmn_mm->lock); > mmn_mm->active_invalidate_ranges++; > mmn_mm->invalidate_seq |= 1; > *seq = mmn_mm->invalidate_seq; > spin_unlock(&mmn_mm->lock); > > WRITE_ONCE(mrn->invalidate_seq, cur_seq); > > invalidate_range_end() > spin_lock(&mmn_mm->lock); > if (--mmn_mm->active_invalidate_ranges) > mmn_mm->invalidate_seq++ > spin_unlock(&mmn_mm->lock); > > ie when we do invalidate_seq++, due to the active_invalidate_ranges > counter and the spinlock, we know all other WRITE_ONCE's have passed > their spin_unlock and no concurrent ones are starting. The spinlock is > providing the barrier here. > > On the read side.. It is a similar argument, except with the > driver_lock: > > mmu_range_read_begin() > seq = READ_ONCE(mrn->invalidate_seq); > > Here 'seq' may be the current value, or it may be an older > value. Ordering is eventually provided by the driver_lock: > > mn_tree_invalidate_start() > [..] > WRITE_ONCE(mrn->invalidate_seq, cur_seq); > driver_lock() > driver_unlock() > > vs > driver_lock() > mmu_range_read_begin() > return seq != READ_ONCE(mrn->invalidate_seq); > driver_unlock() > > Here if mn_tree_invalidate_start() has passed driver_unlock() then > because we do driver_lock() before mmu_range_read_begin() we must > observe the WRITE_ONCE. ie the driver_unlock()/driver_lock() provide > the pair'd barrier. > > If mn_tree_invalidate_start() has not passed driver_lock() then the > mmu_range_read_begin() side prevents it from passing driver_lock() > while it holds the lock. In this case it is OK if we don't observe the > WRITE_ONCE() that was done just before as the invalidate_start() > thread can't proceed to invalidation. > > It is very unusual locking, it would be great if others could help > look at it! > > The unusual bit in all of this is using a lock's critical region to > 'protect' data for read, but updating that same data before the lock's > critical secion. ie relying on the unlock barrier to 'release' program > ordered stores done before the lock's own critical region, and the > lock side barrier to 'acquire' those stores. I think this unusual use of locks as barriers for other unlocked accesses deserves comments even more than just normal barriers. Can you pls add them? I think the design seeems sound ... Also the comment on the driver's lock hopefully prevents driver maintainers from moving the driver_lock around in a way that would very subtle break the scheme, so I think having the acquire barrier commented in each place would be really good. Cheers, Daniel > > This approach is borrowed from the hmm mirror implementation.. > > If for some reason the scheme doesn't work, then the fallback is to > expand the mmn_mm->lock spinlock to protect the mrn->invalidate_seq at > some cost in performance. > > Jason > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: Re: [PATCH hmm 00/15] Consolidate the mmu notifier interval_tree and locking Date: Tue, 22 Oct 2019 09:57:35 +0200 Message-ID: <20191022075735.GV11828@phenom.ffwll.local> References: <20191016160444.GB3430@mellanox.com> <2df298e2-ee91-ef40-5da9-2bc1af3a17be@gmail.com> <2046e0b4-ba05-0683-5804-e9bbf903658d@amd.com> <20191018203608.GA5670@mellanox.com> <20191021135744.GA25164@mellanox.com> <20191021151221.GC25164@mellanox.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Content-Disposition: inline In-Reply-To: <20191021151221.GC25164-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: amd-gfx-bounces-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org Sender: "amd-gfx" To: Jason Gunthorpe Cc: Andrea Arcangeli , "Yang, Philip" , Ralph Campbell , "linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" , John Hubbard , "Kuehling, Felix" , "amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org" , "linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org" , Jerome Glisse , "dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org" , "Koenig, Christian" , Ben Skeggs List-Id: dri-devel@lists.freedesktop.org T24gTW9uLCBPY3QgMjEsIDIwMTkgYXQgMDM6MTI6MjZQTSArMDAwMCwgSmFzb24gR3VudGhvcnBl IHdyb3RlOgo+IE9uIE1vbiwgT2N0IDIxLCAyMDE5IGF0IDAyOjI4OjQ2UE0gKzAwMDAsIEtvZW5p ZywgQ2hyaXN0aWFuIHdyb3RlOgo+ID4gQW0gMjEuMTAuMTkgdW0gMTU6NTcgc2NocmllYiBKYXNv biBHdW50aG9ycGU6Cj4gPiA+IE9uIFN1biwgT2N0IDIwLCAyMDE5IGF0IDAyOjIxOjQyUE0gKzAw MDAsIEtvZW5pZywgQ2hyaXN0aWFuIHdyb3RlOgo+ID4gPj4gQW0gMTguMTAuMTkgdW0gMjI6MzYg c2NocmllYiBKYXNvbiBHdW50aG9ycGU6Cj4gPiA+Pj4gT24gVGh1LCBPY3QgMTcsIDIwMTkgYXQg MDQ6NDc6MjBQTSArMDAwMCwgS29lbmlnLCBDaHJpc3RpYW4gd3JvdGU6Cj4gPiA+Pj4gW1NOSVBd Cj4gPiA+Pj4gICAgCj4gPiA+Pj4+IFNvIGFnYWluIGhvdyBhcmUgdGhleSBzZXJpYWxpemVkPwo+ ID4gPj4+IFRoZSAnZHJpdmVyIGxvY2snIHRoaW5nIGRvZXMgaXQsIHJlYWQgdGhlIGhtbSBkb2N1 bWVudGF0aW9uLCB0aGUgaG1tCj4gPiA+Pj4gYXBwcm9hY2ggaXMgYmFzaWNhbGx5IHRoZSBvbmx5 IGFwcHJvYWNoIHRoYXQgd2FzIGNvcnJlY3Qgb2YgYWxsIHRoZQo+ID4gPj4+IGRyaXZlcnMuLgo+ ID4gPj4gV2VsbCB0aGF0J3Mgd2hhdCBJJ3ZlIGRpZCwgYnV0IHdoYXQgSE1NIGRvZXMgc3RpbGwg ZG9lc24ndCBsb29rcyBjb3JyZWN0Cj4gPiA+PiB0byBtZS4KPiA+ID4gSXQgaGFzIGEgYnVnLCBi dXQgdGhlIGJhc2ljIGZsb3cgc2VlbXMgdG8gd29yay4KPiA+ID4KPiA+ID4gaHR0cHM6Ly9wYXRj aHdvcmsua2VybmVsLm9yZy9wYXRjaC8xMTE5MQo+ID4gCj4gPiBNYXliZSB3cm9uZyBsaW5rPyBU aGF0IGxpbmsgbG9va3MgbGlrZSBhbiB1bnJlbGF0ZWQgZGlzY3Vzc2lvbiBvbiBrZXJuZWwgCj4g PiBpbWFnZSByZWxvY2F0aW9uLgo+IAo+IFNvcnJ5LCBpdCBnb3QgY29ycnVwdGVkOgo+IAo+IGh0 dHBzOi8vcGF0Y2h3b3JrLmtlcm5lbC5vcmcvcGF0Y2gvMTExOTEzOTcvCj4gCj4gPiA+Pj4gU28g bG9uZyBhcyB0aGUgJ2RyaXZlciBsb2NrJyBpcyBoZWxkIHRoZSByYW5nZSBjYW5ub3QgYmVjb21l Cj4gPiA+Pj4gaW52YWxpZGF0ZWQgYXMgdGhlICdkcml2ZXIgbG9jaycgcHJldmVudHMgcHJvZ3Jl c3Mgb2YgaW52YWxpZGF0aW9uLgo+ID4gPj4gQ29ycmVjdCwgYnV0IHRoZSBwcm9ibGVtIGlzIGl0 IGRvZXNuJ3Qgd2FpdCBmb3Igb25nb2luZyBvcGVyYXRpb25zIHRvCj4gPiA+PiBjb21wbGV0ZS4K PiA+ID4+Cj4gPiA+PiBTZWUgSSdtIHRhbGtpbmcgYWJvdXQgdGhlIGZvbGxvd2luZyBjYXNlOgo+ ID4gPj4KPiA+ID4+IFRocmVhZCBBwqDCoMKgIFRocmVhZCBCCj4gPiA+PiBpbnZhbGlkYXRlX3Jh bmdlX3N0YXJ0KCkKPiA+ID4+ICAgICAgICAgICAgICAgICAgICAgICBtbXVfcmFuZ2VfcmVhZF9i ZWdpbigpCj4gPiA+PiAgICAgICAgICAgICAgICAgICAgICAgZ2V0X3VzZXJfcGFnZXMoKS9obW1f cmFuZ2VfZmF1bHQoKQo+ID4gPj4gICAgICAgICAgICAgICAgICAgICAgIGdyYWJfZHJpdmVyX2xv Y2soKQo+ID4gPj4gVXBkYXRpbmcgdGhlIHB0ZXMKPiA+ID4+IGludmFsaWRhdGVfcmFuZ2VfZW5k KCkKPiA+ID4+Cj4gPiA+PiBBcyBmYXIgYXMgSSBjYW4gc2VlIGluIGludmFsaWRhdGVfcmFuZ2Vf c3RhcnQoKSB0aGUgZHJpdmVyIGxvY2sgaXMgdGFrZW4KPiA+ID4+IHRvIG1ha2Ugc3VyZSB0aGF0 IHdlIGNhbid0IHN0YXJ0IGFueSBpbnZhbGlkYXRpb24gd2hpbGUgdGhlIGRyaXZlciBpcwo+ID4g Pj4gdXNpbmcgdGhlIHBhZ2VzIGZvciBhIGNvbW1hbmQgc3VibWlzc2lvbi4KPiA+ID4gQWdhaW4s IHRoaXMgdXNlcyB0aGUgc2VxbG9jayBsaWtlIHNjaGVtZSAqYW5kKiB0aGUgZHJpdmVyIGxvY2su Cj4gPiA+Cj4gPiA+IEluIHRoaXMgY2FzZSBhZnRlciBncmFiX2RyaXZlcl9sb2NrKCkgbW11X3Jh bmdlX3JlYWRfcmV0cnkoKSB3aWxsCj4gPiA+IHJldHVybiBmYWxzZSBpZiBUaHJlYWQgQSBoYXMg cHJvZ3Jlc3NlZCB0byAndXBkYXRpbmcgdGhlIHB0ZXMuCj4gPiA+Cj4gPiA+IEZvciBpbnN0YW5j ZSBoZXJlIGlzIGhvdyB0aGUgY29uY3VycmVuY3kgcmVzb2x2ZXMgZm9yIHJldHJ5Ogo+ID4gPgo+ ID4gPiAgICAgICAgIENQVTEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENQVTIKPiA+ ID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXEgPSBtbXVfcmFuZ2VfcmVh ZF9iZWdpbigpCj4gPiA+IGludmFsaWRhdGVfcmFuZ2Vfc3RhcnQoKQo+ID4gPiAgICBpbnZhbGlk YXRlX3NlcSsrCj4gPiAKPiA+IEhvdyB0aGF0IHdhcyBvcmRlciB3YXMgd2hhdCBjb25mdXNpbmcg bWUuIEJ1dCBJJ3ZlIHJlYWQgdXAgb24gdGhlIGNvZGUgCj4gPiBpbiBtbXVfcmFuZ2VfcmVhZF9i ZWdpbigpIGFuZCBmb3VuZCB0aGUgbGluZXMgSSB3YXMgbG9va2luZyBmb3I6Cj4gPiAKPiA+ICvC oMKgwqAgaWYgKGlzX2ludmFsaWRhdGluZykKPiA+ICvCoMKgwqAgwqDCoMKgIHdhaXRfZXZlbnQo bW1uX21tLT53cSwKPiA+ICvCoMKgwqAgwqDCoMKgIMKgwqDCoCDCoMKgIFJFQURfT05DRShtbW5f bW0tPmludmFsaWRhdGVfc2VxKSAhPSBzZXEpOwo+ID4gCj4gPiBbU05JUF0KPiAKPiBSaWdodCwg dGhlIGJhc2ljIGRlc2lnbiBpcyB0aGF0IHRoZSAnc2VxJyByZXR1cm5lZCBieQo+IG1tdV9yYW5n ZV9yZWFkX2JlZ2luKCkgaXMgbmV2ZXIgY3VycmVudGx5IHVuZGVyIGludmFsaWRhdGlvbi4KPiAK PiBUaHVzIGlmIHRoZSBzdGFydGluZyBzZXEgaXMgbm90IGludmFsaWRhdGluZywgdGhlbiBpZiBp dCBkb2Vzbid0Cj4gY2hhbmdlIHdlIGFyZSBndWFyYW50ZWVkIHRoZSBwdGVzIGhhdmVuJ3QgY2hh bmdlZCBlaXRoZXIuCj4gCj4gPiA+IEZvciB0aGUgYWJvdmUgSSd2ZSBzaW1wbGlmaWVkIHRoZSBt ZWNoYW5pY3Mgb2YgdGhlIGludmFsaWRhdGVfc2VxLCB5b3UKPiA+ID4gbmVlZCB0byBsb29rIHRo cm91Z2ggdGhlIHBhdGNoIHRvIHNlZSBob3cgaXQgYWN0dWFsbHkgd29ya3MuCj4gPiAKPiA+IFll YSwgdGhhdCB5b3UgYWxzbyBhbGxvdyBtdWx0aXBsZSB3cml0ZSBzaWRlcyBpcyBwcmV0dHkgbmVh dC4KPiAKPiBDb21wbGljYXRlZCwgYnV0IG5lY2Vzc2FyeSB0byBtYWtlIHRoZSBub24tYmxvY2tp bmcgT09NIHN0dWZmIGFibGUgdG8KPiByZWFkIHRoZSBpbnRlcnZhbCB0cmVlIHVuZGVyIGFsbCBj b25kaXRpb25zIDpcCj4gCj4gPiA+IE9uZSBvZiB0aGUgbW90aXZhdGlvbnMgZm9yIHRoaXMgd29y ayBpcyB0byBzcXVhc2ggdGhhdCBidWcgYnkgYWRkaW5nIGEKPiA+ID4gc2VxbG9jayBsaWtlIHBh dHRlcm4uIEJ1dCB0aGUgYmFzaWMgaG1tIGZsb3cgYW5kIGNvbGxpc2lvbi1yZXRyeQo+ID4gPiBh cHByb2FjaCBzZWVtcyBzb3VuZC4KPiA+ID4KPiA+ID4gRG8geW91IHNlZSBhIHByb2JsZW0gd2l0 aCB0aGlzIHBhdGNoPwo+ID4gCj4gPiBObywgbm90IGFueSBtb3JlLgo+IAo+IE9rYXksIGdyZWF0 LCB0aGFua3MKPiAgCj4gPiBFc3NlbnRpYWxseSB5b3UgYXJlIGRvaW5nIHRoZSBzYW1lIHRoaW5n IEkndmUgdHJpZWQgdG8gZG8gd2l0aCB0aGUgCj4gPiBvcmlnaW5hbCBhbWRncHUgaW1wbGVtZW50 YXRpb24uIFRoZSBkaWZmZXJlbmNlIGlzIHRoYXQgeW91IGRvbid0IHRyeSB0byAKPiA+IHVzZSBh IHBlciByYW5nZSBzZXF1ZW5jZSAod2hpY2ggaXMgYSBnb29kIGlkZWEsIHdlIG5ldmVyIGdvdCB0 aGF0IGZ1bGx5IAo+ID4gd29ya2luZykgYW5kIHlvdSBhbGxvdyBtdWx0aXBsZSB3cml0ZXJzIGF0 IHRoZSBzYW1lIHRpbWUuCj4gCj4gWWVzLCBPRFAgaGFkIHRoZSBwZXItcmFuZ2Ugc2VxdWVuY2Ug YW5kIGl0IG5ldmVyIHdvcmtlZCByaWdodAo+IGVpdGhlci4gS2VlcGluZyB0cmFjayBvZiB0aGlu Z3MgZHVyaW5nIHRoZSBpbnZhbGlkYXRlX2VuZCB3YXMgdG9vIGNvbXBsZXgKPiAgCj4gPiBGZWVs IGZyZWUgdG8gc3RpdGNoIGFuIEFja2VkLWJ5OiBDaHJpc3RpYW4gS8O2bmlnIAo+ID4gPGNocmlz dGlhbi5rb2VuaWdAYW1kLmNvbT4gb24gcGF0Y2ggIzIsCj4gCj4gVGhhbmtzISBDYW4geW91IGFs c28gdGFrZSBzb21lIHJldmlldyBhbmQgdGVzdCBmb3IgdGhlIEFNRCByZWxhdGVkCj4gcGF0Y2hl cz8gVGhlc2Ugd2VyZSBxdWl0ZSBoYXJkIHRvIG1ha2UsIGl0IGlzIHZlcnkgbGlrZWx5IEkndmUg bWFkZSBhbgo+IGVycm9yLi4KPiAKPiA+IGJ1dCB5b3Ugc3RpbGwgZG9pbmcgYSBidW5jaCBvZiB0 aGluZ3MgaW4gdGhlcmUgd2hpY2ggYXJlIHdheSBiZXlvbmQKPiA+IG15IHVuZGVyc3RhbmRpbmcg KGUuZy4gd2hlcmUgYXJlIGFsbCB0aGUgU01QIGJhcnJpZXJzPykuCj4gCj4gVGhlIG9ubHkgbm9u LWxvY2tlZCBkYXRhIGlzICdzdHJ1Y3QgbW11X3JhbmdlX25vdGlmaWVyLT5pbnZhbGlkYXRlX3Nl cScKPiAKPiBPbiB0aGUgd3JpdGUgc2lkZSBpdCB1c2VzIGEgV1JJVEVfT05DRS4gVGhlICdzZXEn IGl0IHdyaXRlcyBpcwo+IGdlbmVyYXRlZCB1bmRlciB0aGUgbW1uX21tLT5sb2NrIHNwaW5sb2Nr IChoZWxkIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlCj4gV1JJVEVfT05DRSkgc3VjaCB0aGF0IGFsbCBj b25jdXJyZW50IFdSSVRFX09OQ0UncyBhcmUgc3RvcmluZyB0aGUgc2FtZQo+IHZhbHVlLiAKPiAK PiBFc3NlbnRpYWxseSB0aGUgc3BpbmxvY2sgaXMgcHJvdmlkaW5nIHRoZSBiYXJyaWVyIHRvIG9y ZGVyIHdyaXRlOgo+IAo+IGludmFsaWRhdGVfcmFuZ2Vfc3RhcnQoKToKPiAgc3Bpbl9sb2NrKCZt bW5fbW0tPmxvY2spOwo+ICBtbW5fbW0tPmFjdGl2ZV9pbnZhbGlkYXRlX3JhbmdlcysrOwo+ICBt bW5fbW0tPmludmFsaWRhdGVfc2VxIHw9IDE7Cj4gICpzZXEgPSBtbW5fbW0tPmludmFsaWRhdGVf c2VxOwo+ICBzcGluX3VubG9jaygmbW1uX21tLT5sb2NrKTsKPiAKPiAgV1JJVEVfT05DRShtcm4t PmludmFsaWRhdGVfc2VxLCBjdXJfc2VxKTsKPiAKPiBpbnZhbGlkYXRlX3JhbmdlX2VuZCgpCj4g IHNwaW5fbG9jaygmbW1uX21tLT5sb2NrKTsKPiAgaWYgKC0tbW1uX21tLT5hY3RpdmVfaW52YWxp ZGF0ZV9yYW5nZXMpCj4gICAgIG1tbl9tbS0+aW52YWxpZGF0ZV9zZXErKwo+ICBzcGluX3VubG9j aygmbW1uX21tLT5sb2NrKTsKPiAKPiBpZSB3aGVuIHdlIGRvIGludmFsaWRhdGVfc2VxKyssIGR1 ZSB0byB0aGUgYWN0aXZlX2ludmFsaWRhdGVfcmFuZ2VzCj4gY291bnRlciBhbmQgdGhlIHNwaW5s b2NrLCB3ZSBrbm93IGFsbCBvdGhlciBXUklURV9PTkNFJ3MgaGF2ZSBwYXNzZWQKPiB0aGVpciBz cGluX3VubG9jayBhbmQgbm8gY29uY3VycmVudCBvbmVzIGFyZSBzdGFydGluZy4gVGhlIHNwaW5s b2NrIGlzCj4gcHJvdmlkaW5nIHRoZSBiYXJyaWVyIGhlcmUuCj4gCj4gT24gdGhlIHJlYWQgc2lk ZS4uIEl0IGlzIGEgc2ltaWxhciBhcmd1bWVudCwgZXhjZXB0IHdpdGggdGhlCj4gZHJpdmVyX2xv Y2s6Cj4gCj4gbW11X3JhbmdlX3JlYWRfYmVnaW4oKQo+ICAgc2VxID0gUkVBRF9PTkNFKG1ybi0+ aW52YWxpZGF0ZV9zZXEpOwo+IAo+IEhlcmUgJ3NlcScgbWF5IGJlIHRoZSBjdXJyZW50IHZhbHVl LCBvciBpdCBtYXkgYmUgYW4gb2xkZXIKPiB2YWx1ZS4gT3JkZXJpbmcgaXMgZXZlbnR1YWxseSBw cm92aWRlZCBieSB0aGUgZHJpdmVyX2xvY2s6Cj4gCj4gbW5fdHJlZV9pbnZhbGlkYXRlX3N0YXJ0 KCkKPiAgWy4uXQo+ICBXUklURV9PTkNFKG1ybi0+aW52YWxpZGF0ZV9zZXEsIGN1cl9zZXEpOwo+ ICBkcml2ZXJfbG9jaygpCj4gIGRyaXZlcl91bmxvY2soKQo+IAo+IHZzCj4gIGRyaXZlcl9sb2Nr KCkKPiAgICBtbXVfcmFuZ2VfcmVhZF9iZWdpbigpCj4gICAgICByZXR1cm4gc2VxICE9IFJFQURf T05DRShtcm4tPmludmFsaWRhdGVfc2VxKTsKPiAgZHJpdmVyX3VubG9jaygpCj4gCj4gSGVyZSBp ZiBtbl90cmVlX2ludmFsaWRhdGVfc3RhcnQoKSBoYXMgcGFzc2VkIGRyaXZlcl91bmxvY2soKSB0 aGVuCj4gYmVjYXVzZSB3ZSBkbyBkcml2ZXJfbG9jaygpIGJlZm9yZSBtbXVfcmFuZ2VfcmVhZF9i ZWdpbigpIHdlIG11c3QKPiBvYnNlcnZlIHRoZSBXUklURV9PTkNFLiBpZSB0aGUgZHJpdmVyX3Vu bG9jaygpL2RyaXZlcl9sb2NrKCkgcHJvdmlkZQo+IHRoZSBwYWlyJ2QgYmFycmllci4KPiAKPiBJ ZiBtbl90cmVlX2ludmFsaWRhdGVfc3RhcnQoKSBoYXMgbm90IHBhc3NlZCBkcml2ZXJfbG9jaygp IHRoZW4gdGhlCj4gbW11X3JhbmdlX3JlYWRfYmVnaW4oKSBzaWRlIHByZXZlbnRzIGl0IGZyb20g cGFzc2luZyBkcml2ZXJfbG9jaygpCj4gd2hpbGUgaXQgaG9sZHMgdGhlIGxvY2suIEluIHRoaXMg Y2FzZSBpdCBpcyBPSyBpZiB3ZSBkb24ndCBvYnNlcnZlIHRoZQo+IFdSSVRFX09OQ0UoKSB0aGF0 IHdhcyBkb25lIGp1c3QgYmVmb3JlIGFzIHRoZSBpbnZhbGlkYXRlX3N0YXJ0KCkKPiB0aHJlYWQg Y2FuJ3QgcHJvY2VlZCB0byBpbnZhbGlkYXRpb24uCj4gCj4gSXQgaXMgdmVyeSB1bnVzdWFsIGxv Y2tpbmcsIGl0IHdvdWxkIGJlIGdyZWF0IGlmIG90aGVycyBjb3VsZCBoZWxwCj4gbG9vayBhdCBp dCEKPiAKPiBUaGUgdW51c3VhbCBiaXQgaW4gYWxsIG9mIHRoaXMgaXMgdXNpbmcgYSBsb2NrJ3Mg Y3JpdGljYWwgcmVnaW9uIHRvCj4gJ3Byb3RlY3QnIGRhdGEgZm9yIHJlYWQsIGJ1dCB1cGRhdGlu ZyB0aGF0IHNhbWUgZGF0YSBiZWZvcmUgdGhlIGxvY2sncwo+IGNyaXRpY2FsIHNlY2lvbi4gaWUg cmVseWluZyBvbiB0aGUgdW5sb2NrIGJhcnJpZXIgdG8gJ3JlbGVhc2UnIHByb2dyYW0KPiBvcmRl cmVkIHN0b3JlcyBkb25lIGJlZm9yZSB0aGUgbG9jaydzIG93biBjcml0aWNhbCByZWdpb24sIGFu ZCB0aGUKPiBsb2NrIHNpZGUgYmFycmllciB0byAnYWNxdWlyZScgdGhvc2Ugc3RvcmVzLgoKSSB0 aGluayB0aGlzIHVudXN1YWwgdXNlIG9mIGxvY2tzIGFzIGJhcnJpZXJzIGZvciBvdGhlciB1bmxv Y2tlZCBhY2Nlc3NlcwpkZXNlcnZlcyBjb21tZW50cyBldmVuIG1vcmUgdGhhbiBqdXN0IG5vcm1h bCBiYXJyaWVycy4gQ2FuIHlvdSBwbHMgYWRkCnRoZW0/IEkgdGhpbmsgdGhlIGRlc2lnbiBzZWVl bXMgc291bmQgLi4uCgpBbHNvIHRoZSBjb21tZW50IG9uIHRoZSBkcml2ZXIncyBsb2NrIGhvcGVm dWxseSBwcmV2ZW50cyBkcml2ZXIKbWFpbnRhaW5lcnMgZnJvbSBtb3ZpbmcgdGhlIGRyaXZlcl9s b2NrIGFyb3VuZCBpbiBhIHdheSB0aGF0IHdvdWxkIHZlcnkKc3VidGxlIGJyZWFrIHRoZSBzY2hl bWUsIHNvIEkgdGhpbmsgaGF2aW5nIHRoZSBhY3F1aXJlIGJhcnJpZXIgY29tbWVudGVkCmluIGVh Y2ggcGxhY2Ugd291bGQgYmUgcmVhbGx5IGdvb2QuCgpDaGVlcnMsIERhbmllbAoKPiAKPiBUaGlz IGFwcHJvYWNoIGlzIGJvcnJvd2VkIGZyb20gdGhlIGhtbSBtaXJyb3IgaW1wbGVtZW50YXRpb24u Lgo+IAo+IElmIGZvciBzb21lIHJlYXNvbiB0aGUgc2NoZW1lIGRvZXNuJ3Qgd29yaywgdGhlbiB0 aGUgZmFsbGJhY2sgaXMgdG8KPiBleHBhbmQgdGhlIG1tbl9tbS0+bG9jayBzcGlubG9jayB0byBw cm90ZWN0IHRoZSBtcm4tPmludmFsaWRhdGVfc2VxIGF0Cj4gc29tZSBjb3N0IGluIHBlcmZvcm1h bmNlLgo+IAo+IEphc29uCj4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX18KPiBkcmktZGV2ZWwgbWFpbGluZyBsaXN0Cj4gZHJpLWRldmVsQGxpc3RzLmZyZWVk ZXNrdG9wLm9yZwo+IGh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGlu Zm8vZHJpLWRldmVsCgotLSAKRGFuaWVsIFZldHRlcgpTb2Z0d2FyZSBFbmdpbmVlciwgSW50ZWwg Q29ycG9yYXRpb24KaHR0cDovL2Jsb2cuZmZ3bGwuY2gKX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX18KYW1kLWdmeCBtYWlsaW5nIGxpc3QKYW1kLWdmeEBsaXN0 cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9s aXN0aW5mby9hbWQtZ2Z4