From: Linus Torvalds <torvalds@linux-foundation.org> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten Date: Wed, 02 Dec 2009 15:27:45 UTC Message-ID: <fa.iJ9gA2VhV/B/eOtyNrnuFJzMRNA@ifi.uio.no> On Wed, 2 Dec 2009, tip-bot for Jan Beulich wrote: > > locking, x86: Slightly shorten __ticket_spin_trylock() NAK. This is horrible crap. Don't ever send me this kind of broken patch again. > - int new; > + union { int i; bool b; } new; No thank you. This is total bogosity. You have zero idea what type "bool" is, do you? It can well be "int", it can be "char", it can be some compiler-internal type ("_Bool"). You have no idea what size it is. And maybe it _is_ just a byte. But even if it is, using 'bool' here is wrong. The fact is, bool has magic semantic properties outside of sizing. You can't mix it with inline asm, because you simply don't know what the compiler rules for 'bool' are. For example, maybe the rules are that it's always passed as an integer, and is always guaranteed to have the values 0/1. So even if 'sizeof' returns 1, that doesn't actually mean that you can necessarily pass it around as a char - it only means that it will take one byte in a structure (except that bool arrays might be packed, I think). In other words, the semantics of 'bool' are such that you have no clue what the actual ABI for 'bool' is. You cannot mix this with asm. Secondly, the notion of using a union here is just totally broken. There's no point to it, and it just makes the code look horrible. So if you want to do this, then just keep 'new' as an int, and make sure that the function returns a 'char'. No games with 'bool' which is badly defined, no games with unions. And please do make sure that it actually doesn't deprove code at the callers too. Linus

