Re: -current build failure

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Sat, 21 Jul 2012 15:28:27 +0300
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 ?

Received on Sat Jul 21 2012 - 10:28:31 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:29 UTC