Commit 619c1baa authored by Daniel Lezcano's avatar Daniel Lezcano Committed by Thomas Gleixner

genirq/timings: Fix next event index function

The current code is luckily working with most of the interval samples
testing but actually it fails to correctly detect pattern repetition
breaking at the end of the buffer.

Narrowing down the bug has been a real pain because of the pointers,
so the routine is rewrittne by using indexes instead.

Fixes: bbba0e7c "genirq/timings: Add array suffix computation code"
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: andriy.shevchenko@linux.intel.com
Link: https://lkml.kernel.org/r/20190527205521.12091-2-daniel.lezcano@linaro.org
parent 43b98d87
...@@ -297,7 +297,16 @@ static u64 irq_timings_ema_new(u64 value, u64 ema_old) ...@@ -297,7 +297,16 @@ static u64 irq_timings_ema_new(u64 value, u64 ema_old)
static int irq_timings_next_event_index(int *buffer, size_t len, int period_max) static int irq_timings_next_event_index(int *buffer, size_t len, int period_max)
{ {
int i; int period;
/*
* Move the beginning pointer to the end minus the max period x 3.
* We are at the point we can begin searching the pattern
*/
buffer = &buffer[len - (period_max * 3)];
/* Adjust the length to the maximum allowed period x 3 */
len = period_max * 3;
/* /*
* The buffer contains the suite of intervals, in a ilog2 * The buffer contains the suite of intervals, in a ilog2
...@@ -306,21 +315,45 @@ static int irq_timings_next_event_index(int *buffer, size_t len, int period_max) ...@@ -306,21 +315,45 @@ static int irq_timings_next_event_index(int *buffer, size_t len, int period_max)
* period beginning at the end of the buffer. We do that for * period beginning at the end of the buffer. We do that for
* each suffix. * each suffix.
*/ */
for (i = period_max; i >= PREDICTION_PERIOD_MIN ; i--) { for (period = period_max; period >= PREDICTION_PERIOD_MIN; period--) {
int *begin = &buffer[len - (i * 3)]; /*
int *ptr = begin; * The first comparison always succeed because the
* suffix is deduced from the first n-period bytes of
* the buffer and we compare the initial suffix with
* itself, so we can skip the first iteration.
*/
int idx = period;
size_t size = period;
/* /*
* We look if the suite with period 'i' repeat * We look if the suite with period 'i' repeat
* itself. If it is truncated at the end, as it * itself. If it is truncated at the end, as it
* repeats we can use the period to find out the next * repeats we can use the period to find out the next
* element. * element with the modulo.
*/ */
while (!memcmp(ptr, begin, i * sizeof(*ptr))) { while (!memcmp(buffer, &buffer[idx], size * sizeof(int))) {
ptr += i;
if (ptr >= &buffer[len]) /*
return begin[((i * 3) % i)]; * Move the index in a period basis
*/
idx += size;
/*
* If this condition is reached, all previous
* memcmp were successful, so the period is
* found.
*/
if (idx == len)
return buffer[len % period];
/*
* If the remaining elements to compare are
* smaller than the period, readjust the size
* of the comparison for the last iteration.
*/
if (len - idx < period)
size = len - idx;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment