Re: Fw: potential /dev/urandom scalability improvement

From: Andrew Morton
Date: Fri Mar 26 2004 - 13:52:07 EST


David Mosberger <davidm@xxxxxxxxxxxxxxxxx> wrote:
>
> >>>>> On Fri, 26 Mar 2004 11:06:19 +0000, Dave Jones <davej@xxxxxxxxxx> said:
>
> Dave> On Thu, Mar 25, 2004 at 06:00:14PM -0800, Andrew Morton wrote:
> >> +static inline void prefetch_range(void *addr, size_t len) +{
> >> +#ifdef ARCH_HAS_PREFETCH + char *cp; + char *end = addr + len; +
> >> + for (cp = addr; cp < end; cp += PREFETCH_STRIDE) +
> >> prefetch(cp); +#endif +} + #endif
>
> Dave> I think this may be dangerous on some CPUs, if may prefetch
> Dave> past the end of the buffer. Ie, if PREFETCH_STRIDE was 32, and
> Dave> len was 65, we'd end up prefetching 65->97. As well as being
> Dave> wasteful to cachelines, this can crash if theres for eg
> Dave> nothing mapped after the next page boundary.
>
> Huh? It only ever prefetches addresses that are _within_ the
> specified buffer. Of course it will prefetch entire cachelines, but I
> hope you're not worried about cachlines crossing page-boundaries! ;-))
>

But the start address which is fed into prefetch_range() may not be
cacheline-aligned. So if appropriately abused, a prefetch_range() could
wander off the end of the user's buffer and into a new page.

I think this gets it right, but I probably screwed something up.

static inline void prefetch_range(void *addr, size_t len)
{
#ifdef ARCH_HAS_PREFETCH
char *cp;
unsigned long end;

end = ((unsigned long)addr + len + PREFETCH_STRIDE - 1);
end &= ~(PREFETCH_STRIDE - 1);

for (cp = addr; cp < (char *)end; cp += PREFETCH_STRIDE)
prefetch(cp);
#endif
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/