From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 153DA1CFAD; Thu, 7 Mar 2024 07:21:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709796122; cv=none; b=HIcWNokRYYEZeusqZZs4rrMlNapw5F2Uowcyfx8xuqPfMyn2eX+lCukjPo33R3fqr5aIeUBgCfD7uS7Jp5db/mRn1/mMqJUwACCyhgQxFtY3AGqGMHT8zdN9Ho08tWj4KBoietrlNmPWwBdzx0V9KPb0d1Tp9h8yDWpi/KfpDho= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709796122; c=relaxed/simple; bh=IQ7UV1OOTG3Mnp08L8IaLjwv22dHLJaG9E4J67iXGao=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=TyyUUU8lHmEBLKmfZq0FIGFjXRbXCBHwkQqSwE+iwBDEntQfXyjAUyS3SNQ+wGnbmyfOHOE+LHcCuJlwv+xhYxaBjyyuJinbf0nCW9/K5XB0NrMK5E10JEx/xMcO/1m2rcMqsBSX67jAP4qElhwhp9runrgc9omc8zUaJoDHRcA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com 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 42E431FB; Wed, 6 Mar 2024 23:22:29 -0800 (PST) Received: from arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 713713F73F; Wed, 6 Mar 2024 23:21:48 -0800 (PST) Date: Thu, 7 Mar 2024 08:21:07 +0100 From: Beata Michalska To: "lihuisong (C)" Cc: Vanshidhar Konda , Ionela Voinescu , linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rafael@kernel.org, sumitg@nvidia.com, zengheng4@huawei.com, yang@os.amperecomputing.com, will@kernel.org, sudeep.holla@arm.com, liuyonglong@huawei.com, zhanjie9@hisilicon.com, linux-acpi@vger.kernel.org Subject: Re: [PATCH v1 1/3] arm64: topology: Add arch_freq_get_on_cpu() support Message-ID: References: <20240229162520.970986-2-vanshikonda@os.amperecomputing.com> Precedence: bulk X-Mailing-List: linux-acpi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: On Thu, Mar 07, 2024 at 11:20:46AM +0800, lihuisong (C) wrote: > > 在 2024/3/7 6:04, Vanshidhar Konda 写道: > > On Wed, Mar 06, 2024 at 09:24:19AM +0100, Beata Michalska wrote: > > > > > > Hi Vanshidhar, > > > > > > On Thu, Feb 29, 2024 at 08:25:13AM -0800, Vanshidhar Konda wrote: > > > > AMU counters are used by the Frequency Invariance Engine (FIE) to > > > > estimate the CPU utilization during each tick. The delta of the AMU > > > > counters between two ticks can also be used to estimate the average CPU > > > > frequency of each core over the tick duration. Measure the AMU counters > > > > during tick, compute the delta and store it. When the frequency of the > > > > core is queried, use the stored delta to determine the frequency. > > > > > > > > arch_freq_get_on_cpu() is used on x86 systems to estimate the frequency > > > > of each CPU. It can be wired up on arm64 for the same functionality. > > > > > > > > Signed-off-by: Vanshidhar Konda > > > > --- > > > >  arch/arm64/kernel/topology.c | 114 +++++++++++++++++++++++++++++------ > > > >  1 file changed, 96 insertions(+), 18 deletions(-) > > > > > > > > diff --git a/arch/arm64/kernel/topology.c > > > > b/arch/arm64/kernel/topology.c > > > > index 1a2c72f3e7f8..db8d14525cf4 100644 > > > > --- a/arch/arm64/kernel/topology.c > > > > +++ b/arch/arm64/kernel/topology.c > > > > @@ -17,6 +17,8 @@ > > > >  #include > > > >  #include > > > >  #include > > > > +#include > > > > +#include > > > > > > > >  #include > > > >  #include > > > > @@ -82,20 +84,54 @@ int __init parse_acpi_topology(void) > > > >  #undef pr_fmt > > > >  #define pr_fmt(fmt) "AMU: " fmt > > > > > > > > +struct amu_counters { > > > > +    seqcount_t    seq; > > > > +    unsigned long    last_update; > > > > +    u64        core_cnt; > > > > +    u64        const_cnt; > > > > +    u64        delta_core_cnt; > > > > +    u64        delta_const_cnt; > > > > +}; > > > It still might not be necessary to track both last taken sample and > > > deltas from > > > previous ones, see[1]. > > > I could send v3 of [1] and take into account the changes you have > > > suggested here, > > > namely the last tick recorded. Otherwise few comments below. > > > > For this specific patch it might suffice to just track the deltas. The > > reason for storing the core_cnt/const_cnt values is for the case where > > CPU is idle and we are trying to read the read the counters through CPPC > > FFH - see patch 3 of this series. > > > > One of the drawbacks of updating/merging just [1] as a standalone patch > > is > > that it doesn't cover idle or isolated CPUs. This patch series accounts > > for those cases as well. I'm open to suggestions on how we can make that > > happen with [1]. > > > > I tested v2 of [1] on AmpereOne system and noticed that there were some > > inconsistent measurements reported - see [2]. I think that might be due > > to > > frequency scale not being updated when CPU goes idle. > > > > > > + > > > >  /* > > > >   * Ensure that amu_scale_freq_tick() will return > > > > SCHED_CAPACITY_SCALE until > > > >   * the CPU capacity and its associated frequency have been correctly > > > >   * initialized. > > > >   */ > > > > -static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, > > > > arch_max_freq_scale) =  1UL << (2 * SCHED_CAPACITY_SHIFT); > > > > -static DEFINE_PER_CPU(u64, arch_const_cycles_prev); > > > > -static DEFINE_PER_CPU(u64, arch_core_cycles_prev); > > > > +static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, > > > > arch_max_freq_scale) = > > > > +    1UL << (2 * SCHED_CAPACITY_SHIFT); > > > > +static DEFINE_PER_CPU_SHARED_ALIGNED(struct amu_counters, > > > > cpu_samples) = { > > > > +    .seq = SEQCNT_ZERO(cpu_samples.seq) > > > > +}; > > > >  static cpumask_var_t amu_fie_cpus; > > > > > > > >  void update_freq_counters_refs(void) > > > >  { > > > > -    this_cpu_write(arch_core_cycles_prev, read_corecnt()); > > > > -    this_cpu_write(arch_const_cycles_prev, read_constcnt()); > > > > +    struct amu_counters *cpu_sample = this_cpu_ptr(&cpu_samples); > > > > +    u64 core_cnt, const_cnt, delta_core_cnt, delta_const_cnt; > > > > + > > > > +    const_cnt = read_constcnt(); > > > > +    core_cnt = read_corecnt(); > > > > + > > > > +    if (unlikely(core_cnt < cpu_sample->core_cnt) || > > > > +        unlikely(const_cnt < cpu_sample->const_cnt)) { > > > > +        WARN(1, "AMU counter values should be monotonic.\n"); > > > > +        cpu_sample->delta_const_cnt = 0; > > > > +        cpu_sample->delta_core_cnt = 0; > > > Not sure if zero-ing is really necessary here > > > > I can remove that for the next version. > > > > > > +        return; > > > > +    } > > > > + > > > > +    delta_core_cnt = core_cnt - cpu_sample->core_cnt; > > > > +    delta_const_cnt = const_cnt - cpu_sample->const_cnt; > > > > + > > > > +    cpu_sample->core_cnt = core_cnt; > > > > +    cpu_sample->const_cnt = const_cnt; > > > > + > > > > +    raw_write_seqcount_begin(&cpu_sample->seq); > > > > +    cpu_sample->last_update = jiffies; > > > > +    cpu_sample->delta_const_cnt = delta_const_cnt; > > > > +    cpu_sample->delta_core_cnt = delta_core_cnt; > > > > +    raw_write_seqcount_end(&cpu_sample->seq); > > > >  } > > > > > > > >  static inline bool freq_counters_valid(int cpu) > > > > @@ -108,8 +144,7 @@ static inline bool freq_counters_valid(int cpu) > > > >          return false; > > > >      } > > > > > > > > -    if (unlikely(!per_cpu(arch_const_cycles_prev, cpu) || > > > > -             !per_cpu(arch_core_cycles_prev, cpu))) { > > > > +    if (unlikely(per_cpu_ptr(&cpu_samples, cpu) == NULL)) { > > > >          pr_debug("CPU%d: cycle counters are not enabled.\n", cpu); > > > >          return false; > > > >      } > > > > @@ -152,19 +187,15 @@ void freq_inv_set_max_ratio(int cpu, u64 > > > > max_rate) > > > > > > > >  static void amu_scale_freq_tick(void) > > > >  { > > > > -    u64 prev_core_cnt, prev_const_cnt; > > > > -    u64 core_cnt, const_cnt, scale; > > > > - > > > > -    prev_const_cnt = this_cpu_read(arch_const_cycles_prev); > > > > -    prev_core_cnt = this_cpu_read(arch_core_cycles_prev); > > > > +    struct amu_counters *cpu_sample = this_cpu_ptr(&cpu_samples); > > > > +    u64 delta_core_cnt, delta_const_cnt, scale; > > > > > > > >      update_freq_counters_refs(); > > > > > > > > -    const_cnt = this_cpu_read(arch_const_cycles_prev); > > > > -    core_cnt = this_cpu_read(arch_core_cycles_prev); > > > > +    delta_const_cnt = cpu_sample->delta_const_cnt; > > > > +    delta_core_cnt = cpu_sample->delta_core_cnt; > > > > > > > > -    if (unlikely(core_cnt <= prev_core_cnt || > > > > -             const_cnt <= prev_const_cnt)) > > > > +    if ((delta_const_cnt == 0) || (delta_core_cnt == 0)) > > > >          return; > > > > > > > >      /* > > > > @@ -175,15 +206,62 @@ static void amu_scale_freq_tick(void) > > > >       * See validate_cpu_freq_invariance_counters() for details on > > > >       * arch_max_freq_scale and the use of SCHED_CAPACITY_SHIFT. > > > >       */ > > > > -    scale = core_cnt - prev_core_cnt; > > > > +    scale = delta_core_cnt; > > > >      scale *= this_cpu_read(arch_max_freq_scale); > > > >      scale = div64_u64(scale >> SCHED_CAPACITY_SHIFT, > > > > -              const_cnt - prev_const_cnt); > > > > +              delta_const_cnt); > > > > > > > >      scale = min_t(unsigned long, scale, SCHED_CAPACITY_SCALE); > > > >      this_cpu_write(arch_freq_scale, (unsigned long)scale); > > > >  } > > > > > > > > +/* > > > > + * Discard samples older than the define maximum sample age of > > > > 20ms. There > > > > + * is no point in sending IPIs in such a case. If the scheduler > > > > tick was > > > > + * not running then the CPU is either idle or isolated. > > > > + */ > > > > +#define MAX_SAMPLE_AGE    ((unsigned long)HZ / 50) > > > This depends on the config, so for HZ_1000 it will indeed give 20ms, > > > for CONFIG_250 that will be 5ms. It might be better to set it to > > > number of > > > expected missed ticks instead ? Or amend the comment. > > > > I think using jiffies/missed ticks is probably better. I'll update for > > next version. > > > > > > + > > > > +unsigned int arch_freq_get_on_cpu(int cpu) > > > > +{ > > > > +    struct amu_counters *cpu_sample = per_cpu_ptr(&cpu_samples, cpu); > > > > +    u64 delta_const_cnt, delta_core_cnt; > > > > +    unsigned int seq, freq; > > > > +    unsigned long last; > > > > + > > > > +    if (!freq_counters_valid(cpu)) > > > > +        goto fallback; > > > > + > > > > +    do { > > > > +        seq = raw_read_seqcount_begin(&cpu_sample->seq); > > > > +        last = cpu_sample->last_update; > > > > +        delta_core_cnt = cpu_sample->delta_core_cnt; > > > > +        delta_const_cnt = cpu_sample->delta_const_cnt; > > > > +    } while (read_seqcount_retry(&cpu_sample->seq, seq)); > > > > + > > > This seems to be taken from APERF/MPERF relevant code. Including the > > > comments. > > > > Yes. The idea for this patch series is based on APERF/MPERF which are > > quite similar to AMU counters. > > > > > > +    /* > > > > +     * Bail on invalid count and when the last update was too > > > > long ago, > > > > +     * which covers idle and NOHZ full CPUs. > > > > +     */ > > > > +    if (!delta_const_cnt || ((jiffies - last) > MAX_SAMPLE_AGE)) { > > > Shouldn't the first condition (non-zero increase of cnt_cycles counter) > > > disqualify the sample taken altogether ? > > > > I was updating delta_*_cnt values to 0 in one case above. If we just > > drop that sample and don't set delta_*_cnt values to 0 we wouldn't need > > this check. I will remove that in the next version. > > > > > > +        if (!(housekeeping_cpu(cpu, HK_TYPE_TICK) && idle_cpu(cpu))) > > > > +            goto fallback; > > > Not entirely convinced that this condition is what is expected ? > > > For housekeeping cpu that is not idle it will still resolve to AMU > > > counters, > > > not sure if that's what was intended ? > > > > For a CPU that is not idle my preference is that it uses AMU counters > > for frequency measurement. For idle and isolcpus we fallback to the CPPC > > mechanism - which could be through MMIO or PCC. > > > > > Also, for cases when given cpufreq policy spans more than a single > > > core, the > > > frequency might be queried based on relevant CPU that might have > > > seen the tick > > > within specified timeframe (see [1]) > > > > > > > This would not be ideal. On Ampere systems I've not come across a > > cpufreq policy that spans multiple cores, so I overlooked that > > configuration. > > > > > > +    } > > > > + > > > > +    /* > > > > +     * CPU frequency = reference perf (in Hz) * (/\ delivered) > > > > / (/\ reference) > > > > +     * AMU reference performance counter increment rate is > > > > equal to the rate > > > > +     * of increment of the System counter, CNTPCT_EL0 and can > > > > be used to > > > > +     * compute the CPU frequency. > > > > +     */ > > > > +    return div64_u64((delta_core_cnt * (arch_timer_get_rate() / HZ)), > > > /HZ/HZ_PER_KHZ ? > > > > +             delta_const_cnt); > > > > + > > > > +fallback: > > > > +    freq = cpufreq_quick_get(cpu); > > > > +    return freq ? freq : cpufreq_get_hw_max_freq(cpu); > > > If the arch specific code cannot determine the frequency it should > > > actually make > > > it clear by returning '0' instead of trying to patch things up by > > > itself (?) > > > > > > > This was following the same logic as APERF/MPERF logic. Returning 0 from > > here would result in a call to cpufreq_driver->get() vs a call to > > cpufreq_quick_get(). The only difference I can tell is that > > cpufreq_quick_get() will call read_lock_irqsave() before calling > > cpufreq_driver->get(). I don't have enough knowledge to point out > > which one is more appropriate. Following the same logic as the x86 > > implementation seemed more prudent. > > > > > Overall I'd prefer to revive [1] and amened it accordingly instead. > > > > > > > As mentioned earlier, I'm ok with what leads to a coherent solution for > > all the configurations we have - isolcpus, idle and active in > > housekeeping_cpus. > > > > This issue impacts existing Ampere products. It would be great if we > > could arrive at a solution soon. > +1 to have a solution soon, very expecting. @Vanshi and @Beata. Understood. Will prepare new version - should be out by Monday. Apologies for delays on my side. --- BR Beata > > > > > --- > > > [1] https://lore.kernel.org/all/20231127160838.1403404-1-beata.michalska@arm.com/ > > [2] - https://lore.kernel.org/all/7eozim2xnepacnnkzxlbx34hib4otycnbn4dqymfziqou5lw5u@5xzpv3t7sxo3/ > > > > Thanks for the discussion. > > > > Vanshi > > > > > --- > > > Best Regards > > > Beata > > > > +} > > > > + > > > >  static struct scale_freq_data amu_sfd = { > > > >      .source = SCALE_FREQ_SOURCE_ARCH, > > > >      .set_freq_scale = amu_scale_freq_tick, > > > > -- > > > > 2.43.1 > > > > > > . 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 39B7FC54E49 for ; Thu, 7 Mar 2024 07:22:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc: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=jRSXP6olpkUS8g1PUg/YKqS5SdbB7ggiRDR6vnDUUoU=; b=aBOSD1wyiMh6tA sw2Dt/xetx1l+2y4zw2NR4yrlQe1vfJHSamVU5NxefFxKD8iaxPAdXeKFzecy3fiyzbXj87fDzb4w ibSbHIraaUxIT1FrZXW0IiVGYofuqHSvuprSdOyrOXp6lJaQ5+BNZTAWsKz7aT9CHcFtjnimZkNZ4 TBQWpHSvq6ciO2+YvL6J9KPeodTqj+VeHke0SOovmIDeSY9Py32eu4v8Sn2bXG0HOU5vVOajA6ijD sG5n+Rrs/amo5+jVMPZefT3mEr2wGMCz21yH5I4TbTq36ib6yTJO1yohe7HbJE/jxXn7Z4PmmPqLe KRPX+yJKgyjUFiPQkz0w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1ri84j-00000003Pbg-2eNW; Thu, 07 Mar 2024 07:21:57 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1ri84g-00000003PZY-0xEd for linux-arm-kernel@lists.infradead.org; Thu, 07 Mar 2024 07:21:56 +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 42E431FB; Wed, 6 Mar 2024 23:22:29 -0800 (PST) Received: from arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 713713F73F; Wed, 6 Mar 2024 23:21:48 -0800 (PST) Date: Thu, 7 Mar 2024 08:21:07 +0100 From: Beata Michalska To: "lihuisong (C)" Cc: Vanshidhar Konda , Ionela Voinescu , linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rafael@kernel.org, sumitg@nvidia.com, zengheng4@huawei.com, yang@os.amperecomputing.com, will@kernel.org, sudeep.holla@arm.com, liuyonglong@huawei.com, zhanjie9@hisilicon.com, linux-acpi@vger.kernel.org Subject: Re: [PATCH v1 1/3] arm64: topology: Add arch_freq_get_on_cpu() support Message-ID: References: <20240229162520.970986-2-vanshikonda@os.amperecomputing.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240306_232154_404195_F829FE2A X-CRM114-Status: GOOD ( 74.75 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gVGh1LCBNYXIgMDcsIDIwMjQgYXQgMTE6MjA6NDZBTSArMDgwMCwgbGlodWlzb25nIChDKSB3 cm90ZToKPiAKPiDlnKggMjAyNC8zLzcgNjowNCwgVmFuc2hpZGhhciBLb25kYSDlhpnpgZM6Cj4g PiBPbiBXZWQsIE1hciAwNiwgMjAyNCBhdCAwOToyNDoxOUFNICswMTAwLCBCZWF0YSBNaWNoYWxz a2Egd3JvdGU6Cj4gPiA+IAo+ID4gPiBIaSBWYW5zaGlkaGFyLAo+ID4gPiAKPiA+ID4gT24gVGh1 LCBGZWIgMjksIDIwMjQgYXQgMDg6MjU6MTNBTSAtMDgwMCwgVmFuc2hpZGhhciBLb25kYSB3cm90 ZToKPiA+ID4gPiBBTVUgY291bnRlcnMgYXJlIHVzZWQgYnkgdGhlIEZyZXF1ZW5jeSBJbnZhcmlh bmNlIEVuZ2luZSAoRklFKSB0bwo+ID4gPiA+IGVzdGltYXRlIHRoZSBDUFUgdXRpbGl6YXRpb24g ZHVyaW5nIGVhY2ggdGljay4gVGhlIGRlbHRhIG9mIHRoZSBBTVUKPiA+ID4gPiBjb3VudGVycyBi ZXR3ZWVuIHR3byB0aWNrcyBjYW4gYWxzbyBiZSB1c2VkIHRvIGVzdGltYXRlIHRoZSBhdmVyYWdl IENQVQo+ID4gPiA+IGZyZXF1ZW5jeSBvZiBlYWNoIGNvcmUgb3ZlciB0aGUgdGljayBkdXJhdGlv bi4gTWVhc3VyZSB0aGUgQU1VIGNvdW50ZXJzCj4gPiA+ID4gZHVyaW5nIHRpY2ssIGNvbXB1dGUg dGhlIGRlbHRhIGFuZCBzdG9yZSBpdC4gV2hlbiB0aGUgZnJlcXVlbmN5IG9mIHRoZQo+ID4gPiA+ IGNvcmUgaXMgcXVlcmllZCwgdXNlIHRoZSBzdG9yZWQgZGVsdGEgdG8gZGV0ZXJtaW5lIHRoZSBm cmVxdWVuY3kuCj4gPiA+ID4gCj4gPiA+ID4gYXJjaF9mcmVxX2dldF9vbl9jcHUoKSBpcyB1c2Vk IG9uIHg4NiBzeXN0ZW1zIHRvIGVzdGltYXRlIHRoZSBmcmVxdWVuY3kKPiA+ID4gPiBvZiBlYWNo IENQVS4gSXQgY2FuIGJlIHdpcmVkIHVwIG9uIGFybTY0IGZvciB0aGUgc2FtZSBmdW5jdGlvbmFs aXR5Lgo+ID4gPiA+IAo+ID4gPiA+IFNpZ25lZC1vZmYtYnk6IFZhbnNoaWRoYXIgS29uZGEgPHZh bnNoaWtvbmRhQG9zLmFtcGVyZWNvbXB1dGluZy5jb20+Cj4gPiA+ID4gLS0tCj4gPiA+ID4gwqBh cmNoL2FybTY0L2tlcm5lbC90b3BvbG9neS5jIHwgMTE0ICsrKysrKysrKysrKysrKysrKysrKysr KysrKysrLS0tLS0tCj4gPiA+ID4gwqAxIGZpbGUgY2hhbmdlZCwgOTYgaW5zZXJ0aW9ucygrKSwg MTggZGVsZXRpb25zKC0pCj4gPiA+ID4gCj4gPiA+ID4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtNjQv a2VybmVsL3RvcG9sb2d5LmMKPiA+ID4gPiBiL2FyY2gvYXJtNjQva2VybmVsL3RvcG9sb2d5LmMK PiA+ID4gPiBpbmRleCAxYTJjNzJmM2U3ZjguLmRiOGQxNDUyNWNmNCAxMDA2NDQKPiA+ID4gPiAt LS0gYS9hcmNoL2FybTY0L2tlcm5lbC90b3BvbG9neS5jCj4gPiA+ID4gKysrIGIvYXJjaC9hcm02 NC9rZXJuZWwvdG9wb2xvZ3kuYwo+ID4gPiA+IEBAIC0xNyw2ICsxNyw4IEBACj4gPiA+ID4gwqAj aW5jbHVkZSA8bGludXgvY3B1ZnJlcS5oPgo+ID4gPiA+IMKgI2luY2x1ZGUgPGxpbnV4L2luaXQu aD4KPiA+ID4gPiDCoCNpbmNsdWRlIDxsaW51eC9wZXJjcHUuaD4KPiA+ID4gPiArI2luY2x1ZGUg PGxpbnV4L3NjaGVkL2lzb2xhdGlvbi5oPgo+ID4gPiA+ICsjaW5jbHVkZSA8bGludXgvc2VxbG9j a190eXBlcy5oPgo+ID4gPiA+IAo+ID4gPiA+IMKgI2luY2x1ZGUgPGFzbS9jcHUuaD4KPiA+ID4g PiDCoCNpbmNsdWRlIDxhc20vY3B1dHlwZS5oPgo+ID4gPiA+IEBAIC04MiwyMCArODQsNTQgQEAg aW50IF9faW5pdCBwYXJzZV9hY3BpX3RvcG9sb2d5KHZvaWQpCj4gPiA+ID4gwqAjdW5kZWYgcHJf Zm10Cj4gPiA+ID4gwqAjZGVmaW5lIHByX2ZtdChmbXQpICJBTVU6ICIgZm10Cj4gPiA+ID4gCj4g PiA+ID4gK3N0cnVjdCBhbXVfY291bnRlcnMgewo+ID4gPiA+ICvCoMKgwqAgc2VxY291bnRfdMKg wqDCoCBzZXE7Cj4gPiA+ID4gK8KgwqDCoCB1bnNpZ25lZCBsb25nwqDCoMKgIGxhc3RfdXBkYXRl Owo+ID4gPiA+ICvCoMKgwqAgdTY0wqDCoMKgwqDCoMKgwqAgY29yZV9jbnQ7Cj4gPiA+ID4gK8Kg wqDCoCB1NjTCoMKgwqDCoMKgwqDCoCBjb25zdF9jbnQ7Cj4gPiA+ID4gK8KgwqDCoCB1NjTCoMKg wqDCoMKgwqDCoCBkZWx0YV9jb3JlX2NudDsKPiA+ID4gPiArwqDCoMKgIHU2NMKgwqDCoMKgwqDC oMKgIGRlbHRhX2NvbnN0X2NudDsKPiA+ID4gPiArfTsKPiA+ID4gSXQgc3RpbGwgbWlnaHQgbm90 IGJlIG5lY2Vzc2FyeSB0byB0cmFjayBib3RoIGxhc3QgdGFrZW4gc2FtcGxlIGFuZAo+ID4gPiBk ZWx0YXMgZnJvbQo+ID4gPiBwcmV2aW91cyBvbmVzLCBzZWVbMV0uCj4gPiA+IEkgY291bGQgc2Vu ZCB2MyBvZiBbMV0gYW5kIHRha2UgaW50byBhY2NvdW50IHRoZSBjaGFuZ2VzIHlvdSBoYXZlCj4g PiA+IHN1Z2dlc3RlZCBoZXJlLAo+ID4gPiBuYW1lbHkgdGhlIGxhc3QgdGljayByZWNvcmRlZC4g T3RoZXJ3aXNlIGZldyBjb21tZW50cyBiZWxvdy4KPiA+IAo+ID4gRm9yIHRoaXMgc3BlY2lmaWMg cGF0Y2ggaXQgbWlnaHQgc3VmZmljZSB0byBqdXN0IHRyYWNrIHRoZSBkZWx0YXMuIFRoZQo+ID4g cmVhc29uIGZvciBzdG9yaW5nIHRoZSBjb3JlX2NudC9jb25zdF9jbnQgdmFsdWVzIGlzIGZvciB0 aGUgY2FzZSB3aGVyZQo+ID4gQ1BVIGlzIGlkbGUgYW5kIHdlIGFyZSB0cnlpbmcgdG8gcmVhZCB0 aGUgcmVhZCB0aGUgY291bnRlcnMgdGhyb3VnaCBDUFBDCj4gPiBGRkggLSBzZWUgcGF0Y2ggMyBv ZiB0aGlzIHNlcmllcy4KPiA+IAo+ID4gT25lIG9mIHRoZSBkcmF3YmFja3Mgb2YgdXBkYXRpbmcv bWVyZ2luZyBqdXN0IFsxXSBhcyBhIHN0YW5kYWxvbmUgcGF0Y2gKPiA+IGlzCj4gPiB0aGF0IGl0 IGRvZXNuJ3QgY292ZXIgaWRsZSBvciBpc29sYXRlZCBDUFVzLiBUaGlzIHBhdGNoIHNlcmllcyBh Y2NvdW50cwo+ID4gZm9yIHRob3NlIGNhc2VzIGFzIHdlbGwuIEknbSBvcGVuIHRvIHN1Z2dlc3Rp b25zIG9uIGhvdyB3ZSBjYW4gbWFrZSB0aGF0Cj4gPiBoYXBwZW4gd2l0aCBbMV0uCj4gPiAKPiA+ IEkgdGVzdGVkIHYyIG9mIFsxXSBvbiBBbXBlcmVPbmUgc3lzdGVtIGFuZCBub3RpY2VkIHRoYXQg dGhlcmUgd2VyZSBzb21lCj4gPiBpbmNvbnNpc3RlbnQgbWVhc3VyZW1lbnRzIHJlcG9ydGVkIC0g c2VlIFsyXS4gSSB0aGluayB0aGF0IG1pZ2h0IGJlIGR1ZQo+ID4gdG8KPiA+IGZyZXF1ZW5jeSBz Y2FsZSBub3QgYmVpbmcgdXBkYXRlZCB3aGVuIENQVSBnb2VzIGlkbGUuCj4gPiAKPiA+ID4gPiAr Cj4gPiA+ID4gwqAvKgo+ID4gPiA+IMKgICogRW5zdXJlIHRoYXQgYW11X3NjYWxlX2ZyZXFfdGlj aygpIHdpbGwgcmV0dXJuCj4gPiA+ID4gU0NIRURfQ0FQQUNJVFlfU0NBTEUgdW50aWwKPiA+ID4g PiDCoCAqIHRoZSBDUFUgY2FwYWNpdHkgYW5kIGl0cyBhc3NvY2lhdGVkIGZyZXF1ZW5jeSBoYXZl IGJlZW4gY29ycmVjdGx5Cj4gPiA+ID4gwqAgKiBpbml0aWFsaXplZC4KPiA+ID4gPiDCoCAqLwo+ ID4gPiA+IC1zdGF0aWMgREVGSU5FX1BFUl9DUFVfUkVBRF9NT1NUTFkodW5zaWduZWQgbG9uZywK PiA+ID4gPiBhcmNoX21heF9mcmVxX3NjYWxlKSA9wqAgMVVMIDw8ICgyICogU0NIRURfQ0FQQUNJ VFlfU0hJRlQpOwo+ID4gPiA+IC1zdGF0aWMgREVGSU5FX1BFUl9DUFUodTY0LCBhcmNoX2NvbnN0 X2N5Y2xlc19wcmV2KTsKPiA+ID4gPiAtc3RhdGljIERFRklORV9QRVJfQ1BVKHU2NCwgYXJjaF9j b3JlX2N5Y2xlc19wcmV2KTsKPiA+ID4gPiArc3RhdGljIERFRklORV9QRVJfQ1BVX1JFQURfTU9T VExZKHVuc2lnbmVkIGxvbmcsCj4gPiA+ID4gYXJjaF9tYXhfZnJlcV9zY2FsZSkgPQo+ID4gPiA+ ICvCoMKgwqAgMVVMIDw8ICgyICogU0NIRURfQ0FQQUNJVFlfU0hJRlQpOwo+ID4gPiA+ICtzdGF0 aWMgREVGSU5FX1BFUl9DUFVfU0hBUkVEX0FMSUdORUQoc3RydWN0IGFtdV9jb3VudGVycywKPiA+ ID4gPiBjcHVfc2FtcGxlcykgPSB7Cj4gPiA+ID4gK8KgwqDCoCAuc2VxID0gU0VRQ05UX1pFUk8o Y3B1X3NhbXBsZXMuc2VxKQo+ID4gPiA+ICt9Owo+ID4gPiA+IMKgc3RhdGljIGNwdW1hc2tfdmFy X3QgYW11X2ZpZV9jcHVzOwo+ID4gPiA+IAo+ID4gPiA+IMKgdm9pZCB1cGRhdGVfZnJlcV9jb3Vu dGVyc19yZWZzKHZvaWQpCj4gPiA+ID4gwqB7Cj4gPiA+ID4gLcKgwqDCoCB0aGlzX2NwdV93cml0 ZShhcmNoX2NvcmVfY3ljbGVzX3ByZXYsIHJlYWRfY29yZWNudCgpKTsKPiA+ID4gPiAtwqDCoMKg IHRoaXNfY3B1X3dyaXRlKGFyY2hfY29uc3RfY3ljbGVzX3ByZXYsIHJlYWRfY29uc3RjbnQoKSk7 Cj4gPiA+ID4gK8KgwqDCoCBzdHJ1Y3QgYW11X2NvdW50ZXJzICpjcHVfc2FtcGxlID0gdGhpc19j cHVfcHRyKCZjcHVfc2FtcGxlcyk7Cj4gPiA+ID4gK8KgwqDCoCB1NjQgY29yZV9jbnQsIGNvbnN0 X2NudCwgZGVsdGFfY29yZV9jbnQsIGRlbHRhX2NvbnN0X2NudDsKPiA+ID4gPiArCj4gPiA+ID4g K8KgwqDCoCBjb25zdF9jbnQgPSByZWFkX2NvbnN0Y250KCk7Cj4gPiA+ID4gK8KgwqDCoCBjb3Jl X2NudCA9IHJlYWRfY29yZWNudCgpOwo+ID4gPiA+ICsKPiA+ID4gPiArwqDCoMKgIGlmICh1bmxp a2VseShjb3JlX2NudCA8IGNwdV9zYW1wbGUtPmNvcmVfY250KSB8fAo+ID4gPiA+ICvCoMKgwqDC oMKgwqDCoCB1bmxpa2VseShjb25zdF9jbnQgPCBjcHVfc2FtcGxlLT5jb25zdF9jbnQpKSB7Cj4g PiA+ID4gK8KgwqDCoMKgwqDCoMKgIFdBUk4oMSwgIkFNVSBjb3VudGVyIHZhbHVlcyBzaG91bGQg YmUgbW9ub3RvbmljLlxuIik7Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgIGNwdV9zYW1wbGUtPmRl bHRhX2NvbnN0X2NudCA9IDA7Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgIGNwdV9zYW1wbGUtPmRl bHRhX2NvcmVfY250ID0gMDsKPiA+ID4gTm90IHN1cmUgaWYgemVyby1pbmcgaXMgcmVhbGx5IG5l Y2Vzc2FyeSBoZXJlCj4gPiAKPiA+IEkgY2FuIHJlbW92ZSB0aGF0IGZvciB0aGUgbmV4dCB2ZXJz aW9uLgo+ID4gCj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgIHJldHVybjsKPiA+ID4gPiArwqDCoMKg IH0KPiA+ID4gPiArCj4gPiA+ID4gK8KgwqDCoCBkZWx0YV9jb3JlX2NudCA9IGNvcmVfY250IC0g Y3B1X3NhbXBsZS0+Y29yZV9jbnQ7Cj4gPiA+ID4gK8KgwqDCoCBkZWx0YV9jb25zdF9jbnQgPSBj b25zdF9jbnQgLSBjcHVfc2FtcGxlLT5jb25zdF9jbnQ7Cj4gPiA+ID4gKwo+ID4gPiA+ICvCoMKg wqAgY3B1X3NhbXBsZS0+Y29yZV9jbnQgPSBjb3JlX2NudDsKPiA+ID4gPiArwqDCoMKgIGNwdV9z YW1wbGUtPmNvbnN0X2NudCA9IGNvbnN0X2NudDsKPiA+ID4gPiArCj4gPiA+ID4gK8KgwqDCoCBy YXdfd3JpdGVfc2VxY291bnRfYmVnaW4oJmNwdV9zYW1wbGUtPnNlcSk7Cj4gPiA+ID4gK8KgwqDC oCBjcHVfc2FtcGxlLT5sYXN0X3VwZGF0ZSA9IGppZmZpZXM7Cj4gPiA+ID4gK8KgwqDCoCBjcHVf c2FtcGxlLT5kZWx0YV9jb25zdF9jbnQgPSBkZWx0YV9jb25zdF9jbnQ7Cj4gPiA+ID4gK8KgwqDC oCBjcHVfc2FtcGxlLT5kZWx0YV9jb3JlX2NudCA9IGRlbHRhX2NvcmVfY250Owo+ID4gPiA+ICvC oMKgwqAgcmF3X3dyaXRlX3NlcWNvdW50X2VuZCgmY3B1X3NhbXBsZS0+c2VxKTsKPiA+ID4gPiDC oH0KPiA+ID4gPiAKPiA+ID4gPiDCoHN0YXRpYyBpbmxpbmUgYm9vbCBmcmVxX2NvdW50ZXJzX3Zh bGlkKGludCBjcHUpCj4gPiA+ID4gQEAgLTEwOCw4ICsxNDQsNyBAQCBzdGF0aWMgaW5saW5lIGJv b2wgZnJlcV9jb3VudGVyc192YWxpZChpbnQgY3B1KQo+ID4gPiA+IMKgwqDCoMKgwqDCoMKgwqAg cmV0dXJuIGZhbHNlOwo+ID4gPiA+IMKgwqDCoMKgIH0KPiA+ID4gPiAKPiA+ID4gPiAtwqDCoMKg IGlmICh1bmxpa2VseSghcGVyX2NwdShhcmNoX2NvbnN0X2N5Y2xlc19wcmV2LCBjcHUpIHx8Cj4g PiA+ID4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAhcGVyX2NwdShhcmNoX2NvcmVfY3ljbGVz X3ByZXYsIGNwdSkpKSB7Cj4gPiA+ID4gK8KgwqDCoCBpZiAodW5saWtlbHkocGVyX2NwdV9wdHIo JmNwdV9zYW1wbGVzLCBjcHUpID09IE5VTEwpKSB7Cj4gPiA+ID4gwqDCoMKgwqDCoMKgwqDCoCBw cl9kZWJ1ZygiQ1BVJWQ6IGN5Y2xlIGNvdW50ZXJzIGFyZSBub3QgZW5hYmxlZC5cbiIsIGNwdSk7 Cj4gPiA+ID4gwqDCoMKgwqDCoMKgwqDCoCByZXR1cm4gZmFsc2U7Cj4gPiA+ID4gwqDCoMKgwqAg fQo+ID4gPiA+IEBAIC0xNTIsMTkgKzE4NywxNSBAQCB2b2lkIGZyZXFfaW52X3NldF9tYXhfcmF0 aW8oaW50IGNwdSwgdTY0Cj4gPiA+ID4gbWF4X3JhdGUpCj4gPiA+ID4gCj4gPiA+ID4gwqBzdGF0 aWMgdm9pZCBhbXVfc2NhbGVfZnJlcV90aWNrKHZvaWQpCj4gPiA+ID4gwqB7Cj4gPiA+ID4gLcKg wqDCoCB1NjQgcHJldl9jb3JlX2NudCwgcHJldl9jb25zdF9jbnQ7Cj4gPiA+ID4gLcKgwqDCoCB1 NjQgY29yZV9jbnQsIGNvbnN0X2NudCwgc2NhbGU7Cj4gPiA+ID4gLQo+ID4gPiA+IC3CoMKgwqAg cHJldl9jb25zdF9jbnQgPSB0aGlzX2NwdV9yZWFkKGFyY2hfY29uc3RfY3ljbGVzX3ByZXYpOwo+ ID4gPiA+IC3CoMKgwqAgcHJldl9jb3JlX2NudCA9IHRoaXNfY3B1X3JlYWQoYXJjaF9jb3JlX2N5 Y2xlc19wcmV2KTsKPiA+ID4gPiArwqDCoMKgIHN0cnVjdCBhbXVfY291bnRlcnMgKmNwdV9zYW1w bGUgPSB0aGlzX2NwdV9wdHIoJmNwdV9zYW1wbGVzKTsKPiA+ID4gPiArwqDCoMKgIHU2NCBkZWx0 YV9jb3JlX2NudCwgZGVsdGFfY29uc3RfY250LCBzY2FsZTsKPiA+ID4gPiAKPiA+ID4gPiDCoMKg wqDCoCB1cGRhdGVfZnJlcV9jb3VudGVyc19yZWZzKCk7Cj4gPiA+ID4gCj4gPiA+ID4gLcKgwqDC oCBjb25zdF9jbnQgPSB0aGlzX2NwdV9yZWFkKGFyY2hfY29uc3RfY3ljbGVzX3ByZXYpOwo+ID4g PiA+IC3CoMKgwqAgY29yZV9jbnQgPSB0aGlzX2NwdV9yZWFkKGFyY2hfY29yZV9jeWNsZXNfcHJl dik7Cj4gPiA+ID4gK8KgwqDCoCBkZWx0YV9jb25zdF9jbnQgPSBjcHVfc2FtcGxlLT5kZWx0YV9j b25zdF9jbnQ7Cj4gPiA+ID4gK8KgwqDCoCBkZWx0YV9jb3JlX2NudCA9IGNwdV9zYW1wbGUtPmRl bHRhX2NvcmVfY250Owo+ID4gPiA+IAo+ID4gPiA+IC3CoMKgwqAgaWYgKHVubGlrZWx5KGNvcmVf Y250IDw9IHByZXZfY29yZV9jbnQgfHwKPiA+ID4gPiAtwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg IGNvbnN0X2NudCA8PSBwcmV2X2NvbnN0X2NudCkpCj4gPiA+ID4gK8KgwqDCoCBpZiAoKGRlbHRh X2NvbnN0X2NudCA9PSAwKSB8fCAoZGVsdGFfY29yZV9jbnQgPT0gMCkpCj4gPiA+ID4gwqDCoMKg wqDCoMKgwqDCoCByZXR1cm47Cj4gPiA+ID4gCj4gPiA+ID4gwqDCoMKgwqAgLyoKPiA+ID4gPiBA QCAtMTc1LDE1ICsyMDYsNjIgQEAgc3RhdGljIHZvaWQgYW11X3NjYWxlX2ZyZXFfdGljayh2b2lk KQo+ID4gPiA+IMKgwqDCoMKgwqAgKiBTZWUgdmFsaWRhdGVfY3B1X2ZyZXFfaW52YXJpYW5jZV9j b3VudGVycygpIGZvciBkZXRhaWxzIG9uCj4gPiA+ID4gwqDCoMKgwqDCoCAqIGFyY2hfbWF4X2Zy ZXFfc2NhbGUgYW5kIHRoZSB1c2Ugb2YgU0NIRURfQ0FQQUNJVFlfU0hJRlQuCj4gPiA+ID4gwqDC oMKgwqDCoCAqLwo+ID4gPiA+IC3CoMKgwqAgc2NhbGUgPSBjb3JlX2NudCAtIHByZXZfY29yZV9j bnQ7Cj4gPiA+ID4gK8KgwqDCoCBzY2FsZSA9IGRlbHRhX2NvcmVfY250Owo+ID4gPiA+IMKgwqDC oMKgIHNjYWxlICo9IHRoaXNfY3B1X3JlYWQoYXJjaF9tYXhfZnJlcV9zY2FsZSk7Cj4gPiA+ID4g wqDCoMKgwqAgc2NhbGUgPSBkaXY2NF91NjQoc2NhbGUgPj4gU0NIRURfQ0FQQUNJVFlfU0hJRlQs Cj4gPiA+ID4gLcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGNvbnN0X2NudCAtIHByZXZfY29u c3RfY250KTsKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZGVsdGFfY29uc3Rf Y250KTsKPiA+ID4gPiAKPiA+ID4gPiDCoMKgwqDCoCBzY2FsZSA9IG1pbl90KHVuc2lnbmVkIGxv bmcsIHNjYWxlLCBTQ0hFRF9DQVBBQ0lUWV9TQ0FMRSk7Cj4gPiA+ID4gwqDCoMKgwqAgdGhpc19j cHVfd3JpdGUoYXJjaF9mcmVxX3NjYWxlLCAodW5zaWduZWQgbG9uZylzY2FsZSk7Cj4gPiA+ID4g wqB9Cj4gPiA+ID4gCj4gPiA+ID4gKy8qCj4gPiA+ID4gKyAqIERpc2NhcmQgc2FtcGxlcyBvbGRl ciB0aGFuIHRoZSBkZWZpbmUgbWF4aW11bSBzYW1wbGUgYWdlIG9mCj4gPiA+ID4gMjBtcy4gVGhl cmUKPiA+ID4gPiArICogaXMgbm8gcG9pbnQgaW4gc2VuZGluZyBJUElzIGluIHN1Y2ggYSBjYXNl LiBJZiB0aGUgc2NoZWR1bGVyCj4gPiA+ID4gdGljayB3YXMKPiA+ID4gPiArICogbm90IHJ1bm5p bmcgdGhlbiB0aGUgQ1BVIGlzIGVpdGhlciBpZGxlIG9yIGlzb2xhdGVkLgo+ID4gPiA+ICsgKi8K PiA+ID4gPiArI2RlZmluZSBNQVhfU0FNUExFX0FHRcKgwqDCoCAoKHVuc2lnbmVkIGxvbmcpSFog LyA1MCkKPiA+ID4gVGhpcyBkZXBlbmRzIG9uIHRoZSBjb25maWcsIHNvIGZvciBIWl8xMDAwIGl0 IHdpbGwgaW5kZWVkIGdpdmUgMjBtcywKPiA+ID4gZm9yIENPTkZJR18yNTAgdGhhdCB3aWxsIGJl IDVtcy4gSXQgbWlnaHQgYmUgYmV0dGVyIHRvIHNldCBpdCB0bwo+ID4gPiBudW1iZXIgb2YKPiA+ ID4gZXhwZWN0ZWQgbWlzc2VkIHRpY2tzIGluc3RlYWQgPyBPciBhbWVuZCB0aGUgY29tbWVudC4K PiA+IAo+ID4gSSB0aGluayB1c2luZyBqaWZmaWVzL21pc3NlZCB0aWNrcyBpcyBwcm9iYWJseSBi ZXR0ZXIuIEknbGwgdXBkYXRlIGZvcgo+ID4gbmV4dCB2ZXJzaW9uLgo+ID4gCj4gPiA+ID4gKwo+ ID4gPiA+ICt1bnNpZ25lZCBpbnQgYXJjaF9mcmVxX2dldF9vbl9jcHUoaW50IGNwdSkKPiA+ID4g PiArewo+ID4gPiA+ICvCoMKgwqAgc3RydWN0IGFtdV9jb3VudGVycyAqY3B1X3NhbXBsZSA9IHBl cl9jcHVfcHRyKCZjcHVfc2FtcGxlcywgY3B1KTsKPiA+ID4gPiArwqDCoMKgIHU2NCBkZWx0YV9j b25zdF9jbnQsIGRlbHRhX2NvcmVfY250Owo+ID4gPiA+ICvCoMKgwqAgdW5zaWduZWQgaW50IHNl cSwgZnJlcTsKPiA+ID4gPiArwqDCoMKgIHVuc2lnbmVkIGxvbmcgbGFzdDsKPiA+ID4gPiArCj4g PiA+ID4gK8KgwqDCoCBpZiAoIWZyZXFfY291bnRlcnNfdmFsaWQoY3B1KSkKPiA+ID4gPiArwqDC oMKgwqDCoMKgwqAgZ290byBmYWxsYmFjazsKPiA+ID4gPiArCj4gPiA+ID4gK8KgwqDCoCBkbyB7 Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgIHNlcSA9IHJhd19yZWFkX3NlcWNvdW50X2JlZ2luKCZj cHVfc2FtcGxlLT5zZXEpOwo+ID4gPiA+ICvCoMKgwqDCoMKgwqDCoCBsYXN0ID0gY3B1X3NhbXBs ZS0+bGFzdF91cGRhdGU7Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgIGRlbHRhX2NvcmVfY250ID0g Y3B1X3NhbXBsZS0+ZGVsdGFfY29yZV9jbnQ7Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgIGRlbHRh X2NvbnN0X2NudCA9IGNwdV9zYW1wbGUtPmRlbHRhX2NvbnN0X2NudDsKPiA+ID4gPiArwqDCoMKg IH0gd2hpbGUgKHJlYWRfc2VxY291bnRfcmV0cnkoJmNwdV9zYW1wbGUtPnNlcSwgc2VxKSk7Cj4g PiA+ID4gKwo+ID4gPiBUaGlzIHNlZW1zIHRvIGJlIHRha2VuIGZyb20gQVBFUkYvTVBFUkYgcmVs ZXZhbnQgY29kZS4gSW5jbHVkaW5nIHRoZQo+ID4gPiBjb21tZW50cy4KPiA+IAo+ID4gWWVzLiBU aGUgaWRlYSBmb3IgdGhpcyBwYXRjaCBzZXJpZXMgaXMgYmFzZWQgb24gQVBFUkYvTVBFUkYgd2hp Y2ggYXJlCj4gPiBxdWl0ZSBzaW1pbGFyIHRvIEFNVSBjb3VudGVycy4KPiA+IAo+ID4gPiA+ICvC oMKgwqAgLyoKPiA+ID4gPiArwqDCoMKgwqAgKiBCYWlsIG9uIGludmFsaWQgY291bnQgYW5kIHdo ZW4gdGhlIGxhc3QgdXBkYXRlIHdhcyB0b28KPiA+ID4gPiBsb25nIGFnbywKPiA+ID4gPiArwqDC oMKgwqAgKiB3aGljaCBjb3ZlcnMgaWRsZSBhbmQgTk9IWiBmdWxsIENQVXMuCj4gPiA+ID4gK8Kg wqDCoMKgICovCj4gPiA+ID4gK8KgwqDCoCBpZiAoIWRlbHRhX2NvbnN0X2NudCB8fCAoKGppZmZp ZXMgLSBsYXN0KSA+IE1BWF9TQU1QTEVfQUdFKSkgewo+ID4gPiBTaG91bGRuJ3QgdGhlIGZpcnN0 IGNvbmRpdGlvbiAobm9uLXplcm8gaW5jcmVhc2Ugb2YgY250X2N5Y2xlcyBjb3VudGVyKQo+ID4g PiBkaXNxdWFsaWZ5IHRoZSBzYW1wbGUgdGFrZW4gYWx0b2dldGhlciA/Cj4gPiAKPiA+IEkgd2Fz IHVwZGF0aW5nIGRlbHRhXypfY250IHZhbHVlcyB0byAwIGluIG9uZSBjYXNlIGFib3ZlLiBJZiB3 ZSBqdXN0Cj4gPiBkcm9wIHRoYXQgc2FtcGxlIGFuZCBkb24ndCBzZXQgZGVsdGFfKl9jbnQgdmFs dWVzIHRvIDAgd2Ugd291bGRuJ3QgbmVlZAo+ID4gdGhpcyBjaGVjay4gSSB3aWxsIHJlbW92ZSB0 aGF0IGluIHRoZSBuZXh0IHZlcnNpb24uCj4gPiAKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqAgaWYg KCEoaG91c2VrZWVwaW5nX2NwdShjcHUsIEhLX1RZUEVfVElDSykgJiYgaWRsZV9jcHUoY3B1KSkp Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZ290byBmYWxsYmFjazsKPiA+ID4gTm90 IGVudGlyZWx5IGNvbnZpbmNlZCB0aGF0IHRoaXMgY29uZGl0aW9uIGlzIHdoYXQgaXMgZXhwZWN0 ZWQgPwo+ID4gPiBGb3IgaG91c2VrZWVwaW5nIGNwdSB0aGF0IGlzIG5vdCBpZGxlIGl0IHdpbGwg c3RpbGwgcmVzb2x2ZSB0byBBTVUKPiA+ID4gY291bnRlcnMsCj4gPiA+IG5vdCBzdXJlIGlmIHRo YXQncyB3aGF0IHdhcyBpbnRlbmRlZCA/Cj4gPiAKPiA+IEZvciBhIENQVSB0aGF0IGlzIG5vdCBp ZGxlIG15IHByZWZlcmVuY2UgaXMgdGhhdCBpdCB1c2VzIEFNVSBjb3VudGVycwo+ID4gZm9yIGZy ZXF1ZW5jeSBtZWFzdXJlbWVudC4gRm9yIGlkbGUgYW5kIGlzb2xjcHVzIHdlIGZhbGxiYWNrIHRv IHRoZSBDUFBDCj4gPiBtZWNoYW5pc20gLSB3aGljaCBjb3VsZCBiZSB0aHJvdWdoIE1NSU8gb3Ig UENDLgo+ID4gCj4gPiA+IEFsc28sIGZvciBjYXNlcyB3aGVuIGdpdmVuIGNwdWZyZXEgcG9saWN5 IHNwYW5zIG1vcmUgdGhhbiBhIHNpbmdsZQo+ID4gPiBjb3JlLCB0aGUKPiA+ID4gZnJlcXVlbmN5 IG1pZ2h0IGJlIHF1ZXJpZWQgYmFzZWQgb24gcmVsZXZhbnQgQ1BVIHRoYXQgbWlnaHQgaGF2ZQo+ ID4gPiBzZWVuIHRoZSB0aWNrCj4gPiA+IHdpdGhpbiBzcGVjaWZpZWQgdGltZWZyYW1lIChzZWUg WzFdKQo+ID4gPiAKPiA+IAo+ID4gVGhpcyB3b3VsZCBub3QgYmUgaWRlYWwuIE9uIEFtcGVyZSBz eXN0ZW1zIEkndmUgbm90IGNvbWUgYWNyb3NzIGEKPiA+IGNwdWZyZXEgcG9saWN5IHRoYXQgc3Bh bnMgbXVsdGlwbGUgY29yZXMsIHNvIEkgb3Zlcmxvb2tlZCB0aGF0Cj4gPiBjb25maWd1cmF0aW9u Lgo+ID4gCj4gPiA+ID4gK8KgwqDCoCB9Cj4gPiA+ID4gKwo+ID4gPiA+ICvCoMKgwqAgLyoKPiA+ ID4gPiArwqDCoMKgwqAgKiBDUFUgZnJlcXVlbmN5ID0gcmVmZXJlbmNlIHBlcmYgKGluIEh6KSAq ICgvXCBkZWxpdmVyZWQpCj4gPiA+ID4gLyAoL1wgcmVmZXJlbmNlKQo+ID4gPiA+ICvCoMKgwqDC oCAqIEFNVSByZWZlcmVuY2UgcGVyZm9ybWFuY2UgY291bnRlciBpbmNyZW1lbnQgcmF0ZSBpcwo+ ID4gPiA+IGVxdWFsIHRvIHRoZSByYXRlCj4gPiA+ID4gK8KgwqDCoMKgICogb2YgaW5jcmVtZW50 IG9mIHRoZSBTeXN0ZW0gY291bnRlciwgQ05UUENUX0VMMCBhbmQgY2FuCj4gPiA+ID4gYmUgdXNl ZCB0bwo+ID4gPiA+ICvCoMKgwqDCoCAqIGNvbXB1dGUgdGhlIENQVSBmcmVxdWVuY3kuCj4gPiA+ ID4gK8KgwqDCoMKgICovCj4gPiA+ID4gK8KgwqDCoCByZXR1cm4gZGl2NjRfdTY0KChkZWx0YV9j b3JlX2NudCAqIChhcmNoX3RpbWVyX2dldF9yYXRlKCkgLyBIWikpLAo+ID4gPiAvSFovSFpfUEVS X0tIWiA/Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBkZWx0YV9jb25zdF9jbnQp Owo+ID4gPiA+ICsKPiA+ID4gPiArZmFsbGJhY2s6Cj4gPiA+ID4gK8KgwqDCoCBmcmVxID0gY3B1 ZnJlcV9xdWlja19nZXQoY3B1KTsKPiA+ID4gPiArwqDCoMKgIHJldHVybiBmcmVxID8gZnJlcSA6 IGNwdWZyZXFfZ2V0X2h3X21heF9mcmVxKGNwdSk7Cj4gPiA+IElmIHRoZSBhcmNoIHNwZWNpZmlj IGNvZGUgY2Fubm90IGRldGVybWluZSB0aGUgZnJlcXVlbmN5IGl0IHNob3VsZAo+ID4gPiBhY3R1 YWxseSBtYWtlCj4gPiA+IGl0IGNsZWFyIGJ5IHJldHVybmluZyAnMCcgaW5zdGVhZCBvZiB0cnlp bmcgdG8gcGF0Y2ggdGhpbmdzIHVwIGJ5Cj4gPiA+IGl0c2VsZiAoPykKPiA+ID4gCj4gPiAKPiA+ IFRoaXMgd2FzIGZvbGxvd2luZyB0aGUgc2FtZSBsb2dpYyBhcyBBUEVSRi9NUEVSRiBsb2dpYy4g UmV0dXJuaW5nIDAgZnJvbQo+ID4gaGVyZSB3b3VsZCByZXN1bHQgaW4gYSBjYWxsIHRvIGNwdWZy ZXFfZHJpdmVyLT5nZXQoKSB2cyBhIGNhbGwgdG8KPiA+IGNwdWZyZXFfcXVpY2tfZ2V0KCkuIFRo ZSBvbmx5IGRpZmZlcmVuY2UgSSBjYW4gdGVsbCBpcyB0aGF0Cj4gPiBjcHVmcmVxX3F1aWNrX2dl dCgpIHdpbGwgY2FsbCByZWFkX2xvY2tfaXJxc2F2ZSgpIGJlZm9yZSBjYWxsaW5nCj4gPiBjcHVm cmVxX2RyaXZlci0+Z2V0KCkuIEkgZG9uJ3QgaGF2ZSBlbm91Z2gga25vd2xlZGdlIHRvIHBvaW50 IG91dAo+ID4gd2hpY2ggb25lIGlzIG1vcmUgYXBwcm9wcmlhdGUuIEZvbGxvd2luZyB0aGUgc2Ft ZSBsb2dpYyBhcyB0aGUgeDg2Cj4gPiBpbXBsZW1lbnRhdGlvbiBzZWVtZWQgbW9yZSBwcnVkZW50 Lgo+ID4gCj4gPiA+IE92ZXJhbGwgSSdkIHByZWZlciB0byByZXZpdmUgWzFdIGFuZCBhbWVuZWQg aXQgYWNjb3JkaW5nbHkgaW5zdGVhZC4KPiA+ID4gCj4gPiAKPiA+IEFzIG1lbnRpb25lZCBlYXJs aWVyLCBJJ20gb2sgd2l0aCB3aGF0IGxlYWRzIHRvIGEgY29oZXJlbnQgc29sdXRpb24gZm9yCj4g PiBhbGwgdGhlIGNvbmZpZ3VyYXRpb25zIHdlIGhhdmUgLSBpc29sY3B1cywgaWRsZSBhbmQgYWN0 aXZlIGluCj4gPiBob3VzZWtlZXBpbmdfY3B1cy4KPiA+IAo+ID4gVGhpcyBpc3N1ZSBpbXBhY3Rz IGV4aXN0aW5nIEFtcGVyZSBwcm9kdWN0cy4gSXQgd291bGQgYmUgZ3JlYXQgaWYgd2UKPiA+IGNv dWxkIGFycml2ZSBhdCBhIHNvbHV0aW9uIHNvb24uCj4gKzEgdG8gaGF2ZSBhIHNvbHV0aW9uIHNv b24sIHZlcnkgZXhwZWN0aW5nLiBAVmFuc2hpIGFuZCBAQmVhdGEuCgpVbmRlcnN0b29kLgpXaWxs IHByZXBhcmUgbmV3IHZlcnNpb24gLSBzaG91bGQgYmUgb3V0IGJ5IE1vbmRheS4KQXBvbG9naWVz IGZvciBkZWxheXMgb24gbXkgc2lkZS4KCi0tLQpCUgpCZWF0YQo+ID4gCj4gPiA+IC0tLQo+ID4g PiBbMV0gaHR0cHM6Ly9sb3JlLmtlcm5lbC5vcmcvYWxsLzIwMjMxMTI3MTYwODM4LjE0MDM0MDQt MS1iZWF0YS5taWNoYWxza2FAYXJtLmNvbS8KPiA+IFsyXSAtIGh0dHBzOi8vbG9yZS5rZXJuZWwu b3JnL2FsbC83ZW96aW0yeG5lcGFjbm5renhsYngzNGhpYjRvdHljbmJuNGRxeW1memlxb3U1bHc1 dUA1eHpwdjN0N3N4bzMvCj4gPiAKPiA+IFRoYW5rcyBmb3IgdGhlIGRpc2N1c3Npb24uCj4gPiAK PiA+IFZhbnNoaQo+ID4gCj4gPiA+IC0tLQo+ID4gPiBCZXN0IFJlZ2FyZHMKPiA+ID4gQmVhdGEK PiA+ID4gPiArfQo+ID4gPiA+ICsKPiA+ID4gPiDCoHN0YXRpYyBzdHJ1Y3Qgc2NhbGVfZnJlcV9k YXRhIGFtdV9zZmQgPSB7Cj4gPiA+ID4gwqDCoMKgwqAgLnNvdXJjZSA9IFNDQUxFX0ZSRVFfU09V UkNFX0FSQ0gsCj4gPiA+ID4gwqDCoMKgwqAgLnNldF9mcmVxX3NjYWxlID0gYW11X3NjYWxlX2Zy ZXFfdGljaywKPiA+ID4gPiAtLSAKPiA+ID4gPiAyLjQzLjEKPiA+ID4gPiAKPiA+IC4KCl9fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJu ZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRw Oi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK