On Sun, Jul 22, 2012 at 09:01:19PM +0300, Konstantin Belousov wrote:
> [Why don't you bother to configure your mail client properly ?
> Answering to email with 500+ long lines is not trivial]
> 
> On Sun, Jul 22, 2012 at 06:18:12PM +0100, David Chisnall wrote:
> > 
> > On 21 Jul 2012, at 22:16, Konstantin Belousov wrote:
> > 
> > > On Sat, Jul 21, 2012 at 04:00:45PM -0400, Kim Culhan wrote:
> > >> On Fri, Jul 20, 2012 at 11:40 AM, Dimitry Andric <d...@freebsd.org> 
> > >> wrote:
> > >>> On 2012-07-20 16:49, Kim Culhan wrote:
> > >>>> Seeing this for r:238655
> > >>> ...
> > >>>> In file included from 
> > >>>> /usr/src/sys/modules/dtrace/dtrace/../../../sys/pcpu.h:44:
> > >>>> ./machine/pcpu.h:226:13: error: indirection of non-volatile null
> > >>>> pointer will be deleted, not trap
> > >>>>     [-Werror,-Wnull-dereference]
> > >>>>           : "m" (*(char *)OFFSETOF_CURTHREAD));
> > >>>>                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >>>> ./machine/pcpu.h:226:13: note: consider using __builtin_trap() or
> > >>>> qualifying pointer with 'volatile'
> > >>> 
> > >>> That's indeed a valid warning from clang, since OFFSETOF_CURTHREAD is
> > >>> usually zero.  It's probably due to recent work on dtrace.  I'm not in
> > >>> the neighborhood of a FreeBSD box right now to verify, but can you
> > >>> please try to change the cast to "(volatile char *)"?  That should fix
> > >>> the warning.
> > >> 
> > >> Yes it did, I know there are many considerations wrt to this warning.
> > > 
> > > This should be equivalent to what you tried. Can you test build and
> > > boot resulting kernel with this patch ?
> > > 
> > > diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
> > > index 5d1fd4d..7b3c934 100644
> > > --- a/sys/amd64/include/pcpu.h
> > > +++ b/sys/amd64/include/pcpu.h
> > > @@ -217,16 +217,22 @@ extern struct pcpu *pcpup;
> > > #define   PCPU_SET(member, val)   __PCPU_SET(pc_ ## member, val)
> > > 
> > > #define   OFFSETOF_CURTHREAD      0
> > > +#ifdef __clang__
> > > +#define  VOLATILE        volatile
> > > +#else
> > > +#define  VOLATILE
> > > +#endif
> > > static __inline __pure2 struct thread *
> > > __curthread(void)
> > > {
> > >   struct thread *td;
> > > 
> > >   __asm("movq %%gs:%1,%0" : "=r" (td)
> > > -     : "m" (*(char *)OFFSETOF_CURTHREAD));
> > > +     : "m" (*(VOLATILE char *)OFFSETOF_CURTHREAD));
> > >   return (td);
> > > }
> > > #define   curthread               (__curthread())
> > > +#undef VOLATILE
> > > 
> > > #define   OFFSETOF_CURPCB         32
> > > static __inline __pure2 struct pcb *
> > 
> > The following will generate better code, not eliminate future optimisation 
> > opportunities, and work correctly on both 32-bit and 64-bit x86.  
> > 
> > #define GS_RELATIVE __attribute__((address_space(256)))
> > static __inline __pure2 struct thread *
> > __curthread(void)
> > {
> > 
> >     return (*(struct thread *volatile GS_RELATIVE*)OFFSETOF_CURTHREAD);
> > }
Did you ever looked what clang does generate for this function ? I got my
bad mood immediately improved after I saw that:

   0xffffffff804d0883 <+691>:   mov    %gs:0x0,%rax
   0xffffffff804d088c <+700>:   mov    %gs:0x8,%rax

