From: Dmitry Osipenko <digetx@gmail.com>
To: Peter Crosthwaite <crosthwaitepeter@gmail.com>
Cc: Peter Maydell <peter.maydell@linaro.org>,
qemu-arm@nongnu.org, QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [Qemu-arm] [PATCH v8 1/4] hw/ptimer: Fix issues caused by the adjusted timer limit value
Date: Wed, 6 Jan 2016 16:25:48 +0300 [thread overview]
Message-ID: <568D15DC.2020003@gmail.com> (raw)
In-Reply-To: <20160106121535.GB4227@pcrost-box>
06.01.2016 15:15, Peter Crosthwaite пишет:
>> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
>> index edf077c..035af97 100644
>> --- a/hw/core/ptimer.c
>> +++ b/hw/core/ptimer.c
>> @@ -34,20 +34,39 @@ static void ptimer_trigger(ptimer_state *s)
>>
>> static void ptimer_reload(ptimer_state *s)
>> {
>> - if (s->delta == 0) {
>> + uint32_t period_frac = s->period_frac;
>> + uint64_t period = s->period;
>> + uint64_t delta = s->delta;
>> + uint64_t limit = s->limit;
>> +
>
> Localising these variables is out of scope of the change. I think you can
> just use s->foo and if you want to cleanup, it should be a separate
> patch.
>
Okay
>> + if (delta == 0) {
>> ptimer_trigger(s);
>> - s->delta = s->limit;
>> + delta = limit;
>> }
>> - if (s->delta == 0 || s->period == 0) {
>> + if (delta == 0 || period == 0) {
>> fprintf(stderr, "Timer with period zero, disabling\n");
>> s->enabled = 0;
>> return;
>> }
>>
>> + /*
>> + * Artificially limit timeout rate to something
>> + * achievable under QEMU. Otherwise, QEMU spends all
>> + * its time generating timer interrupts, and there
>> + * is no forward progress.
>> + * About ten microseconds is the fastest that really works
>> + * on the current generation of host machines.
>> + */
>> +
>> + if ((s->enabled == 1) && (limit * period < 10000)) {
>> + period = 10000 / limit;
>> + period_frac = 0;
>> + }
>> +
>
> I think it should be ok to just update s->period and s->period_frac ...
>
No, then it would be irreversibly lost. What if'd decide to change the limit to
some large value?
>> s->last_event = s->next_event;
>> - s->next_event = s->last_event + s->delta * s->period;
>> - if (s->period_frac) {
>> - s->next_event += ((int64_t)s->period_frac * s->delta) >> 32;
>> + s->next_event = s->last_event + delta * period;
>> + if (period_frac) {
>> + s->next_event += ((int64_t)period_frac * delta) >> 32;
>> }
>> timer_mod(s->timer, s->next_event);
>> }
>> @@ -82,6 +101,8 @@ uint64_t ptimer_get_count(ptimer_state *s)
>> uint64_t div;
>> int clz1, clz2;
>> int shift;
>> + uint32_t period_frac = s->period_frac;
>> + uint64_t period = s->period;
>>
>> /* We need to divide time by period, where time is stored in
>> rem (64-bit integer) and period is stored in period/period_frac
>> @@ -93,8 +114,13 @@ uint64_t ptimer_get_count(ptimer_state *s)
>> backwards.
>> */
>>
>> + if ((s->enabled == 1) && (s->limit * period < 10000)) {
>> + period = 10000 / s->limit;
>> + period_frac = 0;
>> + }
>> +
>
> ... and then this (and the local variables) become obsolete. Can get_count()
> blindly use the period and period_frac as used by ptimer_reload?
>
>> rem = s->next_event - now;
>> - div = s->period;
>> + div = period;
>>
>> clz1 = clz64(rem);
>> clz2 = clz64(div);
>> @@ -103,13 +129,13 @@ uint64_t ptimer_get_count(ptimer_state *s)
>> rem <<= shift;
>> div <<= shift;
>> if (shift >= 32) {
>> - div |= ((uint64_t)s->period_frac << (shift - 32));
>> + div |= ((uint64_t)period_frac << (shift - 32));
>> } else {
>> if (shift != 0)
>> - div |= (s->period_frac >> (32 - shift));
>> + div |= (period_frac >> (32 - shift));
>> /* Look at remaining bits of period_frac and round div up if
>> necessary. */
>> - if ((uint32_t)(s->period_frac << shift))
>> + if ((uint32_t)(period_frac << shift))
>> div += 1;
>> }
>> counter = rem / div;
>> @@ -181,19 +207,6 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
>> count = limit. */
>> void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
>> {
>> - /*
>> - * Artificially limit timeout rate to something
>> - * achievable under QEMU. Otherwise, QEMU spends all
>> - * its time generating timer interrupts, and there
>> - * is no forward progress.
>> - * About ten microseconds is the fastest that really works
>> - * on the current generation of host machines.
>> - */
>> -
>> - if (!use_icount && limit * s->period < 10000 && s->period) {
>
> This original rate limiting code is gated on icount, so I think then
> new way should be the same.
>
Shoot :) That's second time I'm missing it. Good catch!
> Regards,
> Peter
>
>> - limit = 10000 / s->period;
>> - }
>> -
>> s->limit = limit;
>> if (reload)
>> s->delta = limit;
>> --
>> 2.6.4
>>
--
Dmitry
WARNING: multiple messages have this Message-ID (diff)
From: Dmitry Osipenko <digetx@gmail.com>
To: Peter Crosthwaite <crosthwaitepeter@gmail.com>
Cc: Peter Maydell <peter.maydell@linaro.org>,
qemu-arm@nongnu.org, QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH v8 1/4] hw/ptimer: Fix issues caused by the adjusted timer limit value
Date: Wed, 6 Jan 2016 16:25:48 +0300 [thread overview]
Message-ID: <568D15DC.2020003@gmail.com> (raw)
In-Reply-To: <20160106121535.GB4227@pcrost-box>
06.01.2016 15:15, Peter Crosthwaite пишет:
>> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
>> index edf077c..035af97 100644
>> --- a/hw/core/ptimer.c
>> +++ b/hw/core/ptimer.c
>> @@ -34,20 +34,39 @@ static void ptimer_trigger(ptimer_state *s)
>>
>> static void ptimer_reload(ptimer_state *s)
>> {
>> - if (s->delta == 0) {
>> + uint32_t period_frac = s->period_frac;
>> + uint64_t period = s->period;
>> + uint64_t delta = s->delta;
>> + uint64_t limit = s->limit;
>> +
>
> Localising these variables is out of scope of the change. I think you can
> just use s->foo and if you want to cleanup, it should be a separate
> patch.
>
Okay
>> + if (delta == 0) {
>> ptimer_trigger(s);
>> - s->delta = s->limit;
>> + delta = limit;
>> }
>> - if (s->delta == 0 || s->period == 0) {
>> + if (delta == 0 || period == 0) {
>> fprintf(stderr, "Timer with period zero, disabling\n");
>> s->enabled = 0;
>> return;
>> }
>>
>> + /*
>> + * Artificially limit timeout rate to something
>> + * achievable under QEMU. Otherwise, QEMU spends all
>> + * its time generating timer interrupts, and there
>> + * is no forward progress.
>> + * About ten microseconds is the fastest that really works
>> + * on the current generation of host machines.
>> + */
>> +
>> + if ((s->enabled == 1) && (limit * period < 10000)) {
>> + period = 10000 / limit;
>> + period_frac = 0;
>> + }
>> +
>
> I think it should be ok to just update s->period and s->period_frac ...
>
No, then it would be irreversibly lost. What if'd decide to change the limit to
some large value?
>> s->last_event = s->next_event;
>> - s->next_event = s->last_event + s->delta * s->period;
>> - if (s->period_frac) {
>> - s->next_event += ((int64_t)s->period_frac * s->delta) >> 32;
>> + s->next_event = s->last_event + delta * period;
>> + if (period_frac) {
>> + s->next_event += ((int64_t)period_frac * delta) >> 32;
>> }
>> timer_mod(s->timer, s->next_event);
>> }
>> @@ -82,6 +101,8 @@ uint64_t ptimer_get_count(ptimer_state *s)
>> uint64_t div;
>> int clz1, clz2;
>> int shift;
>> + uint32_t period_frac = s->period_frac;
>> + uint64_t period = s->period;
>>
>> /* We need to divide time by period, where time is stored in
>> rem (64-bit integer) and period is stored in period/period_frac
>> @@ -93,8 +114,13 @@ uint64_t ptimer_get_count(ptimer_state *s)
>> backwards.
>> */
>>
>> + if ((s->enabled == 1) && (s->limit * period < 10000)) {
>> + period = 10000 / s->limit;
>> + period_frac = 0;
>> + }
>> +
>
> ... and then this (and the local variables) become obsolete. Can get_count()
> blindly use the period and period_frac as used by ptimer_reload?
>
>> rem = s->next_event - now;
>> - div = s->period;
>> + div = period;
>>
>> clz1 = clz64(rem);
>> clz2 = clz64(div);
>> @@ -103,13 +129,13 @@ uint64_t ptimer_get_count(ptimer_state *s)
>> rem <<= shift;
>> div <<= shift;
>> if (shift >= 32) {
>> - div |= ((uint64_t)s->period_frac << (shift - 32));
>> + div |= ((uint64_t)period_frac << (shift - 32));
>> } else {
>> if (shift != 0)
>> - div |= (s->period_frac >> (32 - shift));
>> + div |= (period_frac >> (32 - shift));
>> /* Look at remaining bits of period_frac and round div up if
>> necessary. */
>> - if ((uint32_t)(s->period_frac << shift))
>> + if ((uint32_t)(period_frac << shift))
>> div += 1;
>> }
>> counter = rem / div;
>> @@ -181,19 +207,6 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
>> count = limit. */
>> void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
>> {
>> - /*
>> - * Artificially limit timeout rate to something
>> - * achievable under QEMU. Otherwise, QEMU spends all
>> - * its time generating timer interrupts, and there
>> - * is no forward progress.
>> - * About ten microseconds is the fastest that really works
>> - * on the current generation of host machines.
>> - */
>> -
>> - if (!use_icount && limit * s->period < 10000 && s->period) {
>
> This original rate limiting code is gated on icount, so I think then
> new way should be the same.
>
Shoot :) That's second time I'm missing it. Good catch!
> Regards,
> Peter
>
>> - limit = 10000 / s->period;
>> - }
>> -
>> s->limit = limit;
>> if (reload)
>> s->delta = limit;
>> --
>> 2.6.4
>>
--
Dmitry
next prev parent reply other threads:[~2016-01-06 13:26 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-05 2:33 [Qemu-devel] [PATCH v8 0/4] PTimer fixes and ARM MPTimer conversion Dmitry Osipenko
2016-01-05 2:33 ` [Qemu-devel] [PATCH v8 1/4] hw/ptimer: Fix issues caused by the adjusted timer limit value Dmitry Osipenko
2016-01-06 12:15 ` [Qemu-arm] " Peter Crosthwaite
2016-01-06 12:15 ` [Qemu-devel] " Peter Crosthwaite
2016-01-06 13:25 ` Dmitry Osipenko [this message]
2016-01-06 13:25 ` Dmitry Osipenko
2016-01-06 13:38 ` Peter Crosthwaite
2016-01-05 2:33 ` [Qemu-devel] [PATCH v8 2/4] hw/ptimer: Perform tick and counter wrap around if timer already expired Dmitry Osipenko
2016-01-06 12:17 ` [Qemu-arm] " Peter Crosthwaite
2016-01-06 12:17 ` [Qemu-devel] " Peter Crosthwaite
2016-01-06 13:12 ` [Qemu-arm] " Dmitry Osipenko
2016-01-06 13:12 ` [Qemu-devel] " Dmitry Osipenko
2016-01-06 13:59 ` Peter Crosthwaite
2016-01-06 20:52 ` [Qemu-arm] " Dmitry Osipenko
2016-01-06 20:52 ` [Qemu-devel] " Dmitry Osipenko
2016-01-05 2:33 ` [Qemu-devel] [PATCH v8 3/4] hw/ptimer: Update .delta on period/freq change Dmitry Osipenko
2016-01-06 12:17 ` Peter Crosthwaite
2016-01-05 2:33 ` [Qemu-devel] [PATCH v8 4/4] arm_mptimer: Convert to use ptimer Dmitry Osipenko
2016-01-06 13:17 ` Peter Crosthwaite
2016-01-07 14:40 ` [Qemu-arm] " Dmitry Osipenko
2016-01-07 14:40 ` [Qemu-devel] " Dmitry Osipenko
2016-01-07 17:34 ` [Qemu-arm] " Dmitry Osipenko
2016-01-07 17:34 ` [Qemu-devel] " Dmitry Osipenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=568D15DC.2020003@gmail.com \
--to=digetx@gmail.com \
--cc=crosthwaitepeter@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.