From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758108AbcAYVnC (ORCPT ); Mon, 25 Jan 2016 16:43:02 -0500 Received: from mail-wm0-f51.google.com ([74.125.82.51]:34458 "EHLO mail-wm0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756184AbcAYVm5 (ORCPT ); Mon, 25 Jan 2016 16:42:57 -0500 Subject: Re: linux-4.4 bisected: kwin5 stuck on kde5 loading screen with radeon To: =?UTF-8?B?VmlsbGUgU3lyasOkbMOk?= , =?UTF-8?Q?Michel_D=c3=a4nzer?= , Alex Deucher , Vlastimil Babka , LKML , dri-devel@lists.freedesktop.org, =?UTF-8?Q?Christian_K=c3=b6nig?= References: <56A19C98.8020208@daenzer.net> <20160122151835.GM23290@intel.com> <56A5A171.7000205@daenzer.net> <56A6203D.3030803@gmail.com> <20160125132310.GS23290@intel.com> <56A626D5.2040808@gmail.com> <20160125145309.GT23290@intel.com> <56A64F86.9080605@gmail.com> <20160125185122.GV11240@phenom.ffwll.local> <56A677C6.4050909@gmail.com> <20160125203243.GW11240@phenom.ffwll.local> From: Mario Kleiner Message-ID: <56A696DD.2000004@gmail.com> Date: Mon, 25 Jan 2016 22:42:53 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 In-Reply-To: <20160125203243.GW11240@phenom.ffwll.local> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 01/25/2016 09:32 PM, Daniel Vetter wrote: > On Mon, Jan 25, 2016 at 08:30:14PM +0100, Mario Kleiner wrote: >> >> >> On 01/25/2016 07:51 PM, Daniel Vetter wrote: >>> On Mon, Jan 25, 2016 at 05:38:30PM +0100, Mario Kleiner wrote: >>>> Readding Daniel, which somehow got dropped from the cc. >>>> >>>> On 01/25/2016 03:53 PM, Ville Syrjälä wrote: >>>>> On Mon, Jan 25, 2016 at 02:44:53PM +0100, Mario Kleiner wrote: >>>>>> >>>>>> >>>>>> On 01/25/2016 02:23 PM, Ville Syrjälä wrote: >>>>>>> On Mon, Jan 25, 2016 at 02:16:45PM +0100, Mario Kleiner wrote: >>>>>>>> >>>>>>>> >>>>>>>> On 01/25/2016 05:15 AM, Michel Dänzer wrote: >>>>>>>>> On 23.01.2016 00:18, Ville Syrjälä wrote: >>>>>>>>>> On Fri, Jan 22, 2016 at 12:06:00PM +0900, Michel Dänzer wrote: >>>>>>>>>>> >>>>>>>>>>> [ Trimming KDE folks from Cc ] >>>>>>>>>>> >>>>>>>>>>> On 21.01.2016 19:09, Daniel Vetter wrote: >>>>>>>>>>>> On Thu, Jan 21, 2016 at 05:36:46PM +0900, Michel Dänzer wrote: >>>>>>>>>>>>> On 21.01.2016 16:58, Daniel Vetter wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> Can you please point me at the vblank on/off jump bug please? >>>>>>>>>>>>> >>>>>>>>>>>>> AFAIR I originally reported it in response to >>>>>>>>>>>>> http://lists.freedesktop.org/archives/dri-devel/2015-August/087841.html >>>>>>>>>>>>> , but I can't find that in the archives, so maybe that was just on IRC. >>>>>>>>>>>>> See >>>>>>>>>>>>> http://lists.freedesktop.org/archives/dri-devel/2016-January/099122.html >>>>>>>>>>>>> . Basically, I ran into the bug fixed by your patch because the counter >>>>>>>>>>>>> jumped forward on every DPMS off, so it hit the 32-bit boundary after >>>>>>>>>>>>> just a few days. >>>>>>>>>>>> >>>>>>>>>>>> Ok, so just uncovered the overflow bug. >>>>>>>>>>> >>>>>>>>>>> Not sure what you mean by "just", but to be clear: The drm_vblank_on/off >>>>>>>>>>> counter jumping bug (similar to the bug this thread is about), which >>>>>>>>>>> exposed the overflow bug, is still alive and kicking in 4.5. It seems >>>>>>>>>>> to happen when turning off the CRTC: >>>>>>>>>>> >>>>>>>>>>> [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=218104694, diff=0, hw=916 hw_last=916 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] crtc 0: dist from vblank start 3 >>>>>>>>>>> [drm:drm_calc_vbltimestamp_from_scanoutpos] crtc 0 : v 0x7 p(2199,-45)@ 7304.307354 -> 7304.308006 [e 0 us, 0 rep] >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] crtc 0: dist from vblank start 3 >>>>>>>>>>> [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=218104694, diff=16776301, hw=1 hw_last=916 >>>>>>>>>> >>>>>>>>>> Not sure what bug we're talking about here, but here the hw counter >>>>>>>>>> clearly jumps backwards. >>>>>>>>>> >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 3 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 3 >>>>>>>>>>> [drm:drm_update_vblank_count] updating vblank count on crtc 1: current=0, diff=0, hw=0 hw_last=0 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 3 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 3 >>>>>>>>>>> [drm:drm_update_vblank_count] updating vblank count on crtc 2: current=0, diff=0, hw=0 hw_last=0 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 3 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 3 >>>>>>>>>>> [drm:drm_update_vblank_count] updating vblank count on crtc 3: current=0, diff=0, hw=0 hw_last=0 >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 1 >>>>>>>>>>> [drm:drm_calc_vbltimestamp_from_scanoutpos] crtc 0 : v 0x1 p(0,0)@ 7304.317140 -> 7304.317140 [e 0 us, 0 rep] >>>>>>>>>>> [drm:radeon_get_vblank_counter_kms] Query failed! stat 1 >>>>>>>>>>> [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=234880995, diff=16777215, hw=0 hw_last=1 >>>>>>>>>> >>>>>>>>>> Same here. >>>>>>>>> >>>>>>>>> At least one of the jumps is expected, because this is around turning >>>>>>>>> off the CRTC for DPMS off. Don't know yet why there are two jumps back >>>>>>>>> though. >>>>>>>>> >>>>>>>>> >>>>>>>>>> These things just don't happen on i915 because drm_vblank_off() and >>>>>>>>>> drm_vblank_on() are always called around the times when the hw counter >>>>>>>>>> might get reset. Or at least that's how it should be. >>>>>>>>> >>>>>>>>> Which is of course the idea of Daniel's patch (which is what I'm getting >>>>>>>>> the above with) or Mario's patch as well, but clearly something's still >>>>>>>>> wrong. It's certainly possible that it's something in the driver, but >>>>>>>>> since calling drm_vblank_pre/post_modeset from the same places seems to >>>>>>>>> work fine (ignoring the regression discussed in this thread)... Do >>>>>>>>> drm_vblank_on/off require something else to handle this correctly? >>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>>> I suspect it is because vblank_disable_and_save calls >>>>>>>> drm_update_vblank_count() unconditionally, even if vblank irqs are >>>>>>>> already off. >>>>>>>> >>>>>>>> So on a manual display disable -> reenable you get something like >>>>>>>> >>>>>>>> At disable: >>>>>>>> >>>>>>>> Call to dpms-off --> atombios_crtc_dpms(DPMS_OFF) --> drm_vblank_off -> >>>>>>>> vblank_disable_and_save -> irqs off, drm_update_vblank_count() computes >>>>>>>> final count. >>>>>>>> >>>>>>>> Then the crtc is shut down and its hw counter resets to zero. >>>>>>>> >>>>>>>> At reenable: >>>>>>>> >>>>>>>> Modesetting -> drm_crtc_helper_set_mode -> crtc_funcs->prepare(crtc) -> >>>>>>>> atombios_crtc_prepare() -> atombios_crtc_dpms(DPMS_OFF) -> >>>>>>>> drm_vblank_off -> vblank_disable_and_save -> A pointless >>>>>>>> drm_update_vblank_count() while the hw counter is already reset to zero >>>>>>>> --> Unwanted counter jump. >>>>>>>> >>>>>>>> >>>>>>>> The problem doesn't happen on a pure modeset to a different video >>>>>>>> resolution/refresh rate, as then we only have one call into >>>>>>>> atombios_crtc_dpms(DPMS_OFF). >>>>>>>> >>>>>>>> I think the fix is to fix vblank_disable_and_save() to only call >>>>>>>> drm_update_vblank_count() if vblank irqs get actually disabled, not on >>>>>>>> no-op calls. I will try that now. >>>>>>> >>>>>>> It does that on purpose. Otherwise the vblank counter would appear to >>>>>>> have stalled while the interrupt was off. >>>>>>> >>>>>> >>>>>> Ok, that's what the comments there say, although i don't see atm. why >>>>>> that perceived stall would be a big problem. I checked all callers of >>>>>> vblank_disable_and_save(). They are all careful to not call that >>>>>> function if vblanks are already disabled. The only exception is >>>>>> drm_vblank_off(). If drm_vblank_off/on is supposed to protect kms >>>>>> drivers which have resetting hw counters or other problematic behaviour >>>>>> during modesets etc. then this will break. E.g., calling the vblank >>>>>> timestamping stuff is also not safe/well-defined during modesets when >>>>>> the timestamping constants are not (yet) updated to reflect the new mode >>>>>> timing of the modeset in progress. >>>>> >>>>> The idea is to maintain the appearance that the counter ticks all the >>>>> time as long as the crtc is active. While that may not be really >>>>> required in case if no one is currently interested in the vblank >>>>> counter, I think it's a nice thing to have just to make the behaviour >>>>> of the counter consistent. >>>>> >>>>> As far as calling drm_vblank_off() after the hw counter got reset, well, >>>>> that not correct. It should be called before the reset. >>>> >>>> What radeon does is calling drm_vblank_off at beginning of DPMS_OFF. The >>>> first call to DMPS_OFF will call drm_vblank_off() and really disable >>>> vblank-irqs if they were running, updating the counts/ts a last time. But >>>> then the dpms off will reset the hw counter to zero. When one reenables the >>>> display, a second call to DPMS_OFF will now call drm_vblank_off again when >>>> it apparently shouldn't. >>>> >>>> I just tested this patch, which fixes the counter jumps on radeon-kms with >>>> my or Daniel's drm_vblank_off patches to radeon: >>> >>> This might be due to the legacy helpers, which just love to redundantly >>> disable stuff that's off already. The problem I see with no-oping these >>> out is that for atomic drivers (which really should get this right) this >>> might paper over bugs: E.g. when you forget to call _off() when disabling >>> the crtc, then calling _on() twice in a row is indeed a serious bug. >>> Similar when you forget to call _on() and have multiple _off() calls in a >>> row. >>> >>> So not sure what to do here. >>> -Daniel >>> >> >> Yes, the legacy helpers cause two calls to dpms off if one disables a >> display. First during display disable as intended. Then when one reenables >> the display during modesetting as part of crtc_funcs->prepare() - at least >> on radeon. >> >> Maybe the minimum thing that would help is to just check for >> vblank->inmodeset in drm_vblank_off(). If that would be the case we'd know >> it is a redundant call and could no-op it and do a >> WARN_ON(vblank->inmodeset)? > > I have that here locally, blows up all over the place on radoen. And also > would blow up everywhere else. > You mean the WARN_ON causes ugliness? The no-op on redundant calls to drm_vblank_off would hopefully not blow up anything but prevent blow ups? The problem is that there should not ever be a call to the drm_update_vblank_count() function once a crtc is in modeset/dpms off etc., not only because of the hw vblank counters being reset to zero, but also because vblank timestamps computed may be wrong, going backwards etc. That could again confuse clients. > I was thinking of adding the vblank->inmodeset check to radeon/amdgpu, > with a note why it's needed (legacy crtc helpers just suck). Maybe you could do that check in radeon/amdgpu, but still also leave it in drm_vblank_off()? If all kms drivers properly avoid redundant calls as part of legacy paths then the WARN_ON and no-op in drm_vblank_off should not ever trigger, unless there is a real bug, right? In which case it should hopefully prevent worse things like a hanging composited desktop, or login, and instead just make noise in the kernel log? > >> drm_vblank_on() i don't know how to treat, but that one calls >> drm_reset_vblank_timestamp() which should be less problematic if called >> redundantly. > > I think even legacy crtc helpers don't enable stuff again if it's not been > disabled before. So on drm_vblank_on() we might be able to put a WARN_ON > in place ... Hm, logging thist stuff here during modesets and display dis/enable i see lots of drm_vblank_on that come in "pairs" only about two dozen msecs apart. > >> Now the patch i want to try next to fix the drm_vblank_pre/post_modeset >> regression in Linux 4.4/4.5 is to add a ... >> >> if ((diff > 1) && vblank->inmodeset) diff = 1; >> >> ... to the bottom of drm_update_vblank_count(). That should hopefully >> restore the pre/post_modeset behavior as close to the original behavior as >> possible. As a side effect it would also prevent the counter jump caused by >> redundant calls to drm_vblank_off(). > > Hm, can we just frob pre/post_modeset only with some checks? I'd like to > not put that kind of "I have no idea about my hw state" hacks into the new > helpers. Otherwise not even atomic drivers can start to gain WARN_ONs to > enforce correct usage, which would be a real bummer imo. > -Daniel > We could check for only (vblank->inmodeset & 0x2) to only apply it to the legacy pre/post path, trusting that the drm_vblank_off/on path will be made robust in a different way, e.g., by the stuff discussed above and careful implementation in each kms driver that uses those. Atm. radeon doesn't use off/on, so your enablement patch set can make sure it does the right thing from the beginning. rockchip-kms may need similar treatment to radeon to avoid redundant calls. Btw. how the patch to drm_update_vblank_count() close to the bottom would actually look is more like: if ((diff > 1) && ((vblank->inmodeset & 0x2) || (flags & DRM_CALLED_FROM_VBLIRQ))) diff = 1; Another problem we have is that the implementation of the vblank timestamp doublebuffer with our custom sequence locking is only save against concurrent readers as long as the increment for store_vblank() is +1, ie. diff = 1 in that code. Other diff values like 2 would cause us to write to the other timestamp slot that is potentially read by some concurrent readers at the same time and they would get corrupted timestamps. Now outside vblank irq drm_update_vblank_count() is only supposed to be called while there aren't any concurrent readers ie., vblank->refcount == 0, and the way drm_vblank_on/off are implemented this seems to be the case, so anything goes. if called from drm_handle_vblank() aka (flags & DRM_CALLED_FROM_VBLIRQ), we have to assume that there are concurrent readers, because vblank irqs are usually only kept active if vblank->refcount is > 0. This means only +1 increments are allowed. In the past this was always the case, but with the new implementation since Linux 4.4, it could happen that we get diff > 1 if the vblank irq gets deferred by more than 1 video refresh cycle, e.g., due to long irq off periods, maybe preemption on a RT_PREEMPT kernel, long held locks, firmware triggered SMI's etc. That would cause bad corruption of timestamps. So unless or until we also rewrite the timestamp caching, we need that extra protection against diff > 1 in vblank irq. -mario From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mario Kleiner Subject: Re: linux-4.4 bisected: kwin5 stuck on kde5 loading screen with radeon Date: Mon, 25 Jan 2016 22:42:53 +0100 Message-ID: <56A696DD.2000004@gmail.com> References: <56A19C98.8020208@daenzer.net> <20160122151835.GM23290@intel.com> <56A5A171.7000205@daenzer.net> <56A6203D.3030803@gmail.com> <20160125132310.GS23290@intel.com> <56A626D5.2040808@gmail.com> <20160125145309.GT23290@intel.com> <56A64F86.9080605@gmail.com> <20160125185122.GV11240@phenom.ffwll.local> <56A677C6.4050909@gmail.com> <20160125203243.GW11240@phenom.ffwll.local> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from mail-wm0-f46.google.com (mail-wm0-f46.google.com [74.125.82.46]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0609A6E179 for ; Mon, 25 Jan 2016 13:42:58 -0800 (PST) Received: by mail-wm0-f46.google.com with SMTP id l65so81437062wmf.1 for ; Mon, 25 Jan 2016 13:42:57 -0800 (PST) In-Reply-To: <20160125203243.GW11240@phenom.ffwll.local> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: =?UTF-8?B?VmlsbGUgU3lyasOkbMOk?= , =?UTF-8?Q?Michel_D=c3=a4nzer?= , Alex Deucher , Vlastimil Babka , LKML , dri-devel@lists.freedesktop.org, =?UTF-8?Q?Christian_K=c3=b6nig?= List-Id: dri-devel@lists.freedesktop.org CgpPbiAwMS8yNS8yMDE2IDA5OjMyIFBNLCBEYW5pZWwgVmV0dGVyIHdyb3RlOgo+IE9uIE1vbiwg SmFuIDI1LCAyMDE2IGF0IDA4OjMwOjE0UE0gKzAxMDAsIE1hcmlvIEtsZWluZXIgd3JvdGU6Cj4+ Cj4+Cj4+IE9uIDAxLzI1LzIwMTYgMDc6NTEgUE0sIERhbmllbCBWZXR0ZXIgd3JvdGU6Cj4+PiBP biBNb24sIEphbiAyNSwgMjAxNiBhdCAwNTozODozMFBNICswMTAwLCBNYXJpbyBLbGVpbmVyIHdy b3RlOgo+Pj4+IFJlYWRkaW5nIERhbmllbCwgd2hpY2ggc29tZWhvdyBnb3QgZHJvcHBlZCBmcm9t IHRoZSBjYy4KPj4+Pgo+Pj4+IE9uIDAxLzI1LzIwMTYgMDM6NTMgUE0sIFZpbGxlIFN5cmrDpGzD pCB3cm90ZToKPj4+Pj4gT24gTW9uLCBKYW4gMjUsIDIwMTYgYXQgMDI6NDQ6NTNQTSArMDEwMCwg TWFyaW8gS2xlaW5lciB3cm90ZToKPj4+Pj4+Cj4+Pj4+Pgo+Pj4+Pj4gT24gMDEvMjUvMjAxNiAw MjoyMyBQTSwgVmlsbGUgU3lyasOkbMOkIHdyb3RlOgo+Pj4+Pj4+IE9uIE1vbiwgSmFuIDI1LCAy MDE2IGF0IDAyOjE2OjQ1UE0gKzAxMDAsIE1hcmlvIEtsZWluZXIgd3JvdGU6Cj4+Pj4+Pj4+Cj4+ Pj4+Pj4+Cj4+Pj4+Pj4+IE9uIDAxLzI1LzIwMTYgMDU6MTUgQU0sIE1pY2hlbCBEw6RuemVyIHdy b3RlOgo+Pj4+Pj4+Pj4gT24gMjMuMDEuMjAxNiAwMDoxOCwgVmlsbGUgU3lyasOkbMOkIHdyb3Rl Ogo+Pj4+Pj4+Pj4+IE9uIEZyaSwgSmFuIDIyLCAyMDE2IGF0IDEyOjA2OjAwUE0gKzA5MDAsIE1p Y2hlbCBEw6RuemVyIHdyb3RlOgo+Pj4+Pj4+Pj4+Pgo+Pj4+Pj4+Pj4+PiBbIFRyaW1taW5nIEtE RSBmb2xrcyBmcm9tIENjIF0KPj4+Pj4+Pj4+Pj4KPj4+Pj4+Pj4+Pj4gT24gMjEuMDEuMjAxNiAx OTowOSwgRGFuaWVsIFZldHRlciB3cm90ZToKPj4+Pj4+Pj4+Pj4+IE9uIFRodSwgSmFuIDIxLCAy MDE2IGF0IDA1OjM2OjQ2UE0gKzA5MDAsIE1pY2hlbCBEw6RuemVyIHdyb3RlOgo+Pj4+Pj4+Pj4+ Pj4+IE9uIDIxLjAxLjIwMTYgMTY6NTgsIERhbmllbCBWZXR0ZXIgd3JvdGU6Cj4+Pj4+Pj4+Pj4+ Pj4+Cj4+Pj4+Pj4+Pj4+Pj4+IENhbiB5b3UgcGxlYXNlIHBvaW50IG1lIGF0IHRoZSB2Ymxhbmsg b24vb2ZmIGp1bXAgYnVnIHBsZWFzZT8KPj4+Pj4+Pj4+Pj4+Pgo+Pj4+Pj4+Pj4+Pj4+IEFGQUlS IEkgb3JpZ2luYWxseSByZXBvcnRlZCBpdCBpbiByZXNwb25zZSB0bwo+Pj4+Pj4+Pj4+Pj4+IGh0 dHA6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvYXJjaGl2ZXMvZHJpLWRldmVsLzIwMTUtQXVndXN0 LzA4Nzg0MS5odG1sCj4+Pj4+Pj4+Pj4+Pj4gLCBidXQgSSBjYW4ndCBmaW5kIHRoYXQgaW4gdGhl IGFyY2hpdmVzLCBzbyBtYXliZSB0aGF0IHdhcyBqdXN0IG9uIElSQy4KPj4+Pj4+Pj4+Pj4+PiBT ZWUKPj4+Pj4+Pj4+Pj4+PiBodHRwOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL2FyY2hpdmVzL2Ry aS1kZXZlbC8yMDE2LUphbnVhcnkvMDk5MTIyLmh0bWwKPj4+Pj4+Pj4+Pj4+PiAuIEJhc2ljYWxs eSwgSSByYW4gaW50byB0aGUgYnVnIGZpeGVkIGJ5IHlvdXIgcGF0Y2ggYmVjYXVzZSB0aGUgY291 bnRlcgo+Pj4+Pj4+Pj4+Pj4+IGp1bXBlZCBmb3J3YXJkIG9uIGV2ZXJ5IERQTVMgb2ZmLCBzbyBp dCBoaXQgdGhlIDMyLWJpdCBib3VuZGFyeSBhZnRlcgo+Pj4+Pj4+Pj4+Pj4+IGp1c3QgYSBmZXcg ZGF5cy4KPj4+Pj4+Pj4+Pj4+Cj4+Pj4+Pj4+Pj4+PiBPaywgc28ganVzdCB1bmNvdmVyZWQgdGhl IG92ZXJmbG93IGJ1Zy4KPj4+Pj4+Pj4+Pj4KPj4+Pj4+Pj4+Pj4gTm90IHN1cmUgd2hhdCB5b3Ug bWVhbiBieSAianVzdCIsIGJ1dCB0byBiZSBjbGVhcjogVGhlIGRybV92Ymxhbmtfb24vb2ZmCj4+ Pj4+Pj4+Pj4+IGNvdW50ZXIganVtcGluZyBidWcgKHNpbWlsYXIgdG8gdGhlIGJ1ZyB0aGlzIHRo cmVhZCBpcyBhYm91dCksIHdoaWNoCj4+Pj4+Pj4+Pj4+IGV4cG9zZWQgdGhlIG92ZXJmbG93IGJ1 ZywgaXMgc3RpbGwgYWxpdmUgYW5kIGtpY2tpbmcgaW4gNC41LiBJdCBzZWVtcwo+Pj4+Pj4+Pj4+ PiB0byBoYXBwZW4gd2hlbiB0dXJuaW5nIG9mZiB0aGUgQ1JUQzoKPj4+Pj4+Pj4+Pj4KPj4+Pj4+ Pj4+Pj4gW2RybTpkcm1fdXBkYXRlX3ZibGFua19jb3VudF0gdXBkYXRpbmcgdmJsYW5rIGNvdW50 IG9uIGNydGMgMDogY3VycmVudD0yMTgxMDQ2OTQsIGRpZmY9MCwgaHc9OTE2IGh3X2xhc3Q9OTE2 Cj4+Pj4+Pj4+Pj4+IFtkcm06cmFkZW9uX2dldF92YmxhbmtfY291bnRlcl9rbXNdIGNydGMgMDog ZGlzdCBmcm9tIHZibGFuayBzdGFydCAzCj4+Pj4+Pj4+Pj4+IFtkcm06ZHJtX2NhbGNfdmJsdGlt ZXN0YW1wX2Zyb21fc2Nhbm91dHBvc10gY3J0YyAwIDogdiAweDcgcCgyMTk5LC00NSlAIDczMDQu MzA3MzU0IC0+IDczMDQuMzA4MDA2IFtlIDAgdXMsIDAgcmVwXQo+Pj4+Pj4+Pj4+PiBbZHJtOnJh ZGVvbl9nZXRfdmJsYW5rX2NvdW50ZXJfa21zXSBjcnRjIDA6IGRpc3QgZnJvbSB2Ymxhbmsgc3Rh cnQgMwo+Pj4+Pj4+Pj4+PiBbZHJtOmRybV91cGRhdGVfdmJsYW5rX2NvdW50XSB1cGRhdGluZyB2 YmxhbmsgY291bnQgb24gY3J0YyAwOiBjdXJyZW50PTIxODEwNDY5NCwgZGlmZj0xNjc3NjMwMSwg aHc9MSBod19sYXN0PTkxNgo+Pj4+Pj4+Pj4+Cj4+Pj4+Pj4+Pj4gTm90IHN1cmUgd2hhdCBidWcg d2UncmUgdGFsa2luZyBhYm91dCBoZXJlLCBidXQgaGVyZSB0aGUgaHcgY291bnRlcgo+Pj4+Pj4+ Pj4+IGNsZWFybHkganVtcHMgYmFja3dhcmRzLgo+Pj4+Pj4+Pj4+Cj4+Pj4+Pj4+Pj4+IFtkcm06 cmFkZW9uX2dldF92YmxhbmtfY291bnRlcl9rbXNdIFF1ZXJ5IGZhaWxlZCEgc3RhdCAzCj4+Pj4+ Pj4+Pj4+IFtkcm06cmFkZW9uX2dldF92YmxhbmtfY291bnRlcl9rbXNdIFF1ZXJ5IGZhaWxlZCEg c3RhdCAzCj4+Pj4+Pj4+Pj4+IFtkcm06ZHJtX3VwZGF0ZV92YmxhbmtfY291bnRdIHVwZGF0aW5n IHZibGFuayBjb3VudCBvbiBjcnRjIDE6IGN1cnJlbnQ9MCwgZGlmZj0wLCBodz0wIGh3X2xhc3Q9 MAo+Pj4+Pj4+Pj4+PiBbZHJtOnJhZGVvbl9nZXRfdmJsYW5rX2NvdW50ZXJfa21zXSBRdWVyeSBm YWlsZWQhIHN0YXQgMwo+Pj4+Pj4+Pj4+PiBbZHJtOnJhZGVvbl9nZXRfdmJsYW5rX2NvdW50ZXJf a21zXSBRdWVyeSBmYWlsZWQhIHN0YXQgMwo+Pj4+Pj4+Pj4+PiBbZHJtOmRybV91cGRhdGVfdmJs YW5rX2NvdW50XSB1cGRhdGluZyB2YmxhbmsgY291bnQgb24gY3J0YyAyOiBjdXJyZW50PTAsIGRp ZmY9MCwgaHc9MCBod19sYXN0PTAKPj4+Pj4+Pj4+Pj4gW2RybTpyYWRlb25fZ2V0X3ZibGFua19j b3VudGVyX2ttc10gUXVlcnkgZmFpbGVkISBzdGF0IDMKPj4+Pj4+Pj4+Pj4gW2RybTpyYWRlb25f Z2V0X3ZibGFua19jb3VudGVyX2ttc10gUXVlcnkgZmFpbGVkISBzdGF0IDMKPj4+Pj4+Pj4+Pj4g W2RybTpkcm1fdXBkYXRlX3ZibGFua19jb3VudF0gdXBkYXRpbmcgdmJsYW5rIGNvdW50IG9uIGNy dGMgMzogY3VycmVudD0wLCBkaWZmPTAsIGh3PTAgaHdfbGFzdD0wCj4+Pj4+Pj4+Pj4+IFtkcm06 cmFkZW9uX2dldF92YmxhbmtfY291bnRlcl9rbXNdIFF1ZXJ5IGZhaWxlZCEgc3RhdCAxCj4+Pj4+ Pj4+Pj4+IFtkcm06ZHJtX2NhbGNfdmJsdGltZXN0YW1wX2Zyb21fc2Nhbm91dHBvc10gY3J0YyAw IDogdiAweDEgcCgwLDApQCA3MzA0LjMxNzE0MCAtPiA3MzA0LjMxNzE0MCBbZSAwIHVzLCAwIHJl cF0KPj4+Pj4+Pj4+Pj4gW2RybTpyYWRlb25fZ2V0X3ZibGFua19jb3VudGVyX2ttc10gUXVlcnkg ZmFpbGVkISBzdGF0IDEKPj4+Pj4+Pj4+Pj4gW2RybTpkcm1fdXBkYXRlX3ZibGFua19jb3VudF0g dXBkYXRpbmcgdmJsYW5rIGNvdW50IG9uIGNydGMgMDogY3VycmVudD0yMzQ4ODA5OTUsIGRpZmY9 MTY3NzcyMTUsIGh3PTAgaHdfbGFzdD0xCj4+Pj4+Pj4+Pj4KPj4+Pj4+Pj4+PiBTYW1lIGhlcmUu Cj4+Pj4+Pj4+Pgo+Pj4+Pj4+Pj4gQXQgbGVhc3Qgb25lIG9mIHRoZSBqdW1wcyBpcyBleHBlY3Rl ZCwgYmVjYXVzZSB0aGlzIGlzIGFyb3VuZCB0dXJuaW5nCj4+Pj4+Pj4+PiBvZmYgdGhlIENSVEMg Zm9yIERQTVMgb2ZmLiBEb24ndCBrbm93IHlldCB3aHkgdGhlcmUgYXJlIHR3byBqdW1wcyBiYWNr Cj4+Pj4+Pj4+PiB0aG91Z2guCj4+Pj4+Pj4+Pgo+Pj4+Pj4+Pj4KPj4+Pj4+Pj4+PiBUaGVzZSB0 aGluZ3MganVzdCBkb24ndCBoYXBwZW4gb24gaTkxNSBiZWNhdXNlIGRybV92Ymxhbmtfb2ZmKCkg YW5kCj4+Pj4+Pj4+Pj4gZHJtX3ZibGFua19vbigpIGFyZSBhbHdheXMgY2FsbGVkIGFyb3VuZCB0 aGUgdGltZXMgd2hlbiB0aGUgaHcgY291bnRlcgo+Pj4+Pj4+Pj4+IG1pZ2h0IGdldCByZXNldC4g T3IgYXQgbGVhc3QgdGhhdCdzIGhvdyBpdCBzaG91bGQgYmUuCj4+Pj4+Pj4+Pgo+Pj4+Pj4+Pj4g V2hpY2ggaXMgb2YgY291cnNlIHRoZSBpZGVhIG9mIERhbmllbCdzIHBhdGNoICh3aGljaCBpcyB3 aGF0IEknbSBnZXR0aW5nCj4+Pj4+Pj4+PiB0aGUgYWJvdmUgd2l0aCkgb3IgTWFyaW8ncyBwYXRj aCBhcyB3ZWxsLCBidXQgY2xlYXJseSBzb21ldGhpbmcncyBzdGlsbAo+Pj4+Pj4+Pj4gd3Jvbmcu IEl0J3MgY2VydGFpbmx5IHBvc3NpYmxlIHRoYXQgaXQncyBzb21ldGhpbmcgaW4gdGhlIGRyaXZl ciwgYnV0Cj4+Pj4+Pj4+PiBzaW5jZSBjYWxsaW5nIGRybV92YmxhbmtfcHJlL3Bvc3RfbW9kZXNl dCBmcm9tIHRoZSBzYW1lIHBsYWNlcyBzZWVtcyB0bwo+Pj4+Pj4+Pj4gd29yayBmaW5lIChpZ25v cmluZyB0aGUgcmVncmVzc2lvbiBkaXNjdXNzZWQgaW4gdGhpcyB0aHJlYWQpLi4uIERvCj4+Pj4+ Pj4+PiBkcm1fdmJsYW5rX29uL29mZiByZXF1aXJlIHNvbWV0aGluZyBlbHNlIHRvIGhhbmRsZSB0 aGlzIGNvcnJlY3RseT8KPj4+Pj4+Pj4+Cj4+Pj4+Pj4+Pgo+Pj4+Pj4+Pgo+Pj4+Pj4+PiBJIHN1 c3BlY3QgaXQgaXMgYmVjYXVzZSB2YmxhbmtfZGlzYWJsZV9hbmRfc2F2ZSBjYWxscwo+Pj4+Pj4+ PiBkcm1fdXBkYXRlX3ZibGFua19jb3VudCgpIHVuY29uZGl0aW9uYWxseSwgZXZlbiBpZiB2Ymxh bmsgaXJxcyBhcmUKPj4+Pj4+Pj4gYWxyZWFkeSBvZmYuCj4+Pj4+Pj4+Cj4+Pj4+Pj4+IFNvIG9u IGEgbWFudWFsIGRpc3BsYXkgZGlzYWJsZSAtPiByZWVuYWJsZSB5b3UgZ2V0IHNvbWV0aGluZyBs aWtlCj4+Pj4+Pj4+Cj4+Pj4+Pj4+IEF0IGRpc2FibGU6Cj4+Pj4+Pj4+Cj4+Pj4+Pj4+IENhbGwg dG8gZHBtcy1vZmYgLS0+IGF0b21iaW9zX2NydGNfZHBtcyhEUE1TX09GRikgLS0+IGRybV92Ymxh bmtfb2ZmIC0+Cj4+Pj4+Pj4+IHZibGFua19kaXNhYmxlX2FuZF9zYXZlIC0+IGlycXMgb2ZmLCBk cm1fdXBkYXRlX3ZibGFua19jb3VudCgpIGNvbXB1dGVzCj4+Pj4+Pj4+IGZpbmFsIGNvdW50Lgo+ Pj4+Pj4+Pgo+Pj4+Pj4+PiBUaGVuIHRoZSBjcnRjIGlzIHNodXQgZG93biBhbmQgaXRzIGh3IGNv dW50ZXIgcmVzZXRzIHRvIHplcm8uCj4+Pj4+Pj4+Cj4+Pj4+Pj4+IEF0IHJlZW5hYmxlOgo+Pj4+ Pj4+Pgo+Pj4+Pj4+PiBNb2Rlc2V0dGluZyAtPiBkcm1fY3J0Y19oZWxwZXJfc2V0X21vZGUgLT4g Y3J0Y19mdW5jcy0+cHJlcGFyZShjcnRjKSAtPgo+Pj4+Pj4+PiBhdG9tYmlvc19jcnRjX3ByZXBh cmUoKSAtPiBhdG9tYmlvc19jcnRjX2RwbXMoRFBNU19PRkYpIC0+Cj4+Pj4+Pj4+IGRybV92Ymxh bmtfb2ZmIC0+IHZibGFua19kaXNhYmxlX2FuZF9zYXZlIC0+IEEgcG9pbnRsZXNzCj4+Pj4+Pj4+ IGRybV91cGRhdGVfdmJsYW5rX2NvdW50KCkgd2hpbGUgdGhlIGh3IGNvdW50ZXIgaXMgYWxyZWFk eSByZXNldCB0byB6ZXJvCj4+Pj4+Pj4+IC0tPiBVbndhbnRlZCBjb3VudGVyIGp1bXAuCj4+Pj4+ Pj4+Cj4+Pj4+Pj4+Cj4+Pj4+Pj4+IFRoZSBwcm9ibGVtIGRvZXNuJ3QgaGFwcGVuIG9uIGEgcHVy ZSBtb2Rlc2V0IHRvIGEgZGlmZmVyZW50IHZpZGVvCj4+Pj4+Pj4+IHJlc29sdXRpb24vcmVmcmVz aCByYXRlLCBhcyB0aGVuIHdlIG9ubHkgaGF2ZSBvbmUgY2FsbCBpbnRvCj4+Pj4+Pj4+IGF0b21i aW9zX2NydGNfZHBtcyhEUE1TX09GRikuCj4+Pj4+Pj4+Cj4+Pj4+Pj4+IEkgdGhpbmsgdGhlIGZp eCBpcyB0byBmaXggdmJsYW5rX2Rpc2FibGVfYW5kX3NhdmUoKSB0byBvbmx5IGNhbGwKPj4+Pj4+ Pj4gZHJtX3VwZGF0ZV92YmxhbmtfY291bnQoKSBpZiB2YmxhbmsgaXJxcyBnZXQgYWN0dWFsbHkg ZGlzYWJsZWQsIG5vdCBvbgo+Pj4+Pj4+PiBuby1vcCBjYWxscy4gSSB3aWxsIHRyeSB0aGF0IG5v dy4KPj4+Pj4+Pgo+Pj4+Pj4+IEl0IGRvZXMgdGhhdCBvbiBwdXJwb3NlLiBPdGhlcndpc2UgdGhl IHZibGFuayBjb3VudGVyIHdvdWxkIGFwcGVhciB0bwo+Pj4+Pj4+IGhhdmUgc3RhbGxlZCB3aGls ZSB0aGUgaW50ZXJydXB0IHdhcyBvZmYuCj4+Pj4+Pj4KPj4+Pj4+Cj4+Pj4+PiBPaywgdGhhdCdz IHdoYXQgdGhlIGNvbW1lbnRzIHRoZXJlIHNheSwgYWx0aG91Z2ggaSBkb24ndCBzZWUgYXRtLiB3 aHkKPj4+Pj4+IHRoYXQgcGVyY2VpdmVkIHN0YWxsIHdvdWxkIGJlIGEgYmlnIHByb2JsZW0uIEkg Y2hlY2tlZCBhbGwgY2FsbGVycyBvZgo+Pj4+Pj4gdmJsYW5rX2Rpc2FibGVfYW5kX3NhdmUoKS4g VGhleSBhcmUgYWxsIGNhcmVmdWwgdG8gbm90IGNhbGwgdGhhdAo+Pj4+Pj4gZnVuY3Rpb24gaWYg dmJsYW5rcyBhcmUgYWxyZWFkeSBkaXNhYmxlZC4gVGhlIG9ubHkgZXhjZXB0aW9uIGlzCj4+Pj4+ PiBkcm1fdmJsYW5rX29mZigpLiBJZiBkcm1fdmJsYW5rX29mZi9vbiBpcyBzdXBwb3NlZCB0byBw cm90ZWN0IGttcwo+Pj4+Pj4gZHJpdmVycyB3aGljaCBoYXZlIHJlc2V0dGluZyBodyBjb3VudGVy cyBvciBvdGhlciBwcm9ibGVtYXRpYyBiZWhhdmlvdXIKPj4+Pj4+IGR1cmluZyBtb2Rlc2V0cyBl dGMuIHRoZW4gdGhpcyB3aWxsIGJyZWFrLiBFLmcuLCBjYWxsaW5nIHRoZSB2YmxhbmsKPj4+Pj4+ IHRpbWVzdGFtcGluZyBzdHVmZiBpcyBhbHNvIG5vdCBzYWZlL3dlbGwtZGVmaW5lZCBkdXJpbmcg bW9kZXNldHMgd2hlbgo+Pj4+Pj4gdGhlIHRpbWVzdGFtcGluZyBjb25zdGFudHMgYXJlIG5vdCAo eWV0KSB1cGRhdGVkIHRvIHJlZmxlY3QgdGhlIG5ldyBtb2RlCj4+Pj4+PiB0aW1pbmcgb2YgdGhl IG1vZGVzZXQgaW4gcHJvZ3Jlc3MuCj4+Pj4+Cj4+Pj4+IFRoZSBpZGVhIGlzIHRvIG1haW50YWlu IHRoZSBhcHBlYXJhbmNlIHRoYXQgdGhlIGNvdW50ZXIgdGlja3MgYWxsIHRoZQo+Pj4+PiB0aW1l IGFzIGxvbmcgYXMgdGhlIGNydGMgaXMgYWN0aXZlLiBXaGlsZSB0aGF0IG1heSBub3QgYmUgcmVh bGx5Cj4+Pj4+IHJlcXVpcmVkIGluIGNhc2UgaWYgbm8gb25lIGlzIGN1cnJlbnRseSBpbnRlcmVz dGVkIGluIHRoZSB2YmxhbmsKPj4+Pj4gY291bnRlciwgSSB0aGluayBpdCdzIGEgbmljZSB0aGlu ZyB0byBoYXZlIGp1c3QgdG8gbWFrZSB0aGUgYmVoYXZpb3VyCj4+Pj4+IG9mIHRoZSBjb3VudGVy IGNvbnNpc3RlbnQuCj4+Pj4+Cj4+Pj4+IEFzIGZhciBhcyBjYWxsaW5nIGRybV92Ymxhbmtfb2Zm KCkgYWZ0ZXIgdGhlIGh3IGNvdW50ZXIgZ290IHJlc2V0LCB3ZWxsLAo+Pj4+PiB0aGF0IG5vdCBj b3JyZWN0LiBJdCBzaG91bGQgYmUgY2FsbGVkIGJlZm9yZSB0aGUgcmVzZXQuCj4+Pj4KPj4+PiBX aGF0IHJhZGVvbiBkb2VzIGlzIGNhbGxpbmcgZHJtX3ZibGFua19vZmYgYXQgYmVnaW5uaW5nIG9m IERQTVNfT0ZGLiBUaGUKPj4+PiBmaXJzdCBjYWxsIHRvIERNUFNfT0ZGIHdpbGwgY2FsbCBkcm1f dmJsYW5rX29mZigpIGFuZCByZWFsbHkgZGlzYWJsZQo+Pj4+IHZibGFuay1pcnFzIGlmIHRoZXkg d2VyZSBydW5uaW5nLCB1cGRhdGluZyB0aGUgY291bnRzL3RzIGEgbGFzdCB0aW1lLiBCdXQKPj4+ PiB0aGVuIHRoZSBkcG1zIG9mZiB3aWxsIHJlc2V0IHRoZSBodyBjb3VudGVyIHRvIHplcm8uIFdo ZW4gb25lIHJlZW5hYmxlcyB0aGUKPj4+PiBkaXNwbGF5LCBhIHNlY29uZCBjYWxsIHRvIERQTVNf T0ZGIHdpbGwgbm93IGNhbGwgZHJtX3ZibGFua19vZmYgYWdhaW4gd2hlbgo+Pj4+IGl0IGFwcGFy ZW50bHkgc2hvdWxkbid0Lgo+Pj4+Cj4+Pj4gSSBqdXN0IHRlc3RlZCB0aGlzIHBhdGNoLCB3aGlj aCBmaXhlcyB0aGUgY291bnRlciBqdW1wcyBvbiByYWRlb24ta21zIHdpdGgKPj4+PiBteSBvciBE YW5pZWwncyBkcm1fdmJsYW5rX29mZiBwYXRjaGVzIHRvIHJhZGVvbjoKPj4+Cj4+PiBUaGlzIG1p Z2h0IGJlIGR1ZSB0byB0aGUgbGVnYWN5IGhlbHBlcnMsIHdoaWNoIGp1c3QgbG92ZSB0byByZWR1 bmRhbnRseQo+Pj4gZGlzYWJsZSBzdHVmZiB0aGF0J3Mgb2ZmIGFscmVhZHkuIFRoZSBwcm9ibGVt IEkgc2VlIHdpdGggbm8tb3BpbmcgdGhlc2UKPj4+IG91dCBpcyB0aGF0IGZvciBhdG9taWMgZHJp dmVycyAod2hpY2ggcmVhbGx5IHNob3VsZCBnZXQgdGhpcyByaWdodCkgdGhpcwo+Pj4gbWlnaHQg cGFwZXIgb3ZlciBidWdzOiBFLmcuIHdoZW4geW91IGZvcmdldCB0byBjYWxsIF9vZmYoKSB3aGVu IGRpc2FibGluZwo+Pj4gdGhlIGNydGMsIHRoZW4gY2FsbGluZyBfb24oKSB0d2ljZSBpbiBhIHJv dyBpcyBpbmRlZWQgYSBzZXJpb3VzIGJ1Zy4KPj4+IFNpbWlsYXIgd2hlbiB5b3UgZm9yZ2V0IHRv IGNhbGwgX29uKCkgYW5kIGhhdmUgbXVsdGlwbGUgX29mZigpIGNhbGxzIGluIGEKPj4+IHJvdy4K Pj4+Cj4+PiBTbyBub3Qgc3VyZSB3aGF0IHRvIGRvIGhlcmUuCj4+PiAtRGFuaWVsCj4+Pgo+Pgo+ PiBZZXMsIHRoZSBsZWdhY3kgaGVscGVycyBjYXVzZSB0d28gY2FsbHMgdG8gZHBtcyBvZmYgaWYg b25lIGRpc2FibGVzIGEKPj4gZGlzcGxheS4gRmlyc3QgZHVyaW5nIGRpc3BsYXkgZGlzYWJsZSBh cyBpbnRlbmRlZC4gVGhlbiB3aGVuIG9uZSByZWVuYWJsZXMKPj4gdGhlIGRpc3BsYXkgZHVyaW5n IG1vZGVzZXR0aW5nIGFzIHBhcnQgb2YgY3J0Y19mdW5jcy0+cHJlcGFyZSgpIC0gYXQgbGVhc3QK Pj4gb24gcmFkZW9uLgo+Pgo+PiBNYXliZSB0aGUgbWluaW11bSB0aGluZyB0aGF0IHdvdWxkIGhl bHAgaXMgdG8ganVzdCBjaGVjayBmb3IKPj4gdmJsYW5rLT5pbm1vZGVzZXQgaW4gZHJtX3ZibGFu a19vZmYoKS4gSWYgdGhhdCB3b3VsZCBiZSB0aGUgY2FzZSB3ZSdkIGtub3cKPj4gaXQgaXMgYSBy ZWR1bmRhbnQgY2FsbCBhbmQgY291bGQgbm8tb3AgaXQgYW5kIGRvIGEKPj4gV0FSTl9PTih2Ymxh bmstPmlubW9kZXNldCk/Cj4KPiBJIGhhdmUgdGhhdCBoZXJlIGxvY2FsbHksIGJsb3dzIHVwIGFs bCBvdmVyIHRoZSBwbGFjZSBvbiByYWRvZW4uIEFuZCBhbHNvCj4gd291bGQgYmxvdyB1cCBldmVy eXdoZXJlIGVsc2UuCj4KCllvdSBtZWFuIHRoZSBXQVJOX09OIGNhdXNlcyB1Z2xpbmVzcz8gVGhl IG5vLW9wIG9uIHJlZHVuZGFudCBjYWxscyB0byAKZHJtX3ZibGFua19vZmYgd291bGQgaG9wZWZ1 bGx5IG5vdCBibG93IHVwIGFueXRoaW5nIGJ1dCBwcmV2ZW50IGJsb3cgdXBzPwoKVGhlIHByb2Js ZW0gaXMgdGhhdCB0aGVyZSBzaG91bGQgbm90IGV2ZXIgYmUgYSBjYWxsIHRvIHRoZSAKZHJtX3Vw ZGF0ZV92YmxhbmtfY291bnQoKSBmdW5jdGlvbiBvbmNlIGEgY3J0YyBpcyBpbiBtb2Rlc2V0L2Rw bXMgb2ZmIApldGMuLCBub3Qgb25seSBiZWNhdXNlIG9mIHRoZSBodyB2YmxhbmsgY291bnRlcnMg YmVpbmcgcmVzZXQgdG8gemVybywgCmJ1dCBhbHNvIGJlY2F1c2UgdmJsYW5rIHRpbWVzdGFtcHMg Y29tcHV0ZWQgbWF5IGJlIHdyb25nLCBnb2luZyAKYmFja3dhcmRzIGV0Yy4gVGhhdCBjb3VsZCBh Z2FpbiBjb25mdXNlIGNsaWVudHMuCgo+IEkgd2FzIHRoaW5raW5nIG9mIGFkZGluZyB0aGUgdmJs YW5rLT5pbm1vZGVzZXQgY2hlY2sgdG8gcmFkZW9uL2FtZGdwdSwKPiB3aXRoIGEgbm90ZSB3aHkg aXQncyBuZWVkZWQgKGxlZ2FjeSBjcnRjIGhlbHBlcnMganVzdCBzdWNrKS4KCk1heWJlIHlvdSBj b3VsZCBkbyB0aGF0IGNoZWNrIGluIHJhZGVvbi9hbWRncHUsIGJ1dCBzdGlsbCBhbHNvIGxlYXZl IGl0IAppbiBkcm1fdmJsYW5rX29mZigpPyBJZiBhbGwga21zIGRyaXZlcnMgcHJvcGVybHkgYXZv aWQgcmVkdW5kYW50IGNhbGxzIAphcyBwYXJ0IG9mIGxlZ2FjeSBwYXRocyB0aGVuIHRoZSBXQVJO X09OIGFuZCBuby1vcCBpbiBkcm1fdmJsYW5rX29mZiAKc2hvdWxkIG5vdCBldmVyIHRyaWdnZXIs IHVubGVzcyB0aGVyZSBpcyBhIHJlYWwgYnVnLCByaWdodD8gSW4gd2hpY2ggCmNhc2UgaXQgc2hv dWxkIGhvcGVmdWxseSBwcmV2ZW50IHdvcnNlIHRoaW5ncyBsaWtlIGEgaGFuZ2luZyBjb21wb3Np dGVkIApkZXNrdG9wLCBvciBsb2dpbiwgYW5kIGluc3RlYWQganVzdCBtYWtlIG5vaXNlIGluIHRo ZSBrZXJuZWwgbG9nPwoKPgo+PiBkcm1fdmJsYW5rX29uKCkgaSBkb24ndCBrbm93IGhvdyB0byB0 cmVhdCwgYnV0IHRoYXQgb25lIGNhbGxzCj4+IGRybV9yZXNldF92YmxhbmtfdGltZXN0YW1wKCkg d2hpY2ggc2hvdWxkIGJlIGxlc3MgcHJvYmxlbWF0aWMgaWYgY2FsbGVkCj4+IHJlZHVuZGFudGx5 Lgo+Cj4gSSB0aGluayBldmVuIGxlZ2FjeSBjcnRjIGhlbHBlcnMgZG9uJ3QgZW5hYmxlIHN0dWZm IGFnYWluIGlmIGl0J3Mgbm90IGJlZW4KPiBkaXNhYmxlZCBiZWZvcmUuIFNvIG9uIGRybV92Ymxh bmtfb24oKSB3ZSBtaWdodCBiZSBhYmxlIHRvIHB1dCBhIFdBUk5fT04KPiBpbiBwbGFjZSAuLi4K CkhtLCBsb2dnaW5nIHRoaXN0IHN0dWZmIGhlcmUgZHVyaW5nIG1vZGVzZXRzIGFuZCBkaXNwbGF5 IGRpcy9lbmFibGUgaSAKc2VlIGxvdHMgb2YgZHJtX3ZibGFua19vbiB0aGF0IGNvbWUgaW4gInBh aXJzIiBvbmx5IGFib3V0IHR3byBkb3plbiAKbXNlY3MgYXBhcnQuCgo+Cj4+IE5vdyB0aGUgcGF0 Y2ggaSB3YW50IHRvIHRyeSBuZXh0IHRvIGZpeCB0aGUgZHJtX3ZibGFua19wcmUvcG9zdF9tb2Rl c2V0Cj4+IHJlZ3Jlc3Npb24gaW4gTGludXggNC40LzQuNSBpcyB0byBhZGQgYSAuLi4KPj4KPj4g aWYgKChkaWZmID4gMSkgJiYgdmJsYW5rLT5pbm1vZGVzZXQpIGRpZmYgPSAxOwo+Pgo+PiAuLi4g dG8gdGhlIGJvdHRvbSBvZiBkcm1fdXBkYXRlX3ZibGFua19jb3VudCgpLiBUaGF0IHNob3VsZCBo b3BlZnVsbHkKPj4gcmVzdG9yZSB0aGUgcHJlL3Bvc3RfbW9kZXNldCBiZWhhdmlvciBhcyBjbG9z ZSB0byB0aGUgb3JpZ2luYWwgYmVoYXZpb3IgYXMKPj4gcG9zc2libGUuIEFzIGEgc2lkZSBlZmZl Y3QgaXQgd291bGQgYWxzbyBwcmV2ZW50IHRoZSBjb3VudGVyIGp1bXAgY2F1c2VkIGJ5Cj4+IHJl ZHVuZGFudCBjYWxscyB0byBkcm1fdmJsYW5rX29mZigpLgo+Cj4gSG0sIGNhbiB3ZSBqdXN0IGZy b2IgcHJlL3Bvc3RfbW9kZXNldCBvbmx5IHdpdGggc29tZSBjaGVja3M/IEknZCBsaWtlIHRvCj4g bm90IHB1dCB0aGF0IGtpbmQgb2YgIkkgaGF2ZSBubyBpZGVhIGFib3V0IG15IGh3IHN0YXRlIiBo YWNrcyBpbnRvIHRoZSBuZXcKPiBoZWxwZXJzLiBPdGhlcndpc2Ugbm90IGV2ZW4gYXRvbWljIGRy aXZlcnMgY2FuIHN0YXJ0IHRvIGdhaW4gV0FSTl9PTnMgdG8KPiBlbmZvcmNlIGNvcnJlY3QgdXNh Z2UsIHdoaWNoIHdvdWxkIGJlIGEgcmVhbCBidW1tZXIgaW1vLgo+IC1EYW5pZWwKPgoKV2UgY291 bGQgY2hlY2sgZm9yIG9ubHkgKHZibGFuay0+aW5tb2Rlc2V0ICYgMHgyKSB0byBvbmx5IGFwcGx5 IGl0IHRvIAp0aGUgbGVnYWN5IHByZS9wb3N0IHBhdGgsIHRydXN0aW5nIHRoYXQgdGhlIGRybV92 Ymxhbmtfb2ZmL29uIHBhdGggd2lsbCAKYmUgbWFkZSByb2J1c3QgaW4gYSBkaWZmZXJlbnQgd2F5 LCBlLmcuLCBieSB0aGUgc3R1ZmYgZGlzY3Vzc2VkIGFib3ZlIAphbmQgY2FyZWZ1bCBpbXBsZW1l bnRhdGlvbiBpbiBlYWNoIGttcyBkcml2ZXIgdGhhdCB1c2VzIHRob3NlLiBBdG0uIApyYWRlb24g ZG9lc24ndCB1c2Ugb2ZmL29uLCBzbyB5b3VyIGVuYWJsZW1lbnQgcGF0Y2ggc2V0IGNhbiBtYWtl IHN1cmUgaXQgCmRvZXMgdGhlIHJpZ2h0IHRoaW5nIGZyb20gdGhlIGJlZ2lubmluZy4KCnJvY2tj aGlwLWttcyBtYXkgbmVlZCBzaW1pbGFyIHRyZWF0bWVudCB0byByYWRlb24gdG8gYXZvaWQgcmVk dW5kYW50IGNhbGxzLgoKQnR3LiBob3cgdGhlIHBhdGNoIHRvIGRybV91cGRhdGVfdmJsYW5rX2Nv dW50KCkgY2xvc2UgdG8gdGhlIGJvdHRvbSAKd291bGQgYWN0dWFsbHkgbG9vayBpcyBtb3JlIGxp a2U6CgppZiAoKGRpZmYgPiAxKSAmJgogICAgICgodmJsYW5rLT5pbm1vZGVzZXQgJiAweDIpIHx8 IChmbGFncyAmIERSTV9DQUxMRURfRlJPTV9WQkxJUlEpKSkKICAgICAgICAgIGRpZmYgPSAxOwoK QW5vdGhlciBwcm9ibGVtIHdlIGhhdmUgaXMgdGhhdCB0aGUgaW1wbGVtZW50YXRpb24gb2YgdGhl IHZibGFuayAKdGltZXN0YW1wIGRvdWJsZWJ1ZmZlciB3aXRoIG91ciBjdXN0b20gc2VxdWVuY2Ug bG9ja2luZyBpcyBvbmx5IHNhdmUgCmFnYWluc3QgY29uY3VycmVudCByZWFkZXJzIGFzIGxvbmcg YXMgdGhlIGluY3JlbWVudCBmb3Igc3RvcmVfdmJsYW5rKCkgCmlzICsxLCBpZS4gZGlmZiA9IDEg aW4gdGhhdCBjb2RlLgoKT3RoZXIgZGlmZiB2YWx1ZXMgbGlrZSAyIHdvdWxkIGNhdXNlIHVzIHRv IHdyaXRlIHRvIHRoZSBvdGhlciB0aW1lc3RhbXAgCnNsb3QgdGhhdCBpcyBwb3RlbnRpYWxseSBy ZWFkIGJ5IHNvbWUgY29uY3VycmVudCByZWFkZXJzIGF0IHRoZSBzYW1lIAp0aW1lIGFuZCB0aGV5 IHdvdWxkIGdldCBjb3JydXB0ZWQgdGltZXN0YW1wcy4KCk5vdyBvdXRzaWRlIHZibGFuayBpcnEg ZHJtX3VwZGF0ZV92YmxhbmtfY291bnQoKSBpcyBvbmx5IHN1cHBvc2VkIHRvIGJlIApjYWxsZWQg d2hpbGUgdGhlcmUgYXJlbid0IGFueSBjb25jdXJyZW50IHJlYWRlcnMgaWUuLCB2YmxhbmstPnJl ZmNvdW50IAo9PSAwLCBhbmQgdGhlIHdheSBkcm1fdmJsYW5rX29uL29mZiBhcmUgaW1wbGVtZW50 ZWQgdGhpcyBzZWVtcyB0byBiZSB0aGUgCmNhc2UsIHNvIGFueXRoaW5nIGdvZXMuCgppZiBjYWxs ZWQgZnJvbSBkcm1faGFuZGxlX3ZibGFuaygpIGFrYSAoZmxhZ3MgJiBEUk1fQ0FMTEVEX0ZST01f VkJMSVJRKSwgCndlIGhhdmUgdG8gYXNzdW1lIHRoYXQgdGhlcmUgYXJlIGNvbmN1cnJlbnQgcmVh ZGVycywgYmVjYXVzZSB2YmxhbmsgaXJxcyAKYXJlIHVzdWFsbHkgb25seSBrZXB0IGFjdGl2ZSBp ZiB2YmxhbmstPnJlZmNvdW50IGlzID4gMC4gVGhpcyBtZWFucyBvbmx5IAorMSBpbmNyZW1lbnRz IGFyZSBhbGxvd2VkLiBJbiB0aGUgcGFzdCB0aGlzIHdhcyBhbHdheXMgdGhlIGNhc2UsIGJ1dCAK d2l0aCB0aGUgbmV3IGltcGxlbWVudGF0aW9uIHNpbmNlIExpbnV4IDQuNCwgaXQgY291bGQgaGFw cGVuIHRoYXQgd2UgZ2V0IApkaWZmID4gMSBpZiB0aGUgdmJsYW5rIGlycSBnZXRzIGRlZmVycmVk IGJ5IG1vcmUgdGhhbiAxIHZpZGVvIHJlZnJlc2ggCmN5Y2xlLCBlLmcuLCBkdWUgdG8gbG9uZyBp cnEgb2ZmIHBlcmlvZHMsIG1heWJlIHByZWVtcHRpb24gb24gYSAKUlRfUFJFRU1QVCBrZXJuZWws IGxvbmcgaGVsZCBsb2NrcywgZmlybXdhcmUgdHJpZ2dlcmVkIFNNSSdzIGV0Yy4gVGhhdCAKd291 bGQgY2F1c2UgYmFkIGNvcnJ1cHRpb24gb2YgdGltZXN0YW1wcy4KClNvIHVubGVzcyBvciB1bnRp bCB3ZSBhbHNvIHJld3JpdGUgdGhlIHRpbWVzdGFtcCBjYWNoaW5nLCB3ZSBuZWVkIHRoYXQgCmV4 dHJhIHByb3RlY3Rpb24gYWdhaW5zdCBkaWZmID4gMSBpbiB2YmxhbmsgaXJxLgoKLW1hcmlvCl9f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBt YWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwOi8vbGlzdHMu ZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg==