public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] 2.5 fast poll on ppc64
@ 2002-12-26 20:55 Mikael Pettersson
  2002-12-26 21:23 ` Linus Torvalds
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Mikael Pettersson @ 2002-12-26 20:55 UTC (permalink / raw)
  To: manfred; +Cc: anton, linux-kernel, torvalds

On Thu, 26 Dec 2002 14:53:40 +0100, Manfred Spraul wrote:
>Mikael Pettersson wrote:
>
>>Anton Blanchard writes:
>> > I was unable to boot 2.5-BK on ppc64 and narrowed it down to the fast
>> > poll patch.  I found:
>> > 
>> > offsetof(struct poll_list, entries) == 12 but
>> > sizeof(struct poll_list) == 16
...
>>To me (I'm a compiler writer) it looks like your compiler did NOT
>>mess up. Assuming struct pollfd has 32-bit alignment, the compiler
>>is doing the right thing by starting entries[] at offset 12.
>>The 16-byte size for struct poll_list is because the 'next' field
>>has 64-bit alignment, which forces the compiler to pad struct
>>poll_lists's size to a multiple of 8 bytes, i.e. 16 bytes in this
>>case. So the compiler is not broken.
>>  
>>
>I would agree, but there is a special restriction on offsetof() and 
>sizeof() of structures with flexible array members: section 6.7.2.1, 
>clause 16:
>
>First, the size of the structure shall be equal to the offset of the last element of an otherwise identical structure that replaces the flexible array member with an array of unspecified length.
>
>The simplest test case I've found is
>
>struct a1 { int a; char b; short c[];};
>struct a2 { int a; char b; short c[1];};
>
>    sizeof(struct a{1,2}) is 8.
>    offsetof(struct a{1,2}, c) is 6.
>
>--> sizeof(struct a1) != offsetof(struct a2, c)

Oh dear. I checked my C9x draft copy and you seem to be right.
The standard states that sizeof(struct a1) == offsetof(struct a1, c),
but both gcc (2.95.3 and 3.2) and Intel's icc (7.0) get it wrong on x86:
they make sizeof(struct a1) == 8 but offsetof(struct a1, c) == 6.

Technically speaking, the kernel code which uses 'entries[0]' is
non-compliant since the proper syntax is 'entries[]', but the empty
array size syntax isn't implemented in gcc 2.95.3.

>>But the old code which assumed pp+1 == pp->entries is so horribly
>>broken I can't find words for it. s/pp+1/pp->entries/ is the correct fix.

My mistake. The old code is Ok for C99, but broken for ANSI-C.

>I agree. Should we fix the kmalloc allocations, too?
>
>-	pp = kmalloc(sizeof(struct poll_list)+
>+	pp = kmalloc(offsetof(struct poll_list,entries)+
>			sizeof(struct pollfd)*
>			(i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i),
>				GFP_KERNEL);

Yes, this should be changed as you suggest. The old code only
works in C99-compliant implementations, but we now know that both
gcc and icc get this wrong, so it seems prudent to revert to
the classical formulation, using the 'entries[0]' declaration
syntax and offsetof() instead of sizeof().

/Mikael

^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [PATCH] 2.5 fast poll on ppc64
@ 2002-12-26 12:57 Mikael Pettersson
  2002-12-26 13:53 ` Manfred Spraul
  0 siblings, 1 reply; 8+ messages in thread
From: Mikael Pettersson @ 2002-12-26 12:57 UTC (permalink / raw)
  To: anton; +Cc: linux-kernel, manfred, torvalds

Anton Blanchard writes:
 > I was unable to boot 2.5-BK on ppc64 and narrowed it down to the fast
 > poll patch.  I found:
 > 
 > offsetof(struct poll_list, entries) == 12 but
 > sizeof(struct poll_list) == 16
 > 
 > This means pp+1 did not match up with pp->entries. Im not sure what the
 > alignment requirements are for a zero length struct (ie is this a
 > compiler bug) but the following patch fixes the problem and also changes
 > ->len to a long to ensure 8 byte alignment of ->entries on 64bit archs.
 > 
 > Anton
 > 
 > ===== fs/select.c 1.15 vs edited =====
 > --- 1.15/fs/select.c	Sat Dec 21 20:42:41 2002
 > +++ edited/fs/select.c	Thu Dec 26 17:31:16 2002
 > @@ -362,7 +362,7 @@
 >  
 >  struct poll_list {
 >  	struct poll_list *next;
 > -	int len;
 > +	long len;
 >  	struct pollfd entries[0];
 >  };

To me (I'm a compiler writer) it looks like your compiler did NOT
mess up. Assuming struct pollfd has 32-bit alignment, the compiler
is doing the right thing by starting entries[] at offset 12.
The 16-byte size for struct poll_list is because the 'next' field
has 64-bit alignment, which forces the compiler to pad struct
poll_lists's size to a multiple of 8 bytes, i.e. 16 bytes in this
case. So the compiler is not broken.

 >  
 > @@ -471,7 +471,7 @@
 >  			walk->next = pp;
 >  
 >  		walk = pp;
 > -		if (copy_from_user(pp+1, ufds + nfds-i, 
 > +		if (copy_from_user(pp->entries, ufds + nfds-i, 
 >  				sizeof(struct pollfd)*pp->len)) {

But the old code which assumed pp+1 == pp->entries is so horribly
broken I can't find words for it. s/pp+1/pp->entries/ is the correct fix.

/Mikael

^ permalink raw reply	[flat|nested] 8+ messages in thread
* [PATCH] 2.5 fast poll on ppc64
@ 2002-12-26  6:48 Anton Blanchard
  2002-12-26 12:09 ` Manfred Spraul
  0 siblings, 1 reply; 8+ messages in thread
From: Anton Blanchard @ 2002-12-26  6:48 UTC (permalink / raw)
  To: torvalds; +Cc: manfred, linux-kernel


Hi,

I was unable to boot 2.5-BK on ppc64 and narrowed it down to the fast
poll patch.  I found:

offsetof(struct poll_list, entries) == 12 but
sizeof(struct poll_list) == 16

This means pp+1 did not match up with pp->entries. Im not sure what the
alignment requirements are for a zero length struct (ie is this a
compiler bug) but the following patch fixes the problem and also changes
->len to a long to ensure 8 byte alignment of ->entries on 64bit archs.

Anton

===== fs/select.c 1.15 vs edited =====
--- 1.15/fs/select.c	Sat Dec 21 20:42:41 2002
+++ edited/fs/select.c	Thu Dec 26 17:31:16 2002
@@ -362,7 +362,7 @@
 
 struct poll_list {
 	struct poll_list *next;
-	int len;
+	long len;
 	struct pollfd entries[0];
 };
 
@@ -471,7 +471,7 @@
 			walk->next = pp;
 
 		walk = pp;
-		if (copy_from_user(pp+1, ufds + nfds-i, 
+		if (copy_from_user(pp->entries, ufds + nfds-i, 
 				sizeof(struct pollfd)*pp->len)) {
 			err = -EFAULT;
 			goto out_fds;

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2002-12-27  0:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-26 20:55 [PATCH] 2.5 fast poll on ppc64 Mikael Pettersson
2002-12-26 21:23 ` Linus Torvalds
2002-12-26 21:42 ` Manfred Spraul
2002-12-27  0:14 ` Richard Henderson
  -- strict thread matches above, loose matches on Subject: below --
2002-12-26 12:57 Mikael Pettersson
2002-12-26 13:53 ` Manfred Spraul
2002-12-26  6:48 Anton Blanchard
2002-12-26 12:09 ` Manfred Spraul

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox