All of lore.kernel.org
 help / color / mirror / Atom feed
* Eliminating nested functions
@ 2009-04-17 15:54 Pavel Roskin
  2009-04-17 19:33 ` Bean
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Pavel Roskin @ 2009-04-17 15:54 UTC (permalink / raw)
  To: The development of GRUB 2

Hello!

While I have just applied a patch adding NESTED_FUNC_ATTR to several
functions as an emergency fix for a major breakage in ata, ohci, uhci
and lspci modules, I would prefer a more radical solution.

I suggest that we eliminate all nested functions.  The reasons are:

1) They make the code less readable, as they make the parent functions
longer.

2) They have problems with some popular compilers, as recent as gcc-4.0
when regparm(3) is used.

3) We failed to implement a reliable test for such problems.  We are
using regparm(1) for all compilers.

4) The existing test is one of the obstacles making it impossible to
compile without having libc for the target (x86_64->i386 would be really
nice), as we need to run the compiled test executable.

5) Non-i386 architectures define NESTED_FUNC_ATTR as an empty symbol, so
developers on such architectures don't see if they use it correctly.

6) NESTED_FUNC_ATTR tends to proliferate to the file scope functions, as
it happened with grub_pci_iterate().  It only takes one caller using a
nested function to force NESTED_FUNC_ATTR on all functions used as an
argument to the same function.

We can give all formerly nested functions better, more descriptive names
starting like other functions in the file and ending with "_iter".

-- 
Regards,
Pavel Roskin



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

* Re: Eliminating nested functions
  2009-04-17 15:54 Eliminating nested functions Pavel Roskin
@ 2009-04-17 19:33 ` Bean
  2009-04-17 19:52   ` Vladimir Serbinenko
  2009-04-17 21:38   ` Pavel Roskin
  2009-04-17 21:57 ` Christian Franke
  2009-04-17 23:17 ` David Miller
  2 siblings, 2 replies; 12+ messages in thread
From: Bean @ 2009-04-17 19:33 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

One of the advantage of nested function is to use local variables.
Without it, we would need to pass them as global variable, or add
custom data pointer in many of the iterate function, which would make
the code a lot uglier IMO.

On Fri, Apr 17, 2009 at 11:54 PM, Pavel Roskin <proski@gnu.org> wrote:
> Hello!
>
> While I have just applied a patch adding NESTED_FUNC_ATTR to several
> functions as an emergency fix for a major breakage in ata, ohci, uhci
> and lspci modules, I would prefer a more radical solution.
>
> I suggest that we eliminate all nested functions.  The reasons are:
>
> 1) They make the code less readable, as they make the parent functions
> longer.
>
> 2) They have problems with some popular compilers, as recent as gcc-4.0
> when regparm(3) is used.
>
> 3) We failed to implement a reliable test for such problems.  We are
> using regparm(1) for all compilers.
>
> 4) The existing test is one of the obstacles making it impossible to
> compile without having libc for the target (x86_64->i386 would be really
> nice), as we need to run the compiled test executable.
>
> 5) Non-i386 architectures define NESTED_FUNC_ATTR as an empty symbol, so
> developers on such architectures don't see if they use it correctly.
>
> 6) NESTED_FUNC_ATTR tends to proliferate to the file scope functions, as
> it happened with grub_pci_iterate().  It only takes one caller using a
> nested function to force NESTED_FUNC_ATTR on all functions used as an
> argument to the same function.
>
> We can give all formerly nested functions better, more descriptive names
> starting like other functions in the file and ending with "_iter".
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Bean



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

* Re: Eliminating nested functions
  2009-04-17 19:33 ` Bean
@ 2009-04-17 19:52   ` Vladimir Serbinenko
  2009-04-17 21:38   ` Pavel Roskin
  1 sibling, 0 replies; 12+ messages in thread
From: Vladimir Serbinenko @ 2009-04-17 19:52 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2298 bytes --]

On Fri, Apr 17, 2009 at 9:33 PM, Bean <bean123ch@gmail.com> wrote:

> Hi,
>
> One of the advantage of nested function is to use local variables.
> Without it, we would need to pass them as global variable, or add
> custom data pointer in many of the iterate function, which would make
> the code a lot uglier IMO.
>
Do you have information in which direction it will influence the size of
kernel? (trampoline vs global vs custom pointer)


>
> On Fri, Apr 17, 2009 at 11:54 PM, Pavel Roskin <proski@gnu.org> wrote:
> > Hello!
> >
> > While I have just applied a patch adding NESTED_FUNC_ATTR to several
> > functions as an emergency fix for a major breakage in ata, ohci, uhci
> > and lspci modules, I would prefer a more radical solution.
> >
> > I suggest that we eliminate all nested functions.  The reasons are:
> >
> > 1) They make the code less readable, as they make the parent functions
> > longer.
> >
> > 2) They have problems with some popular compilers, as recent as gcc-4.0
> > when regparm(3) is used.
> >
> > 3) We failed to implement a reliable test for such problems.  We are
> > using regparm(1) for all compilers.
> >
> > 4) The existing test is one of the obstacles making it impossible to
> > compile without having libc for the target (x86_64->i386 would be really
> > nice), as we need to run the compiled test executable.
> >
> > 5) Non-i386 architectures define NESTED_FUNC_ATTR as an empty symbol, so
> > developers on such architectures don't see if they use it correctly.
> >
> > 6) NESTED_FUNC_ATTR tends to proliferate to the file scope functions, as
> > it happened with grub_pci_iterate().  It only takes one caller using a
> > nested function to force NESTED_FUNC_ATTR on all functions used as an
> > argument to the same function.
> >
> > We can give all formerly nested functions better, more descriptive names
> > starting like other functions in the file and ending with "_iter".
> >
> > --
> > Regards,
> > Pavel Roskin
> >
> >
> > _______________________________________________
> > Grub-devel mailing list
> > Grub-devel@gnu.org
> > http://lists.gnu.org/mailman/listinfo/grub-devel
> >
>
>
>
> --
> Bean
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>

[-- Attachment #2: Type: text/html, Size: 3475 bytes --]

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

* Re: Eliminating nested functions
  2009-04-17 19:33 ` Bean
  2009-04-17 19:52   ` Vladimir Serbinenko
@ 2009-04-17 21:38   ` Pavel Roskin
  2009-04-19  6:38     ` Bean
  1 sibling, 1 reply; 12+ messages in thread
From: Pavel Roskin @ 2009-04-17 21:38 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, 2009-04-18 at 03:33 +0800, Bean wrote: 
> Hi,
> 
> One of the advantage of nested function is to use local variables.
> Without it, we would need to pass them as global variable, or add
> custom data pointer in many of the iterate function, which would make
> the code a lot uglier IMO.

Indeed, I tried to get rid on nested functions in fs/ext2.c, and it
requires more changes than I expected.

However, my impression is that everything can be written nicely with
more effort.  Some arguments could be put into the structures we need to
pass, so the number of arguments doesn't increase.

We should probably try to avoid adding new nested functions in the
meantime.

-- 
Regards,
Pavel Roskin



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

* Re: Eliminating nested functions
  2009-04-17 15:54 Eliminating nested functions Pavel Roskin
  2009-04-17 19:33 ` Bean
@ 2009-04-17 21:57 ` Christian Franke
  2009-04-17 23:17 ` David Miller
  2 siblings, 0 replies; 12+ messages in thread
From: Christian Franke @ 2009-04-17 21:57 UTC (permalink / raw)
  To: The development of GRUB 2

Pavel Roskin wrote:
> I suggest that we eliminate all nested functions.  The reasons are:
>
> 1) They make the code less readable, as they make the parent functions
> longer.
>
> 2) They have problems with some popular compilers, as recent as gcc-4.0
> when regparm(3) is used.
>
> 3) We failed to implement a reliable test for such problems.  We are
> using regparm(1) for all compilers.
>
> 4) The existing test is one of the obstacles making it impossible to
> compile without having libc for the target (x86_64->i386 would be really
> nice), as we need to run the compiled test executable.
>
> 5) Non-i386 architectures define NESTED_FUNC_ATTR as an empty symbol, so
> developers on such architectures don't see if they use it correctly.
>
> 6) NESTED_FUNC_ATTR tends to proliferate to the file scope functions, as
> it happened with grub_pci_iterate().  It only takes one caller using a
> nested function to force NESTED_FUNC_ATTR on all functions used as an
> argument to the same function.
>
>   

7) The grub utils may not run on some 'security hardened' platform which 
does not allow to enable stack execution.


-- 
Christian Franke




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

* Re: Eliminating nested functions
  2009-04-17 15:54 Eliminating nested functions Pavel Roskin
  2009-04-17 19:33 ` Bean
  2009-04-17 21:57 ` Christian Franke
@ 2009-04-17 23:17 ` David Miller
  2009-04-18 15:57   ` Colin D Bennett
  2 siblings, 1 reply; 12+ messages in thread
From: David Miller @ 2009-04-17 23:17 UTC (permalink / raw)
  To: grub-devel, proski

From: Pavel Roskin <proski@gnu.org>
Date: Fri, 17 Apr 2009 11:54:57 -0400

> I suggest that we eliminate all nested functions.

I support this completely.



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

* Re: Eliminating nested functions
  2009-04-17 23:17 ` David Miller
@ 2009-04-18 15:57   ` Colin D Bennett
  2009-04-19  3:52     ` David Miller
  0 siblings, 1 reply; 12+ messages in thread
From: Colin D Bennett @ 2009-04-18 15:57 UTC (permalink / raw)
  To: The development of GRUB 2

David Miller wrote on Friday 17 April 2009:
> From: Pavel Roskin <proski@gnu.org>
> Date: Fri, 17 Apr 2009 11:54:57 -0400
>
> > I suggest that we eliminate all nested functions.
>
> I support this completely.

Me too.

While I like the idea of nested functions, since they are like closures and 
make a lot of common operations (such as iterating over a collection) a little 
more concise in the source code, you can certainly implement anything without 
nested functions that you can with them.  Probably passing a pointer to a 
local structure is the easiest way to do it in most cases if the iteration 
function needs to access some state, right?

Regards,
Colin



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

* Re: Eliminating nested functions
  2009-04-18 15:57   ` Colin D Bennett
@ 2009-04-19  3:52     ` David Miller
  0 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2009-04-19  3:52 UTC (permalink / raw)
  To: grub-devel, colin

From: Colin D Bennett <colin@gibibit.com>
Date: Sat, 18 Apr 2009 08:57:33 -0700

> Probably passing a pointer to a local structure is the easiest way
> to do it in most cases if the iteration function needs to access
> some state, right?

Right.

The biggest surprise for me, easily, when reading the grub2 sources
for the first time was seeing all of this masterbation with nested
functions.



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

* Re: Eliminating nested functions
  2009-04-17 21:38   ` Pavel Roskin
@ 2009-04-19  6:38     ` Bean
  2009-04-19 14:29       ` Pavel Roskin
  0 siblings, 1 reply; 12+ messages in thread
From: Bean @ 2009-04-19  6:38 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

Yeah, I agree with you. The conversion will take some effort, but it
could payoff in the long run. Perhaps we can achieve this in two
steps:

1, Change nested function definition to accept only one parameter. For
function with multiple parameters, place them in a structure and pass
the pointer. This would eliminate NESTED_FUNC_ATTR, as the regparm
issue won't occur in function with only one parameter.

2. Eliminate nested function. This would be easier after step 1. As we
now pass parameters in a structure, we can append extra variables at
the end, and cast it to the required type. Inside the callback
function, we cast it back to use the extra fields.

On Sat, Apr 18, 2009 at 5:38 AM, Pavel Roskin <proski@gnu.org> wrote:
> On Sat, 2009-04-18 at 03:33 +0800, Bean wrote:
>> Hi,
>>
>> One of the advantage of nested function is to use local variables.
>> Without it, we would need to pass them as global variable, or add
>> custom data pointer in many of the iterate function, which would make
>> the code a lot uglier IMO.
>
> Indeed, I tried to get rid on nested functions in fs/ext2.c, and it
> requires more changes than I expected.
>
> However, my impression is that everything can be written nicely with
> more effort.  Some arguments could be put into the structures we need to
> pass, so the number of arguments doesn't increase.
>
> We should probably try to avoid adding new nested functions in the
> meantime.
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Bean



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

* Re: Eliminating nested functions
  2009-04-19  6:38     ` Bean
@ 2009-04-19 14:29       ` Pavel Roskin
  2009-04-19 14:51         ` Vladimir Serbinenko
  0 siblings, 1 reply; 12+ messages in thread
From: Pavel Roskin @ 2009-04-19 14:29 UTC (permalink / raw)
  To: The development of GRUB 2

Quoting Bean <bean123ch@gmail.com>:

> Yeah, I agree with you. The conversion will take some effort, but it
> could payoff in the long run. Perhaps we can achieve this in two
> steps:
>
> 1, Change nested function definition to accept only one parameter. For
> function with multiple parameters, place them in a structure and pass
> the pointer. This would eliminate NESTED_FUNC_ATTR, as the regparm
> issue won't occur in function with only one parameter.
>
> 2. Eliminate nested function. This would be easier after step 1. As we
> now pass parameters in a structure, we can append extra variables at
> the end, and cast it to the required type. Inside the callback
> function, we cast it back to use the extra fields.

That's an excellent plan!  Thank you!

Considering the amount of changes, it may be a good idea to use the  
git mirror with stgit, so that several patches can be made and  
everything is well tested together before applying.

-- 
Regards,
Pavel Roskin



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

* Re: Eliminating nested functions
  2009-04-19 14:29       ` Pavel Roskin
@ 2009-04-19 14:51         ` Vladimir Serbinenko
  2009-04-19 16:52           ` Bean
  0 siblings, 1 reply; 12+ messages in thread
From: Vladimir Serbinenko @ 2009-04-19 14:51 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1555 bytes --]

