Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Jul 2012 15:28:27 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        David Chisnall <theraven@freebsd.org>
Cc:        Dimitry Andric <dim@freebsd.org>, freebsd-current@freebsd.org, Kim Culhan <w8hdkim@gmail.com>
Subject:   Re: -current build failure
Message-ID:  <20120721122827.GA2676@deviant.kiev.zoral.com.ua>
In-Reply-To: <8A03FF40-9A33-402F-AA01-E7C25EFF7430@freebsd.org>
References:  <CAKZxVQV5xhFDN_WbTk-EMoQ18N8u1f4YhqKSJQFUzbX4NZxhUA@mail.gmail.com> <50097BF0.9010103@FreeBSD.org> <20120720163352.GS2676@deviant.kiev.zoral.com.ua> <9EBB4101-3117-4FE0-AD08-1053423BECD6@FreeBSD.org> <20120720231604.GT2676@deviant.kiev.zoral.com.ua> <8A03FF40-9A33-402F-AA01-E7C25EFF7430@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--0hyMCxJS7FIePeVX
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Sat, Jul 21, 2012 at 12:59:07PM +0100, David Chisnall wrote:
> On 21 Jul 2012, at 00:16, Konstantin Belousov wrote:
>=20
> > 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).
>=20
> See 6.5.3.2, paragraph 4.  In particular:
>=20
> > If an invalid value has been assigned to the pointer, the behavior of t=
he unary * operator is undefined.
>=20
> and then (footnote 87 from the same page):
>=20
> > Among the invalid values for dereferencing a pointer by the unary * ope=
rator are a null pointer
>=20
>=20
> This clearly states that any dereference of the null pointer is explicitl=
y invalid.  You can look up the correct paragraph for the other reason your=
self (that any valid pointer must be the result of pointer arithmetic on a =
valid pointer).
>=20
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.
>=20
> 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.  Compi=
ling for a freestanding target does not let you opt out of the C memory mod=
el.
>=20
> > 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.
>=20
> 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.

>=20
> >  (*(char *)OFFSETOF_CURTHREAD)
>=20
> This is dereferencing the NULL pointer if OFFSETOF_CURTHREAD is 0.  If yo=
u want to pass the 0 into the assembly then passing it as something other t=
han a memory operand would make sense.  Or, as the warning suggests, add a =
volatile qualification to indicate that the asm is not actually dereferenci=
ng 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.

>=20
> However...
>=20
> > 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.
>=20
> Clang designates address space 256 for GS-relative addressing (and 257 fo=
r FS-relative addressing), so you don't need to use any assembly if all tha=
t you want to do is load something relative to one of these segments.  From=
 the clang manual:
>=20
> > Annotating a pointer with address space #256 causes it to be code gener=
ated 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).
> >=20
> > Here is an example:
> >=20
>=20
> > #define GS_RELATIVE __attribute__((address_space(256)))
> > int foo(int GS_RELATIVE *P) {
> >   return *P;
> > }
> >=20
> > Which compiles to (on X86-32):
> >=20
> > _foo:
> > 	movl	4(%esp), %eax
> > 	movl	%gs:(%eax), %eax
> > 	ret
>=20
> 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 ?

--0hyMCxJS7FIePeVX
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (FreeBSD)

iEYEARECAAYFAlAKoGsACgkQC3+MBN1Mb4i2PgCdE3braxORLPvB3UeoA3WnRCbO
B4AAn1QMVuT4ZaKvrq/xbhLlU4fvhbZU
=yE/T
-----END PGP SIGNATURE-----

--0hyMCxJS7FIePeVX--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120721122827.GA2676>