2001-04-05 12:57:49

by Sardañons, Eliel

[permalink] [raw]
Subject: asm/unistd.h

I'm taking a look at the linux code and I don't understand how do you
programm...mmm (?) may be i'm a stupid why in include/asm/unistd.h in some
macros you use this:

do {
...
} while (0)

Thanks in advance.

Eliel C. Sardanons


2001-04-05 13:08:50

by David Miller

[permalink] [raw]
Subject: Re: asm/unistd.h


[email protected], Eliel writes:
> I'm taking a look at the linux code and I don't understand how do you
> programm...mmm (?) may be i'm a stupid why in include/asm/unistd.h in some
> macros you use this:

Two reasons:

1) Empty statements give a warning from the compiler so
this is why you see "#define FOO do { } while(0)"
2) It gives you a basic block in which to declare local
variables.

Later,
David S. Miller
[email protected]

2001-04-05 13:08:14

by Bart Trojanowski

[permalink] [raw]
Subject: Re: asm/unistd.h

On Thu, 5 Apr 2001, Sarda?ons, Eliel wrote:

> I'm taking a look at the linux code and I don't understand how do you
> programm...mmm (?) may be i'm a stupid why in include/asm/unistd.h in some
> macros you use this:
>
> do {
> ...
> } while (0)

This is a very useful trick.

If you define a macro such as:

#define foo(x) do_one(x); do_two(x); do_three(x)

you may later be compelled to call it in an if statement:

if(condition)
foo(something);

note that it would not do what you want as it will only execute do_one(x)
conditionally but do_two(x) and do_three(x) would always be done.

However a do{ ... } while(0) is a nice convenient block which is
guaranteed to execute once. The compiler (with a -O flag) will not
generate any extra code for the do{}while(0) so its just a macro building
aid.

So you ask: "why not just use a { ... } to define a macro". I don't
remember the case for this but I know it's there. It has to do with a
complicated if/else structure where a simple {} breaks.

Cheers,
Bart.


--
WebSig: http://www.jukie.net/~bart/sig/


2001-04-05 13:14:00

by Tim Waugh

[permalink] [raw]
Subject: Re: asm/unistd.h

On Thu, Apr 05, 2001 at 09:06:20AM -0400, Bart Trojanowski wrote:

> So you ask: "why not just use a { ... } to define a macro". I don't
> remember the case for this but I know it's there. It has to do with a
> complicated if/else structure where a simple {} breaks.

It's for eating the semi-colon after the macro invocation.

Tim.
*/


Attachments:
(No filename) (338.00 B)
(No filename) (232.00 B)
Download all attachments

2001-04-05 13:15:01

by Ben Collins

[permalink] [raw]
Subject: Re: asm/unistd.h

On Thu, Apr 05, 2001 at 09:58:43AM -0300, Sarda?ons, Eliel wrote:
> I'm taking a look at the linux code and I don't understand how do you
> programm...mmm (?) may be i'm a stupid why in include/asm/unistd.h in some
> macros you use this:
>
> do {
> ...
> } while (0)

Imagine a macro of several lines of code like:

#define FOO(x) \
printf("arg is %s\n", x); \
do_something_useful(x);

Now imagine using it like:

if (blah == 2)
FOO(blah);

This interprets to

if (blah == 2)
printf("arg is %s\n", blah);
do_something_useful(blah);;

As you can see, the "if" then only encompasses the printf, and the
do_something_useful() call is unconditional (not within the scope of the
if), like you wanted it.

So, by using a block like do{...}while(0), you would get this:

if (blah == 2)
do {
printf("arg is %s\n", blah);
do_something_useful(blah);
} while (0);

Which is exactly what you want.

--
-----------=======-=-======-=========-----------=====------------=-=------
/ Ben Collins -- ...on that fantastic voyage... -- Debian GNU/Linux \
` [email protected] -- [email protected] -- [email protected] '
`---=========------=======-------------=-=-----=-===-======-------=--=---'

2001-04-05 14:27:48

by Joseph Carter

[permalink] [raw]
Subject: Re: asm/unistd.h

On Thu, Apr 05, 2001 at 09:06:20AM -0400, Bart Trojanowski wrote:
> So you ask: "why not just use a { ... } to define a macro". I don't
> remember the case for this but I know it's there. It has to do with a
> complicated if/else structure where a simple {} breaks.

This doesn't follow in my mind. I can't think of a case where a { ... }
would fail, but a do { ... } while (0) would succeed. The former would
also save a few keystrokes.

--
Joseph Carter <[email protected]> Free software developer

// Minor lesson: don't fuck about with something you don't fully understand
-- the dosdoom source code


Attachments:
(No filename) (635.00 B)
(No filename) (273.00 B)
Download all attachments

2001-04-05 14:36:08

by Stephen Thomas

[permalink] [raw]
Subject: Re: asm/unistd.h

Joseph Carter wrote:
> This doesn't follow in my mind. I can't think of a case where a { ... }
> would fail, but a do { ... } while (0) would succeed. The former would
> also save a few keystrokes.

#define FOO(x) { wibble(x); wobble((x)+1);}

if (something)
FOO(23);
else /* Compile goes crump here. */
another_thing();


Stephen Thomas

2001-04-05 14:36:38

by Bart Trojanowski

[permalink] [raw]
Subject: Re: asm/unistd.h

On Thu, 5 Apr 2001, Joseph Carter wrote:

> On Thu, Apr 05, 2001 at 09:06:20AM -0400, Bart Trojanowski wrote:
> > So you ask: "why not just use a { ... } to define a macro". I don't
> > remember the case for this but I know it's there. It has to do with a
> > complicated if/else structure where a simple {} breaks.
>
> This doesn't follow in my mind. I can't think of a case where a { ... }
> would fail, but a do { ... } while (0) would succeed. The former would
> also save a few keystrokes.

