On Sat, Jul 21, 2012 at 12:59:07PM +0100, David Chisnall wrote:
> On 21 Jul 2012, at 00:16, Konstantin Belousov wrote:
> 
> > Ok, I stand corrected. But the standard does not say what you claim
> > either. It only specifies that NULL pointer is unequal to any pointer
> > to object or function (implicitely saying that you can create a C object
> > or function pointer to which is equal to NULL).
> 
> See 6.5.3.2, paragraph 4.  In particular:
> 
> > If an invalid value has been assigned to the pointer, the behavior of the 
> > unary * operator is undefined.
> 
> and then (footnote 87 from the same page):
> 
> > Among the invalid values for dereferencing a pointer by the unary * 
> > operator are a null pointer
> 
> 
> This clearly states that any dereference of the null pointer is explicitly 
> invalid.  You can look up the correct paragraph for the other reason yourself 
> (that any valid pointer must be the result of pointer arithmetic on a valid 
> pointer).
> 
As I said in the followup, the C part of the code does not dereferences
NULL at all.

> > So, lets reformulate it other way: freestanding implementation in clang
> > has no use, at least for general purpose kernel.
> 
> The term 'freestanding' has a well-defined meaning in the C specification.  
> It does not mean 'the C memory model doesn't apply', it means that there is 
> no underlying operating system providing facilities such as I/O.  Compiling 
> for a freestanding target does not let you opt out of the C memory model.
> 
> > Especially ridiculous
> > is the fact that clang throws it hands for asm inline wanting to get
> > null address, on the machine with linearly addressable memory.
> 
> C is not a macro assembler, it is a well-defined (mostly) language with a 
> complex memory model.  The relevant bit of code is:

Yes, implementation that interprets the freestanding this way is not
useful as a tool for implementing kernel.

> 
> >  (*(char *)OFFSETOF_CURTHREAD)
> 
> This is dereferencing the NULL pointer if OFFSETOF_CURTHREAD is 0.  If you 
> want to pass the 0 into the assembly then passing it as something other than 
> a memory operand would make sense.  Or, as the warning suggests, add a 
> volatile qualification to indicate that the asm is not actually dereferencing 
> this pointer.

I want the code to generate exact "movq %gs:0,%<any reg>" instruction,
without using volatile, and using C-level constant with the value of
offsetof(struct pcpu, pc_curthread), to be able to assert that
assumptions of the assembler fragment did not changed.

Your words about specifying immediate operand instead of memory reference
almost inevitably results in asm-level expression like $0, not 0. At least
I cannot write such asm constraint. You are welcome to provide the snippet.

> 
> However...
> 
> > The point of existence of the inline __pure2 __curthread() is to allow
> > a compiler to cache the result of the call. Basically, the curthread
> > dereference uses %gs basing, which typically adds a measurable penalty
> > on the frontend and sometimes on the execution as well.
> 
> Clang designates address space 256 for GS-relative addressing (and 257 for 
> FS-relative addressing), so you don't need to use any assembly if all that 
> you want to do is load something relative to one of these segments.  From the 
> clang manual:
> 
> > Annotating a pointer with address space #256 causes it to be code generated 
> > relative to the X86 GS segment register, and address space #257 causes it 
> > to be relative to the X86 FS segment. Note that this is a very very 
> > low-level feature that should only be used if you know what you're doing 
> > (for example in an OS kernel).
> > 
> > Here is an example:
> > 
> 
> > #define GS_RELATIVE __attribute__((address_space(256)))
> > int foo(int GS_RELATIVE *P) {
> >   return *P;
> > }
> > 
> > Which compiles to (on X86-32):
> > 
> > _foo:
> >     movl    4(%esp), %eax
> >     movl    %gs:(%eax), %eax
> >     ret
> 
> Using this instead of the inline asm allows the front end to perform
> numerous optimisations because it no longer has a bit of magic embedded
> in the middle of the code that the optimisers don't understand.

Great, how to express a fetch of the struct thread * from gs-based offset
0 using this machinery and both avoiding NULL pointer dereference warning
and avoiding an addition of volatile ?

Attachment: pgpZKizwSJxkT.pgp
Description: PGP signature

Reply via email to