This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: memcmp-sse4.S EqualHappy bug


On Wed, Jun 17, 2015 at 10:19:58PM +0200, OndÅej BÃlka wrote:
> More precisely impossible without very big hammer. My most effective
> solution would be syscall that marks affected pages as read only to
> suspend threads that try to write into them before doing comparison You need
> simultaneous load of both memory areas which hardware doesn't support.
> 
> Without that there would still be race, simplest example would be
> 
> char x[4];
> memcmp(x,x+1,1)
> 
> where another thread just does following:
> *((int *)x) = 1;
> memcmp read x[0] == 1
> *((int *)x) = 256;
> memcmp read x[1] == 1

This actually shows a case where the result is always undefined.

Now suppose the above case but len is 4096 (not 1) and the 4bytes are
followed by 4092 bytes all different and never changing (I write the
program so I can force them never to change). How does memcmp retun 0
in that case?

> memcmp read x[0] == 1

ok

> memcmp read x[1] == 1

ok

4094 bytes are left to compare, do you stop here and return 0 because
first two bytes are equal?

Because current memcmp stops (for other reasons but it stops).

If the first part of memcmp changes randomly returning an undefined
value above or below zero is expected too, -1 or 1 both would be
expected and undefined results, what's feeling weird and unexpected is
only that it returns 0 despite the end is different and never
changing. That's the only issue I'm raising here about memcmp/bcmp.

By physical hardware terms no matter how you change the part of the
memory at the start of memcmp, it is defined it cannot return 0, and
sse4 version does return 0.

I fully understand your arguments about the standard and I expected
this behavior was permitted.

I'm also pointing out we go a bit beyond in what we pretend from C
with the READ_ONCE/WRITE_ONCE/volatile/asm("memory") to provide RCU
(and to implement the spinlock/mutex). I just wanted to express my
views on the practical aspects and how we could enforce that if a part
of memory (a part that is separated by atomic granularity of the arch,
a variable you need to know and isn't 1 byte minimum on alpha for
example) the memcmp is well defined that can't return 0 (i.e. if it
returns 0 it actually read all bytes of "length" parameter and at some
point in time each byte individually was always equal, and the last
part of the page is never changed and never equal).

I'm fine if no change is done, and it'd be great if at least the
manpage of memcmp/bcmp is updated. If it was up to me though I'd
prefer to fix this case so 0 isn't happily returned too soon
unexpectedly, as the unrolled loop fast path won't require change.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]