Tim Waugh already stated this one:

#define foo(x) { do_something(x) }

if( condition )
foo(x);
else
foo(y);

would produce

if( condition )
{ do_something(x) };
else
{ do_something(y) };

note the semi-colon at the end of {.*}.

This is bad because it forces you to use the foo macro knowing it's a
macro and not a function.

So you say I will use it like this:

if( condition )
foo(x)
else
foo(y)

That's just great for this case, but now imagine that on some other
architecture doing foo(x) takes many many lines with recursion and all.
You don't want that to be in a macro so you make a function. And you get
many many compiler errors on thsi new platform.

Cheers,
Bart.

--
WebSig: http://www.jukie.net/~bart/sig/


2001-04-05 14:46:49

by Andreas Schwab

[permalink] [raw]
Subject: Re: asm/unistd.h

Joseph Carter <[email protected]> writes:

|> On Thu, Apr 05, 2001 at 09:06:20AM -0400, Bart Trojanowski wrote:
|> > So you ask: "why not just use a { ... } to define a macro". I don't
|> > remember the case for this but I know it's there. It has to do with a
|> > complicated if/else structure where a simple {} breaks.
|>
|> This doesn't follow in my mind. I can't think of a case where a { ... }
|> would fail, but a do { ... } while (0) would succeed. The former would
|> also save a few keystrokes.

Try this and watch your compiler complaining:

#define foo() { }
#define bar() do { } while (0)
void mumble ()
{
if (1) foo(); else bar();
if (2) bar(); else foo();
}

Andreas.

--
Andreas Schwab "And now for something
SuSE Labs completely different."
[email protected]
SuSE GmbH, Schanz?ckerstr. 10, D-90443 N?rnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5

2001-04-05 15:24:28

by Steve Grubb

[permalink] [raw]
Subject: Re: asm/unistd.h

It would seem to me that after hearing how the macros are used in practice,
wouldn't turning them into inline functions be an improvement? This is
something gcc supports, it accomplishes the same thing, and has the added
advantage of type checking.
http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC92

Or perhaps type checking macro arguments would be another fertile area for
the Stanford Checker...

Cheers,
Steve Grubb

2001-04-05 15:43:01

by Bart Trojanowski

[permalink] [raw]
Subject: Re: asm/unistd.h

On Thu, 5 Apr 2001, Steve Grubb wrote:

> It would seem to me that after hearing how the macros are used in practice,
> wouldn't turning them into inline functions be an improvement? This is
> something gcc supports, it accomplishes the same thing, and has the added
> advantage of type checking.
> http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC92
>
> Or perhaps type checking macro arguments would be another fertile area for
> the Stanford Checker...

There are benefits to macros too. One that I like for debuggin is that
the C parser will unravel a macro within the context of the execution:

#ifdef DEBUG
#define KMALLOC(x,y) \
printk(__FILE__ ":%d: kmalloc(%d,%d")\n", __LINE__,x,y); \
kmalloc(x,y);
#else
#define KMALLOC(x,y) \
kmalloc(x,y);
#endif

I think the benefit of a macro here is quite visible... you cannot do this
with an inline.

You may also look at some better reasons:

http://www.uwsg.iu.edu/hypermail/linux/kernel/9810.3/0323.html

[btw I found this by looking for 'macros vs inline' on google/linux]

Bart.

--
WebSig: http://www.jukie.net/~bart/sig/


2001-04-05 15:46:21

by David Miller

[permalink] [raw]
Subject: Re: asm/unistd.h


Steve Grubb writes:
> It would seem to me that after hearing how the macros are used in practice,
> wouldn't turning them into inline functions be an improvement? This is
> something gcc supports, it accomplishes the same thing, and has the added
> advantage of type checking.
> http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC92

Two reasons:

1) Sometimes I don't want any type checking because it would create
the necessity of adding a new include to a file --> a circular
dependency to resolve. Macros hide the types except in the
cases where they are actually invoked :-)

2) Historically GCC was very bad with code generation with inline
functions, so at that time the GCC manual statement "inline
functions are just like a macro" was technically false :-)

Yes, I know this is much different in today's gcc tree, but
there hasn't been a gcc release in over 2 years so...

Later,
David S. Miller
[email protected]

2001-04-05 17:39:51

by J.A. Magallon

[permalink] [raw]
Subject: Re: asm/unistd.h


On 04.05 Andreas Schwab wrote:
>
> Try this and watch your compiler complaining:
>
> #define foo() { }
> #define bar() do { } while (0)
> void mumble ()
> {
> if (1) foo(); else bar();
> if (2) bar(); else foo();
> }
>

Perhaps it is time to USE gcc, yet the kernel can be built only with gcc.
IE, use statement expressions.

Try this:

#define foo() ({ })
#define bar() do { } while (0)
void mumble ()
{
if (1) foo(); else bar();
if (2) bar(); else foo();
}

and see you compiler shutup.
You can even declare vars inside the ({ ... }) block,
so all the

#define bar(x) do { use_1(x); use_2(x); } while (0)

could be written like:

#define bar(x) ({ use_1(x); use_2(x); })

Even you can use <typeof>:

#define swap(a,b) \
({ typeof(a) tmp = a; \
a = b; \
b = tmp; \
})

int main()
{
int a,b;
double c,d;

swap(a,b);
swap(c,d);
}

Its correct in egcs-1.1.2 and up, so it is safe for use in kernel 2.4.
Do not know if previuous gcc eats it up.

--
J.A. Magallon # Let the source
mailto:[email protected] # be with you, Luke...

Linux werewolf 2.4.3-ac3 #1 SMP Thu Apr 5 00:28:45 CEST 2001 i686