On 09/18/2016 09:42 AM, Elliott, Robert (Persistent Memory) wrote: > > >> -----Original Message----- >> From: Dave Jiang [mailto:[email protected]] >> Sent: Friday, September 16, 2016 12:24 PM > ... >> Subject: Re: [PATCH] ndctl: move test/dax-errors buffer to global to >> avoid gcc optimization >> >> On 09/15/2016 06:18 PM, Elliott, Robert (Persistent Memory) wrote: >>> > .... >>>> Some gcc toolchain are optimizing out the memcpy and this causes >>>> dax- errors to not trigger the SIG_BUS when doing memcpy on an >>>> mmap'd buffer. By moving >>>> the buffer to a global variable this bypasses the optimization and >>>> allow the test to work as intended. >>>> > ... >>>> diff --git a/test/dax-errors.c b/test/dax-errors.c >>>> index 11d0031..9ea5c91 100644 >>>> --- a/test/dax-errors.c >>>> +++ b/test/dax-errors.c >>>> @@ -17,6 +17,8 @@ >>>> >>>> static sigjmp_buf sj_env; >>>> static int sig_count; >>>> +/* buf is global in order to avoid gcc memcpy optimization */ >>>> +static void *buf; >>>> >>>> static void sigbus_hdl(int sig, siginfo_t *siginfo, void *ptr) >>>> { >>>> @@ -27,7 +29,7 @@ static void sigbus_hdl(int sig, siginfo_t *siginfo, >>>> void *ptr) >>>> >>>> static int test_dax_read_err(int fd) >>>> { >>>> -void *base, *buf; >>>> +void *base; >>>> int rc = 0; >>>> >>>> if (fd < 0) { >>>> >>> >>> I've run into that kind of problem before, and found that >>> marking *buf as volatile (and leaving it inside the function) >>> tends to be honored better by aggressive optimizing compilers >>> and linkers. >> >> Doesn't appear to work. The compiler discards the volatile. >> >> >> CC dax-errors.o >> dax-errors.c: In function 'test_dax_read_err': >> dax-errors.c:66:9: warning: passing argument 1 of 'memcpy' discards >> 'volatile' qualifier from pointer target type [-Wdiscarded- >> qualifiers] >> memcpy(buf, base, 4096); >> ^~~ >> In file included from dax-errors.c:8:0: >> /usr/include/string.h:42:14: note: expected 'void * restrict' but >> argument is of type 'volatile void *' >> extern void *memcpy (void *__restrict __dest, const void *__restrict >> __src, >> ^~~~~~ >> CCLD dax-errors >> > > For this, put volatile to the right of the *: > void * volatile buf;
It made the compile warning go away, but it did not prevent the memcpy optimization. It still fails unlike when I move the ptr to global. gcc version 6.1.1 20160621 (Red Hat 6.1.1-3) (GCC) gcc -DHAVE_CONFIG_H -I. -I.. -include ../config.h -DSYSCONFDIR=\""/etc"\" -DLIBEXECDIR=\""/usr/libexec"\" -DPREFIX=\""/usr"\" -DNDCTL_MAN_PATH=\""/usr/share/man"\" -I../ndctl/lib -I../ndctl -I../ -I/usr/include/uuid -I/usr/include/json-c -Wall -Wchar-subscripts -Wformat-security -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wshadow -Wsign-compare -Wstrict-prototypes -Wtype-limits -fvisibility=hidden -ffunction-sections -fdata-sections -g -O2 -MT dax-errors.o -MD -MP -MF $depbase.Tpo -c -o dax-errors.o dax-errors.c > > That means buf (the pointer) is volatile, and the compiler is > not allowed to optimize away any accesses inside this function. > When calling another function, it just picks up the value at > that time; that other function doesn't need to continue treating > it as special. > > On a little test program, gcc -O2 preserves the call, and -O3 > optimizes away the call unless it is marked volatile like that. > > In comparison: > volatile void *buf; > means whatever buf points to is volatile, and all functions to > which buf is passed must agree. Accesses to buf itself could > be optimized away, but any dereferences using it that remain > must be freshly made. > > memcpy does not promise to treat its buffers that way, so > triggers compiler warnings or errors if src or dest are pointing > to volatile data. > > In a test program, I made a mycpy() with volatile * buffer > arguments, and gcc -O3 does optimize away the call. > > This combination has both properties: > volatile void * volatile buf; > > > --- > Robert Elliott, HPE Persistent Memory > > _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