From: Linus Torvalds <torvalds@linux-foundation.org> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten Date: Wed, 02 Dec 2009 15:34:52 UTC Message-ID: <fa.OurMjvE+FjOoLtZzIx5xDB4VUGo@ifi.uio.no> On Wed, 2 Dec 2009, Jan Beulich wrote: > >>> Ingo Molnar <mingo@elte.hu> 02.12.09 15:21 >>> > 792a99a9 <_raw_spin_lock>: > ... > >792a99f3: 89 d8 mov %ebx,%eax > >792a99f5: ff 15 d0 6c f2 79 call *0x79f26cd0 > >792a99fb: 85 c0 test %eax,%eax > ... > >792a9a2e: 89 f8 mov %edi,%eax > >792a9a30: ff 15 d0 6c f2 79 call *0x79f26cd0 > >792a9a36: 85 c0 test %eax,%eax > > Assuming that these are the calls to __raw_spin_trylock, it is clear that > the generated code isn't what we want: It should be test %al, %al in > both cases. See my previous email. Using 'bool' was a mistake. It's _always_ a mistake. 'bool' basically says that the compiler can assume magic things, and compile the thing to be anything it wants that is convenient for it. Put another way, 'bool' has a magic API. For all you know, the rule might even be that a 'bool' return value is always returned in a flag register (ok, on x86 that would be _very_ inconvenient, but it's _possible_). So the calling convention could have been call <bool-returning-function> jne .. // jump if it returned non-zero because the rule about bool is that it is just one bit of information, but exactly _how_ that bit is done is totally up to the compiler ABI. In this case, the rule gcc implements on x86 is probably just "we pass it around as an 'int' that contains 0 or 1". So the code would work if you had left in the 'movzbl'. End result: don't use bool. Linus

From: Linus Torvalds <torvalds@linux-foundation.org> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten Date: Wed, 02 Dec 2009 16:57:57 UTC Message-ID: <fa.HJm8Upo//wQAP4xhp2Ir7SZ9PMw@ifi.uio.no> On Wed, 2 Dec 2009, Jan Beulich wrote: > > This just can't be the case: In order for two compilers to be > interoperable, the processor specific ABI has to define the handling of > bool, just like it has to for any other data type. You are full of crap. The fact is, compilers are _not_ interoperable in general, and ABI's are often compiler-specific. Look at MSVC vs gcc on x86 for just a really obvious and trivial example. The fact is, on x86-unix we simply don't have any real ABI at all, and gcc picks whatever randon choices it has. So stop making excuses. Just admit that 'bool' was wrong, and you made a fundamental mistake in choosing it. The fact is, the compiler can do whatever the hell it does, which is not necessarily sensible with any other type. 'bool' really is special. Linus

From: Linus Torvalds <torvalds@linux-foundation.org> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten Date: Wed, 02 Dec 2009 17:06:26 UTC Message-ID: <fa.mbg1TrWLDfeEU2f/NflkeQKuRG0@ifi.uio.no> On Wed, 2 Dec 2009, Linus Torvalds wrote: > > So stop making excuses. Just admit that 'bool' was wrong, and you made a > fundamental mistake in choosing it. The fact is, the compiler can do > whatever the hell it does, which is not necessarily sensible with any > other type. 'bool' really is special. Btw, even if gcc just treats 'bool' as 'char' (which is the sane thing to do on x86 anyway - I don't see why it should ever do anything else), we actually mess up in the kernel and make that type confusion even worse. Do this: git grep typedef.*bool and then do this: git grep 'define bool' and then sit down and cry silently. Linus

From: "H. Peter Anvin" <hpa@zytor.com> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten __ticket_spin_trylock() Date: Wed, 02 Dec 2009 17:25:11 UTC Message-ID: <fa.xns+H7mtEW2oXE5zlnxF+ospK5g@ifi.uio.no> On 12/02/2009 09:05 AM, Linus Torvalds wrote: > > Btw, even if gcc just treats 'bool' as 'char' (which is the sane thing to > do on x86 anyway - I don't see why it should ever do anything else), we > actually mess up in the kernel and make that type confusion even worse. > For what it's worth, the gcc ABI for i386-Linux treats _Bool (bool) as follows: When in memory, except stack slots: sizeof(_Bool) = 1 0 is false, 1 is true, any other value is *undefined behavior*. When in registers, or in a stack slot: Registers, and stack slots, are always 4 bytes 0 is false, 1 is true, any other value is *undefined behavior*. All of which is well-defined. However, it also only applies to values in memory, or values passed across function boundaries in registers[1] -- anything else is *by definition outside the scope of the ABI* and therefore the compiler can legitimately do whatever is appropriate at any point in time. As such, I would agree with Linus in that using an u8 is the right thing to be handed through the inline asm boundary -- if the compiler needs to extend it, it will, and if it doesn't, there is no penalty. Similarly, a bool can be cast to u8 without penalty. -hpa -- H. Peter Anvin, Intel Open Source Technology Center I work for Intel. I don't speak on their behalf.

From: Linus Torvalds <torvalds@linux-foundation.org> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten Date: Wed, 02 Dec 2009 17:49:14 UTC Message-ID: <fa.7Hx12AjurWuYhXSngaXzPhnbUq0@ifi.uio.no> On Wed, 2 Dec 2009, H. Peter Anvin wrote: > > For what it's worth, the gcc ABI for i386-Linux treats _Bool (bool) as > follows: > > When in memory, except stack slots: > > sizeof(_Bool) = 1 > 0 is false, 1 is true, any other value is *undefined behavior*. > > When in registers, or in a stack slot: > > Registers, and stack slots, are always 4 bytes > 0 is false, 1 is true, any other value is *undefined behavior*. Hmm. Odd. I just checked: _Bool myfunction(char val) { return val; } and compiling it with gcc -O2 -S -m32 -mregparm=3 -fomit-frame-pointer t.c I get myfunction: testb %al, %al setne %al ret which only sets the low 8 bits. So my gcc actually seems to think that _Bool is just 8 bits, at least for return values, and then upper 24 bits are undefined. It also generates 'testb' for a test of a return value. So it so happens that I think Jan's patch would have worked - except for the PV_OPS mess. _Bool does act like a 'char' on x86 at least with gcc. I still think that it's fundamentally wrong to use 'bool' because of how subtly it can act. Linus

From: "H. Peter Anvin" <hpa@zytor.com> Newsgroups: fa.linux.kernel Subject: Re: [tip:core/locking] locking, x86: Slightly shorten __ticket_spin_trylock() Date: Wed, 02 Dec 2009 17:59:35 UTC Message-ID: <fa.yTgTFoNF3kyFp3DopDgMBWp3zK0@ifi.uio.no> On 12/02/2009 09:48 AM, Linus Torvalds wrote: > > Hmm. Odd. I just checked: > > _Bool myfunction(char val) > { > return val; > } > > and compiling it with > > gcc -O2 -S -m32 -mregparm=3 -fomit-frame-pointer t.c > > I get > > myfunction: > testb %al, %al > setne %al > ret > > which only sets the low 8 bits. So my gcc actually seems to think that > _Bool is just 8 bits, at least for return values, and then upper 24 bits > are undefined. It also generates 'testb' for a test of a return value. > Damn. I stand corrected :-/ I just tested it on x86-64, and gcc 4.4.1 actually *violates the documented ABI* for x86-64. > So it so happens that I think Jan's patch would have worked - except for > the PV_OPS mess. _Bool does act like a 'char' on x86 at least with gcc. I > still think that it's fundamentally wrong to use 'bool' because of how > subtly it can act. I personally think using "bool" for C values is a good thing -- people have a very nasty tendency to come up with the clever idea of "oh, there is this flag which is 'int'... well, in this special case let's set it to -1 or 2", and of course there is absolutely no way to know, globally, that this value once in a blue moon gets set to a bizarre value. I have seen this a number of times in the kernel. It doesn't mean one should pass it to assembly code. -hpa -- H. Peter Anvin, Intel Open Source Technology Center I work for Intel. I don't speak on their behalf.