> > 
> > The volatile that clang recommends is very important, because the compiler 
> > (in this version) is not aware of changes to GS and so must assume that it 
> > can change between calls.  In this specific case it is fine, and that's why 
> > it's a warning and not an error.  Both clang and gcc accept the volatile 
> > and both have the same behaviour.  Adding the volatile just for clang will 
> > pessimise the code to silence a warning.  This is not the correct thing to 
> > do.
> 
> I cannot understand what you are trying to say there. I indeed consider
> adding a volatile to shut down a pointless warning a waste. And on the
> other hand clang insist on issuing a warning which breaks the build.
> 
> The function is _guaranteed_ to return the same value any time it is
> called in context of the current thread. In particular, 'gs changing' is
> completely irrelevant. First, segment index loaded into %gs itself does
> not change, even between threads. Second, we guarantee that the basing
> performed over the %gs is constant for current thread. Why should we say
> to clang that %gs base can change there, when it is not, is beyond me.
> 
> Side note, i386 uses %fs and not %gs for pcpu basing.
> > 
> > I have tested this with clang and gcc.  With gcc, a trivial function that 
> > calls __curthread() twice results in two gs-relativel movs either without 
> > __pure2 or with __pure2 and volatile.  With clang, both forms produce a 
> > single one, but the inline asm one is passing inline asm through the LLVM 
> > IR and so will be losing some other optimisation opportunities.  The 
> > presence of __pure2 does make a difference for clang (gcc ignores it), but 
> > removing the volatile has the same effect).  The following version 
> > preserves the exact intention of the function for the entire optimisation 
> > pipeline:
> > 
> > #if __clang__
> > #pragma clang diagnostic push
> > #pragma clang diagnostic ignored "-Wnull-dereference"
> > inline struct thread *
> I wonder if there shall be static keyword as well.
> 
> > __curthread2(void)
> > {
> > 
> >    return (*(struct thread *GS_RELATIVE*)OFFSETOF_CURTHREAD);
> > }
> > #pragma clang diagnostic pop
> > #endif
And there, clang generates
      0xffffffff804d088c <+700>:   mov    %gs:0x8,%rax
This is with the nice patch at the end of this reply. The code causes
panic at the pmap init time.

Longer description is that pc_curthread is offset 0 if %gs-based.
The dereferenced pointer point to the struct thread, which contains
td_proc pointer at offset 8. Instead, clang seems to dereference
td_proc from offset 8 based on %gs, or something similar.

pooma% clang -v
FreeBSD clang version 3.1 (branches/release_31 156863) 20120523
Target: x86_64-unknown-freebsd9.0

I am quite impressed.

> > 
> > The point of warnings is to tell you when you are doing something that is 
> > usually wrong.  The correct response is to disable them when you have 
> > audited the code and determined that this is one of the exceptional cases.
> 
> So it still cannot work without disabling the warning ? Not much
> different from what I noted initially. I am fine with whatever you end
> up under #ifdef clang, please commit a patch.


diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index 5d1fd4d..dc0d828 100644
--- a/sys/amd64/include/pcpu.h
+++ b/sys/amd64/include/pcpu.h
@@ -217,6 +217,34 @@ extern struct pcpu *pcpup;
 #define        PCPU_SET(member, val)   __PCPU_SET(pc_ ## member, val)
 
 #define        OFFSETOF_CURTHREAD      0
+#define        OFFSETOF_CURPCB         32
+
+#ifdef __clang__
+
+#define GS_BASED __attribute__((address_space(256)))
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnull-dereference"
+
+static __inline struct thread *
+__curthread(void)
+{
+
+       return (*(struct thread *volatile GS_BASED *)OFFSETOF_CURTHREAD);
+}
+
+static __inline struct pcb *
+__curpcb(void)
+{
+
+       return (*(struct pcb *GS_BASED *)OFFSETOF_CURPCB);
+}
+
+#pragma clang diagnostic pop
+#undef GS_RELATIVE
+
+#else /* __clang__ */
+
 static __inline __pure2 struct thread *
 __curthread(void)
 {
@@ -226,9 +254,7 @@ __curthread(void)
            : "m" (*(char *)OFFSETOF_CURTHREAD));
        return (td);
 }
-#define        curthread               (__curthread())
 
-#define        OFFSETOF_CURPCB         32
 static __inline __pure2 struct pcb *
 __curpcb(void)
 {
@@ -237,8 +263,11 @@ __curpcb(void)
        __asm("movq %%gs:%1,%0" : "=r" (pcb) : "m" (*(char *)OFFSETOF_CURPCB));
        return (pcb);
 }
-#define        curpcb          (__curpcb())
 
+#endif /* __clang__ */
+
+#define        curthread       (__curthread())
+#define        curpcb          (__curpcb())
 #define        IS_BSP()        (PCPU_GET(cpuid) == 0)
 
 #else /* !lint || defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF) */

Attachment: pgp2PEvYgRQWf.pgp
Description: PGP signature

Reply via email to