> -----Original Message-----
> From: Dave Jiang [mailto:dave.ji...@intel.com]
> 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;

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
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to