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.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,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 33C19C2D0DB for ; Wed, 29 Jan 2020 17:52:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 14A7920720 for ; Wed, 29 Jan 2020 17:52:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727301AbgA2RwZ (ORCPT ); Wed, 29 Jan 2020 12:52:25 -0500 Received: from foss.arm.com ([217.140.110.172]:44164 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727297AbgA2RwZ (ORCPT ); Wed, 29 Jan 2020 12:52:25 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0EFCC328; Wed, 29 Jan 2020 09:52:25 -0800 (PST) Received: from localhost (unknown [10.1.198.81]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A465B3F67D; Wed, 29 Jan 2020 09:52:24 -0800 (PST) Date: Wed, 29 Jan 2020 17:52:23 +0000 From: Ionela Voinescu To: Valentin Schneider Cc: catalin.marinas@arm.com, will@kernel.org, mark.rutland@arm.com, maz@kernel.org, suzuki.poulose@arm.com, sudeep.holla@arm.com, dietmar.eggemann@arm.com, peterz@infradead.org, mingo@redhat.com, ggherdovich@suse.cz, vincent.guittot@linaro.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 6/6] arm64: use activity monitors for frequency invariance Message-ID: <20200129175223.GA26494@arm.com> References: <20191218182607.21607-1-ionela.voinescu@arm.com> <20191218182607.21607-7-ionela.voinescu@arm.com> <96fdead6-9896-5695-6744-413300d424f5@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <96fdead6-9896-5695-6744-413300d424f5@arm.com> User-Agent: Mutt/1.9.4 (2018-02-28) Sender: linux-doc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-doc@vger.kernel.org Hi Valentin, On Wednesday 29 Jan 2020 at 17:13:53 (+0000), Valentin Schneider wrote: > Only commenting on the bits that should be there regardless of using the > workqueues or not; > > On 18/12/2019 18:26, Ionela Voinescu wrote: > > +static void cpu_amu_fie_init_workfn(struct work_struct *work) > > +{ > > + u64 core_cnt, const_cnt, ratio; > > + struct cpu_amu_work *amu_work; > > + int cpu = smp_processor_id(); > > + > > + if (!cpu_has_amu_feat()) { > > + pr_debug("CPU%d: counters are not supported.\n", cpu); > > + return; > > + } > > + > > + core_cnt = read_sysreg_s(SYS_AMEVCNTR0_CORE_EL0); > > + const_cnt = read_sysreg_s(SYS_AMEVCNTR0_CONST_EL0); > > + > > + if (unlikely(!core_cnt || !const_cnt)) { > > + pr_err("CPU%d: cycle counters are not enabled.\n", cpu); > > + return; > > + } > > + > > + amu_work = container_of(work, struct cpu_amu_work, cpu_work); > > + if (unlikely(!(amu_work->cpuinfo_max_freq))) { > > + pr_err("CPU%d: invalid maximum frequency.\n", cpu); > > + return; > > + } > > + > > + /* > > + * Pre-compute the fixed ratio between the frequency of the > > + * constant counter and the maximum frequency of the CPU (hz). > > I can't resist: s/hz/Hz/ > > > + */ > > + ratio = (u64)arch_timer_get_rate() << (2 * SCHED_CAPACITY_SHIFT); > > + ratio = div64_u64(ratio, amu_work->cpuinfo_max_freq * 1000); > > Nit: we're missing a comment somewhere that the unit of this is in kHz > (which explains the * 1000). > Will do! The previous comment that explained this was ".. while ensuring max_freq is converted to HZ.", but I believed it as too clear and replaced it with the obscure "(hz)". I'll revert :). > > + this_cpu_write(arch_max_freq_scale, (unsigned long)ratio); > > + > > Okay so what we get in the tick is: > > /\ core > -------- > /\ const > > And we want that to be SCHED_CAPACITY_SCALE when running at max freq. IOW we > want to turn > > max_freq > ---------- > const_freq > > into SCHED_CAPACITY_SCALE, so we can just multiply that by: > > const_freq > ---------- * SCHED_CAPACITY_SCALE > max_freq > > But what the ratio you are storing here is > > const_freq > arch_max_freq_scale = ---------- * SCHED_CAPACITY_SCALE² > max_freq > > (because x << 2 * SCHED_CAPACITY_SHIFT == x << 20) > > > In topology_freq_scale_tick() you end up doing > > /\ core arch_max_freq_scale > ------- * -------------------- > /\ const SCHED_CAPACITY_SCALE > > which gives us what we want (SCHED_CAPACITY_SCALE at max freq). > > > Now, the reason why we multiply our ratio by the square of > SCHED_CAPACITY_SCALE was not obvious to me, but you pointed me out that the > frequency of the arch timer can be *really* low compared to the max CPU freq. > > For instance on h960: > > [ 0.000000] arch_timer: cp15 timer(s) running at 1.92MHz (phys) > > $ root@valsch-h960:~# cat /sys/devices/system/cpu/cpufreq/policy4/cpuinfo_max_freq > 2362000 > > So our ratio would be > > 1'920'000 * 1024 > ---------------- > 2'362'000'000 > > Which is ~0.83, so that becomes simply 0... > > > I had a brief look at the Arm ARM, for the arch timer it says it is > "typically in the range 1-50MHz", but then also gives an example with 20KHz > in a low-power mode. > > If we take say 5GHz max CPU frequency, our lower bound for the arch timer > (with that SCHED_CAPACITY_SCALE² trick) is about ~4.768KHz. It's not *too* > far from that 20KHz, but I'm not sure we would actually be executing stuff > in that low-power mode. > > Long story short, we're probably fine, but it would nice to shove some of > the above into comments (especially the SCHED_CAPACITY_SCALE² trick) Okay, I'll add some of this documentation as comments in the patches. I thought about doing it but I was not sure it justified the line count. But if it saves people at least the hassle to unpack this computation to understand the logic, it will be worth it. Thank you for the thorough review, Ionela. 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=0.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE, SPF_PASS,URIBL_BLOCKED,URIBL_DBL_ABUSE_MALW,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 D9DCAC2D0DB for ; Wed, 29 Jan 2020 17:52:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AF6EF206D4 for ; Wed, 29 Jan 2020 17:52:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="csQrG4ID" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AF6EF206D4 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Rtfm/nywsXsAp8P4COZdivGneDZ161sC4v2hZYXE5bE=; b=csQrG4IDhFRCD9 iM0loFQ8/SVQrFjD/E7uQ/Q8gXhQ7/ZpoBbM4MiErBg0SbNzXJ0aztdMDoqhtgxxNPfSs4Xq5Hkzs 3pPxhWGj929Pd1wNUksIbHz7FjH8F+DutJvkpU8NAkQFq6T0IrqwlD47X1GtudOBIEsfQ5XEJqI+6 35PUZGcEWiMn3Fa6DooQtSIilV5LhNox/MwY6NL+PaWfnGawbEY74LCP6cAUXRUYTqyPpo77iNTzM k25N1CuSOPKeiHFRoYcppvbR2hhL73yINT3H1bfklet54sDM70iN2SLeFsAAZLj6QJ+FFQhXaevpy V/hhHzbTba9WR+8eCr9w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iwrVu-00080G-WB; Wed, 29 Jan 2020 17:52:31 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iwrVr-0007zX-8M for linux-arm-kernel@lists.infradead.org; Wed, 29 Jan 2020 17:52:28 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0EFCC328; Wed, 29 Jan 2020 09:52:25 -0800 (PST) Received: from localhost (unknown [10.1.198.81]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A465B3F67D; Wed, 29 Jan 2020 09:52:24 -0800 (PST) Date: Wed, 29 Jan 2020 17:52:23 +0000 From: Ionela Voinescu To: Valentin Schneider Subject: Re: [PATCH v2 6/6] arm64: use activity monitors for frequency invariance Message-ID: <20200129175223.GA26494@arm.com> References: <20191218182607.21607-1-ionela.voinescu@arm.com> <20191218182607.21607-7-ionela.voinescu@arm.com> <96fdead6-9896-5695-6744-413300d424f5@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <96fdead6-9896-5695-6744-413300d424f5@arm.com> User-Agent: Mutt/1.9.4 (2018-02-28) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200129_095227_385772_F32EF4C1 X-CRM114-Status: GOOD ( 24.37 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, maz@kernel.org, suzuki.poulose@arm.com, peterz@infradead.org, catalin.marinas@arm.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, mingo@redhat.com, ggherdovich@suse.cz, sudeep.holla@arm.com, will@kernel.org, dietmar.eggemann@arm.com, linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org SGkgVmFsZW50aW4sCgpPbiBXZWRuZXNkYXkgMjkgSmFuIDIwMjAgYXQgMTc6MTM6NTMgKCswMDAw KSwgVmFsZW50aW4gU2NobmVpZGVyIHdyb3RlOgo+IE9ubHkgY29tbWVudGluZyBvbiB0aGUgYml0 cyB0aGF0IHNob3VsZCBiZSB0aGVyZSByZWdhcmRsZXNzIG9mIHVzaW5nIHRoZQo+IHdvcmtxdWV1 ZXMgb3Igbm90Owo+IAo+IE9uIDE4LzEyLzIwMTkgMTg6MjYsIElvbmVsYSBWb2luZXNjdSB3cm90 ZToKPiA+ICtzdGF0aWMgdm9pZCBjcHVfYW11X2ZpZV9pbml0X3dvcmtmbihzdHJ1Y3Qgd29ya19z dHJ1Y3QgKndvcmspCj4gPiArewo+ID4gKwl1NjQgY29yZV9jbnQsIGNvbnN0X2NudCwgcmF0aW87 Cj4gPiArCXN0cnVjdCBjcHVfYW11X3dvcmsgKmFtdV93b3JrOwo+ID4gKwlpbnQgY3B1ID0gc21w X3Byb2Nlc3Nvcl9pZCgpOwo+ID4gKwo+ID4gKwlpZiAoIWNwdV9oYXNfYW11X2ZlYXQoKSkgewo+ ID4gKwkJcHJfZGVidWcoIkNQVSVkOiBjb3VudGVycyBhcmUgbm90IHN1cHBvcnRlZC5cbiIsIGNw dSk7Cj4gPiArCQlyZXR1cm47Cj4gPiArCX0KPiA+ICsKPiA+ICsJY29yZV9jbnQgPSByZWFkX3N5 c3JlZ19zKFNZU19BTUVWQ05UUjBfQ09SRV9FTDApOwo+ID4gKwljb25zdF9jbnQgPSByZWFkX3N5 c3JlZ19zKFNZU19BTUVWQ05UUjBfQ09OU1RfRUwwKTsKPiA+ICsKPiA+ICsJaWYgKHVubGlrZWx5 KCFjb3JlX2NudCB8fCAhY29uc3RfY250KSkgewo+ID4gKwkJcHJfZXJyKCJDUFUlZDogY3ljbGUg Y291bnRlcnMgYXJlIG5vdCBlbmFibGVkLlxuIiwgY3B1KTsKPiA+ICsJCXJldHVybjsKPiA+ICsJ fQo+ID4gKwo+ID4gKwlhbXVfd29yayA9IGNvbnRhaW5lcl9vZih3b3JrLCBzdHJ1Y3QgY3B1X2Ft dV93b3JrLCBjcHVfd29yayk7Cj4gPiArCWlmICh1bmxpa2VseSghKGFtdV93b3JrLT5jcHVpbmZv X21heF9mcmVxKSkpIHsKPiA+ICsJCXByX2VycigiQ1BVJWQ6IGludmFsaWQgbWF4aW11bSBmcmVx dWVuY3kuXG4iLCBjcHUpOwo+ID4gKwkJcmV0dXJuOwo+ID4gKwl9Cj4gPiArCj4gPiArCS8qCj4g PiArCSAqIFByZS1jb21wdXRlIHRoZSBmaXhlZCByYXRpbyBiZXR3ZWVuIHRoZSBmcmVxdWVuY3kg b2YgdGhlCj4gPiArCSAqIGNvbnN0YW50IGNvdW50ZXIgYW5kIHRoZSBtYXhpbXVtIGZyZXF1ZW5j eSBvZiB0aGUgQ1BVIChoeikuCj4gCj4gSSBjYW4ndCByZXNpc3Q6IHMvaHovSHovCj4gCj4gPiAr CSAqLwo+ID4gKwlyYXRpbyA9ICh1NjQpYXJjaF90aW1lcl9nZXRfcmF0ZSgpIDw8ICgyICogU0NI RURfQ0FQQUNJVFlfU0hJRlQpOwo+ID4gKwlyYXRpbyA9IGRpdjY0X3U2NChyYXRpbywgYW11X3dv cmstPmNwdWluZm9fbWF4X2ZyZXEgKiAxMDAwKTsKPiAKPiBOaXQ6IHdlJ3JlIG1pc3NpbmcgYSBj b21tZW50IHNvbWV3aGVyZSB0aGF0IHRoZSB1bml0IG9mIHRoaXMgaXMgaW4ga0h6Cj4gKHdoaWNo IGV4cGxhaW5zIHRoZSAqIDEwMDApLgo+IAoKV2lsbCBkbyEgVGhlIHByZXZpb3VzIGNvbW1lbnQg dGhhdCBleHBsYWluZWQgdGhpcyB3YXMgIi4uIHdoaWxlCmVuc3VyaW5nIG1heF9mcmVxIGlzIGNv bnZlcnRlZCB0byBIWi4iLCBidXQgSSBiZWxpZXZlZCBpdCBhcyB0b28KY2xlYXIgYW5kIHJlcGxh Y2VkIGl0IHdpdGggdGhlIG9ic2N1cmUgIihoeikiLiBJJ2xsIHJldmVydCA6KS4KCj4gPiArCXRo aXNfY3B1X3dyaXRlKGFyY2hfbWF4X2ZyZXFfc2NhbGUsICh1bnNpZ25lZCBsb25nKXJhdGlvKTsK PiA+ICsKPiAKPiBPa2F5IHNvIHdoYXQgd2UgZ2V0IGluIHRoZSB0aWNrIGlzOgo+IAo+ICAgL1wg Y29yZQo+ICAgLS0tLS0tLS0KPiAgIC9cIGNvbnN0Cj4gCj4gQW5kIHdlIHdhbnQgdGhhdCB0byBi ZSBTQ0hFRF9DQVBBQ0lUWV9TQ0FMRSB3aGVuIHJ1bm5pbmcgYXQgbWF4IGZyZXEuIElPVyB3ZQo+ IHdhbnQgdG8gdHVybgo+IAo+ICAgbWF4X2ZyZXEKPiAgIC0tLS0tLS0tLS0KPiAgIGNvbnN0X2Zy ZXEKPiAKPiBpbnRvIFNDSEVEX0NBUEFDSVRZX1NDQUxFLCBzbyB3ZSBjYW4ganVzdCBtdWx0aXBs eSB0aGF0IGJ5Ogo+IAo+ICAgY29uc3RfZnJlcQo+ICAgLS0tLS0tLS0tLSAqIFNDSEVEX0NBUEFD SVRZX1NDQUxFCj4gICBtYXhfZnJlcQo+IAo+IEJ1dCB3aGF0IHRoZSByYXRpbyB5b3UgYXJlIHN0 b3JpbmcgaGVyZSBpcyAKPiAKPiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0X2ZyZXEK PiAgIGFyY2hfbWF4X2ZyZXFfc2NhbGUgPSAgIC0tLS0tLS0tLS0gKiBTQ0hFRF9DQVBBQ0lUWV9T Q0FMRcKyCj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4X2ZyZXEKPiAKPiAoYmVjYXVz ZSB4IDw8IDIgKiBTQ0hFRF9DQVBBQ0lUWV9TSElGVCA9PSB4IDw8IDIwKQo+IAo+IAo+IEluIHRv cG9sb2d5X2ZyZXFfc2NhbGVfdGljaygpIHlvdSBlbmQgdXAgZG9pbmcKPiAKPiAgIC9cIGNvcmUg ICBhcmNoX21heF9mcmVxX3NjYWxlCj4gICAtLS0tLS0tICogLS0tLS0tLS0tLS0tLS0tLS0tLS0K PiAgIC9cIGNvbnN0ICBTQ0hFRF9DQVBBQ0lUWV9TQ0FMRQo+IAo+IHdoaWNoIGdpdmVzIHVzIHdo YXQgd2Ugd2FudCAoU0NIRURfQ0FQQUNJVFlfU0NBTEUgYXQgbWF4IGZyZXEpLgo+IAo+IAo+IE5v dywgdGhlIHJlYXNvbiB3aHkgd2UgbXVsdGlwbHkgb3VyIHJhdGlvIGJ5IHRoZSBzcXVhcmUgb2YK PiBTQ0hFRF9DQVBBQ0lUWV9TQ0FMRSB3YXMgbm90IG9idmlvdXMgdG8gbWUsIGJ1dCB5b3UgcG9p bnRlZCBtZSBvdXQgdGhhdCB0aGUKPiBmcmVxdWVuY3kgb2YgdGhlIGFyY2ggdGltZXIgY2FuIGJl ICpyZWFsbHkqIGxvdyBjb21wYXJlZCB0byB0aGUgbWF4IENQVSBmcmVxLgo+IAo+IEZvciBpbnN0 YW5jZSBvbiBoOTYwOgo+IAo+ICAgWyAgICAwLjAwMDAwMF0gYXJjaF90aW1lcjogY3AxNSB0aW1l cihzKSBydW5uaW5nIGF0IDEuOTJNSHogKHBoeXMpCj4gCj4gICAkIHJvb3RAdmFsc2NoLWg5NjA6 fiMgY2F0IC9zeXMvZGV2aWNlcy9zeXN0ZW0vY3B1L2NwdWZyZXEvcG9saWN5NC9jcHVpbmZvX21h eF9mcmVxIAo+ICAgMjM2MjAwMAo+IAo+IFNvIG91ciByYXRpbyB3b3VsZCBiZQo+IAo+ICAgMSc5 MjAnMDAwICogMTAyNAo+ICAgLS0tLS0tLS0tLS0tLS0tLQo+ICAgICAyJzM2MicwMDAnMDAwCj4g Cj4gV2hpY2ggaXMgfjAuODMsIHNvIHRoYXQgYmVjb21lcyBzaW1wbHkgMC4uLgo+IAo+IAo+IEkg aGFkIGEgYnJpZWYgbG9vayBhdCB0aGUgQXJtIEFSTSwgZm9yIHRoZSBhcmNoIHRpbWVyIGl0IHNh eXMgaXQgaXMKPiAidHlwaWNhbGx5IGluIHRoZSByYW5nZSAxLTUwTUh6IiwgYnV0IHRoZW4gYWxz byBnaXZlcyBhbiBleGFtcGxlIHdpdGggMjBLSHoKPiBpbiBhIGxvdy1wb3dlciBtb2RlLgo+IAo+ IElmIHdlIHRha2Ugc2F5IDVHSHogbWF4IENQVSBmcmVxdWVuY3ksIG91ciBsb3dlciBib3VuZCBm b3IgdGhlIGFyY2ggdGltZXIKPiAod2l0aCB0aGF0IFNDSEVEX0NBUEFDSVRZX1NDQUxFwrIgdHJp Y2spIGlzIGFib3V0IH40Ljc2OEtIei4gSXQncyBub3QgKnRvbyoKPiBmYXIgZnJvbSB0aGF0IDIw S0h6LCBidXQgSSdtIG5vdCBzdXJlIHdlIHdvdWxkIGFjdHVhbGx5IGJlIGV4ZWN1dGluZyBzdHVm Zgo+IGluIHRoYXQgbG93LXBvd2VyIG1vZGUuCj4gCj4gTG9uZyBzdG9yeSBzaG9ydCwgd2UncmUg cHJvYmFibHkgZmluZSwgYnV0IGl0IHdvdWxkIG5pY2UgdG8gc2hvdmUgc29tZSBvZgo+IHRoZSBh Ym92ZSBpbnRvIGNvbW1lbnRzIChlc3BlY2lhbGx5IHRoZSBTQ0hFRF9DQVBBQ0lUWV9TQ0FMRcKy IHRyaWNrKQoKT2theSwgSSdsbCBhZGQgc29tZSBvZiB0aGlzIGRvY3VtZW50YXRpb24gYXMgY29t bWVudHMgaW4gdGhlIHBhdGNoZXMuIEkKdGhvdWdodCBhYm91dCBkb2luZyBpdCBidXQgSSB3YXMg bm90IHN1cmUgaXQganVzdGlmaWVkIHRoZSBsaW5lIGNvdW50LgpCdXQgaWYgaXQgc2F2ZXMgcGVv cGxlIGF0IGxlYXN0IHRoZSBoYXNzbGUgdG8gdW5wYWNrIHRoaXMgY29tcHV0YXRpb24gdG8KdW5k ZXJzdGFuZCB0aGUgbG9naWMsIGl0IHdpbGwgYmUgd29ydGggaXQuCgpUaGFuayB5b3UgZm9yIHRo ZSB0aG9yb3VnaCByZXZpZXcsCklvbmVsYS4KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFy bS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9t YWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK