2005-09-20 06:15:34

by 林建安

[permalink] [raw]
Subject: CONFIG_PRINTK doesn't makes size smaller


Hi there,
I tried to make kernel with CONFIG_PRINTK off. I considered it should become
smaller, but it didn't because it actually isn't an empty function, and
there are many copies of it in vmlinux, not just one. Here is its
definition:
static inline int printk(const char *s, ...) { return 0; }

I change the definition to this and it can greatly reduce the size by about
5%:
#define printk(...) do {} while (0)
However, this definition would lead to error in some situations. For
example:
1. (printk)
2. ret = printk

I hope someone could suggest a better definition of printk that can both
make printk smaller and eliminate errors.

Regards,
Colin



2005-09-20 06:38:19

by Andrey Panin

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller

On 263, 09 20, 2005 at 02:14:55PM +0800, colin wrote:
>
> Hi there,
> I tried to make kernel with CONFIG_PRINTK off. I considered it should become
> smaller, but it didn't because it actually isn't an empty function, and
> there are many copies of it in vmlinux, not just one. Here is its
> definition:
> static inline int printk(const char *s, ...) { return 0; }
>
> I change the definition to this and it can greatly reduce the size by about
> 5%:
> #define printk(...) do {} while (0)
> However, this definition would lead to error in some situations. For
> example:
> 1. (printk)
> 2. ret = printk
>
> I hope someone could suggest a better definition of printk that can both
> make printk smaller and eliminate errors.

What about the macro below ?

#define printk(...) ({ do { } while(0); 0; })

--
Andrey Panin | Linux and UNIX system administrator
[email protected] | PGP key: wwwkeys.pgp.net

2005-09-20 07:49:00

by Vadim Lobanov

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller

On Tue, 20 Sep 2005, Andrey Panin wrote:

> On 263, 09 20, 2005 at 02:14:55PM +0800, colin wrote:
> >
> > Hi there,
> > I tried to make kernel with CONFIG_PRINTK off. I considered it should become
> > smaller, but it didn't because it actually isn't an empty function, and
> > there are many copies of it in vmlinux, not just one. Here is its
> > definition:
> > static inline int printk(const char *s, ...) { return 0; }
> >
> > I change the definition to this and it can greatly reduce the size by about
> > 5%:
> > #define printk(...) do {} while (0)
> > However, this definition would lead to error in some situations. For
> > example:
> > 1. (printk)
> > 2. ret = printk
> >
> > I hope someone could suggest a better definition of printk that can both
> > make printk smaller and eliminate errors.
>
> What about the macro below ?
>
> #define printk(...) ({ do { } while(0); 0; })

So what does the do-while loop give us in the above case? In other
words, why not just do the following...?

#define printk(...) ({ 0; })

-VadimL

2005-09-20 08:04:24

by Andrew Morton

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller

Vadim Lobanov <[email protected]> wrote:
>
> On Tue, 20 Sep 2005, Andrey Panin wrote:
>
> > On 263, 09 20, 2005 at 02:14:55PM +0800, colin wrote:
> > >
> > > Hi there,
> > > I tried to make kernel with CONFIG_PRINTK off. I considered it should become
> > > smaller, but it didn't because it actually isn't an empty function, and
> > > there are many copies of it in vmlinux, not just one. Here is its
> > > definition:
> > > static inline int printk(const char *s, ...) { return 0; }
> > >
> > > I change the definition to this and it can greatly reduce the size by about
> > > 5%:
> > > #define printk(...) do {} while (0)
> > > However, this definition would lead to error in some situations. For
> > > example:
> > > 1. (printk)
> > > 2. ret = printk
> > >
> > > I hope someone could suggest a better definition of printk that can both
> > > make printk smaller and eliminate errors.
> >
> > What about the macro below ?
> >
> > #define printk(...) ({ do { } while(0); 0; })
>
> So what does the do-while loop give us in the above case? In other
> words, why not just do the following...?
>
> #define printk(...) ({ 0; })
>

You may find that when printk() is a static inline there are still copies
of the control string in the generated kernel image:

printk("foo %d\n", bar());

must still evaluate bar() and may cause "foo %d\n" to turn up in vmlinux.
IIRC later versions of gcc do remove the unreferenced string.

If printk is a macro, it all of course disappears.

2005-09-20 08:31:12

by Denis Vlasenko

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller

On Tuesday 20 September 2005 09:14, colin wrote:
>
> Hi there,
> I tried to make kernel with CONFIG_PRINTK off. I considered it should become
> smaller, but it didn't because it actually isn't an empty function, and
> there are many copies of it in vmlinux, not just one. Here is its
> definition:
> static inline int printk(const char *s, ...) { return 0; }
>
> I change the definition to this and it can greatly reduce the size by about
> 5%:
> #define printk(...) do {} while (0)
> However, this definition would lead to error in some situations. For
> example:
> 1. (printk)
> 2. ret = printk
>
> I hope someone could suggest a better definition of printk that can both
> make printk smaller and eliminate errors.

I think isolated testcase (a preprocessed .c file) would be interesting.
Use make dir/dir/file.i, reduce result to small .c file which shows
the problem, and show it on lkml.
--
vda

2005-09-20 09:03:05

by Andrey Panin

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller

On 263, 09 20, 2005 at 12:48:59AM -0700, Vadim Lobanov wrote:
> On Tue, 20 Sep 2005, Andrey Panin wrote:
>
> > On 263, 09 20, 2005 at 02:14:55PM +0800, colin wrote:
> > >
> > > Hi there,
> > > I tried to make kernel with CONFIG_PRINTK off. I considered it should become
> > > smaller, but it didn't because it actually isn't an empty function, and
> > > there are many copies of it in vmlinux, not just one. Here is its
> > > definition:
> > > static inline int printk(const char *s, ...) { return 0; }
> > >
> > > I change the definition to this and it can greatly reduce the size by about
> > > 5%:
> > > #define printk(...) do {} while (0)
> > > However, this definition would lead to error in some situations. For
> > > example:
> > > 1. (printk)
> > > 2. ret = printk
> > >
> > > I hope someone could suggest a better definition of printk that can both
> > > make printk smaller and eliminate errors.
> >
> > What about the macro below ?
> >
> > #define printk(...) ({ do { } while(0); 0; })
>
> So what does the do-while loop give us in the above case? In other
> words, why not just do the following...?

do-while loop eliminates "statement with no effect" warnings from gcc4.

> #define printk(...) ({ 0; })
>

--
Andrey Panin | Linux and UNIX system administrator
[email protected] | PGP key: wwwkeys.pgp.net

2005-09-20 09:12:11

by 林建安

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller


Hi all,
Andrey's suggestion can solve the compiling problem.

I also tested the problem that Vadim had just said. I found that the marco
version of printk indeed will have the problem in this kind of situation:
printk("foo %d\n", bar());
bar() in marco version of printk won't be called. Because someone may put
meaningful instructions in it, it may cause error.
Is there any better solution of definition of printk that can greatly reduce
size?

BTW, I see many function definitions in kernel using "do {} while(0);". Do
they have this kind of potential problem, too?

Regards,
Colin




----- Original Message -----
From: "Andrew Morton" <[email protected]>
To: "Vadim Lobanov" <[email protected]>
Cc: <[email protected]>; <[email protected]>;
<[email protected]>
Sent: Tuesday, September 20, 2005 4:03 PM
Subject: Re: CONFIG_PRINTK doesn't makes size smaller


> Vadim Lobanov <[email protected]> wrote:
> >
> > On Tue, 20 Sep 2005, Andrey Panin wrote:
> >
> > > On 263, 09 20, 2005 at 02:14:55PM +0800, colin wrote:
> > > >
> > > > Hi there,
> > > > I tried to make kernel with CONFIG_PRINTK off. I considered it
should become
> > > > smaller, but it didn't because it actually isn't an empty function,
and
> > > > there are many copies of it in vmlinux, not just one. Here is its
> > > > definition:
> > > > static inline int printk(const char *s, ...) { return 0; }
> > > >
> > > > I change the definition to this and it can greatly reduce the size
by about
> > > > 5%:
> > > > #define printk(...) do {} while (0)
> > > > However, this definition would lead to error in some situations. For
> > > > example:
> > > > 1. (printk)
> > > > 2. ret = printk
> > > >
> > > > I hope someone could suggest a better definition of printk that can
both
> > > > make printk smaller and eliminate errors.
> > >
> > > What about the macro below ?
> > >
> > > #define printk(...) ({ do { } while(0); 0; })
> >
> > So what does the do-while loop give us in the above case? In other
> > words, why not just do the following...?
> >
> > #define printk(...) ({ 0; })
> >
>
> You may find that when printk() is a static inline there are still copies
> of the control string in the generated kernel image:
>
> printk("foo %d\n", bar());
>
> must still evaluate bar() and may cause "foo %d\n" to turn up in vmlinux.
> IIRC later versions of gcc do remove the unreferenced string.
>
> If printk is a macro, it all of course disappears.

2005-09-20 15:41:51

by Vadim Lobanov

[permalink] [raw]
Subject: Re: CONFIG_PRINTK doesn't makes size smaller

On Tue, 20 Sep 2005, Andrey Panin wrote:

> On 263, 09 20, 2005 at 12:48:59AM -0700, Vadim Lobanov wrote:
> > On Tue, 20 Sep 2005, Andrey Panin wrote:
> >
> > > On 263, 09 20, 2005 at 02:14:55PM +0800, colin wrote:
> > > >
> > > > Hi there,
> > > > I tried to make kernel with CONFIG_PRINTK off. I considered it should become
> > > > smaller, but it didn't because it actually isn't an empty function, and
> > > > there are many copies of it in vmlinux, not just one. Here is its
> > > > definition:
> > > > static inline int printk(const char *s, ...) { return 0; }
> > > >
> > > > I change the definition to this and it can greatly reduce the size by about
> > > > 5%:
> > > > #define printk(...) do {} while (0)
> > > > However, this definition would lead to error in some situations. For
> > > > example:
> > > > 1. (printk)
> > > > 2. ret = printk
> > > >
> > > > I hope someone could suggest a better definition of printk that can both
> > > > make printk smaller and eliminate errors.
> > >
> > > What about the macro below ?
> > >
> > > #define printk(...) ({ do { } while(0); 0; })
> >
> > So what does the do-while loop give us in the above case? In other
> > words, why not just do the following...?
>
> do-while loop eliminates "statement with no effect" warnings from gcc4.
>
> > #define printk(...) ({ 0; })
> >

Funky: gcc3.3.4 seems to like it just fine. I am rather curious why gcc4
has different semantics in this case. But that is probably off-topic for
this list...

In either case, as Andrew Morton pointed out, function invokations as
arguments don't get expanded out in the case of it being a macro, so no
dice.

> --
> Andrey Panin | Linux and UNIX system administrator
> [email protected] | PGP key: wwwkeys.pgp.net
>

-VadimL