In my opinion a far better way would be to add an additional void * argument
which is passed unchanged to the hook. Like:

struct local
{
   ...
};

main_func ()
{
struct local locvars;

grub_*_iterate (arg1,arg2,arg3, &locvars);
}

hook (arg1, arg2, arg3, voidparg)
{
struct local *locvars = (struct local *) voidparg;

}

On Sun, Apr 19, 2009 at 4:29 PM, Pavel Roskin <proski@gnu.org> wrote:

> Quoting Bean <bean123ch@gmail.com>:
>
>  Yeah, I agree with you. The conversion will take some effort, but it
>> could payoff in the long run. Perhaps we can achieve this in two
>> steps:
>>
>> 1, Change nested function definition to accept only one parameter. For
>> function with multiple parameters, place them in a structure and pass
>> the pointer. This would eliminate NESTED_FUNC_ATTR, as the regparm
>> issue won't occur in function with only one parameter.
>>
>> 2. Eliminate nested function. This would be easier after step 1. As we
>> now pass parameters in a structure, we can append extra variables at
>> the end, and cast it to the required type. Inside the callback
>> function, we cast it back to use the extra fields.
>>
>
> That's an excellent plan!  Thank you!
>
> Considering the amount of changes, it may be a good idea to use the git
> mirror with stgit, so that several patches can be made and everything is
> well tested together before applying.
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>

[-- Attachment #2: Type: text/html, Size: 2395 bytes --]

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

* Re: Eliminating nested functions
  2009-04-19 14:51         ` Vladimir Serbinenko
@ 2009-04-19 16:52           ` Bean
  0 siblings, 0 replies; 12+ messages in thread
From: Bean @ 2009-04-19 16:52 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

Right, we can wrap the local variables in void* and pass them in a
custom pointer, but I still think it's advantageous to put them in a
structure rather than use multiple parameters:

1, We can still use nested function. Sometimes it may seem tedious to
use external function for simple callback function. IMO, nested
function is not that bad, we just have to use it safely.

2. It's extensible. For example, we may need to add new information
for the hook function (such as adding modification time for dir hook).
With the structure pointer, we just need to add a new field, old code
that doesn' t use this information doesn't need to change. With
parameters, we need to change the definition of all callback function,
and the numerous __attribute__ ((unused)) is not pretty either.

On Sun, Apr 19, 2009 at 10:51 PM, Vladimir Serbinenko <phcoder@gmail.com> wrote:
> In my opinion a far better way would be to add an additional void * argument
> which is passed unchanged to the hook. Like:
>
> struct local
> {
>    ...
> };
>
> main_func ()
> {
> struct local locvars;
>
> grub_*_iterate (arg1,arg2,arg3, &locvars);
> }
>
> hook (arg1, arg2, arg3, voidparg)
> {
> struct local *locvars = (struct local *) voidparg;
>
> }
>
> On Sun, Apr 19, 2009 at 4:29 PM, Pavel Roskin <proski@gnu.org> wrote:
>>
>> Quoting Bean <bean123ch@gmail.com>:
>>
>>> Yeah, I agree with you. The conversion will take some effort, but it
>>> could payoff in the long run. Perhaps we can achieve this in two
>>> steps:
>>>
>>> 1, Change nested function definition to accept only one parameter. For
>>> function with multiple parameters, place them in a structure and pass
>>> the pointer. This would eliminate NESTED_FUNC_ATTR, as the regparm
>>> issue won't occur in function with only one parameter.
>>>
>>> 2. Eliminate nested function. This would be easier after step 1. As we
>>> now pass parameters in a structure, we can append extra variables at
>>> the end, and cast it to the required type. Inside the callback
>>> function, we cast it back to use the extra fields.
>>
>> That's an excellent plan!  Thank you!
>>
>> Considering the amount of changes, it may be a good idea to use the git
>> mirror with stgit, so that several patches can be made and everything is
>> well tested together before applying.
>>
>> --
>> Regards,
>> Pavel Roskin
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>



-- 
Bean



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

end of thread, other threads:[~2009-04-19 16:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-17 15:54 Eliminating nested functions Pavel Roskin
2009-04-17 19:33 ` Bean
2009-04-17 19:52   ` Vladimir Serbinenko
2009-04-17 21:38   ` Pavel Roskin
2009-04-19  6:38     ` Bean
2009-04-19 14:29       ` Pavel Roskin
2009-04-19 14:51         ` Vladimir Serbinenko
2009-04-19 16:52           ` Bean
2009-04-17 21:57 ` Christian Franke
2009-04-17 23:17 ` David Miller
2009-04-18 15:57   ` Colin D Bennett
2009-04-19  3:52     ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.