linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* fake loop
@ 2001-08-03 15:57 Andrey Ilinykh
  2001-08-03 16:07 ` Thomas Pornin
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Andrey Ilinykh @ 2001-08-03 15:57 UTC (permalink / raw)
  To: linux-kernel

Hi!
Very often I see in kernel such code as
do {
  dosomthing();
} while(0);

or even

#define prepare_to_switch()     do { } while(0)

Who can explain me a reason for these fake loops?
Thank you,
  Andrey


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

* Re: fake loop
  2001-08-03 15:57 fake loop Andrey Ilinykh
@ 2001-08-03 16:07 ` Thomas Pornin
  2001-08-03 16:11 ` Martin Mačok
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Thomas Pornin @ 2001-08-03 16:07 UTC (permalink / raw)
  To: ailinykh; +Cc: linux-kernel

In article <20010803155735.18620.qmail@nwcst31f.netaddress.usa.net> you write:
> #define prepare_to_switch()     do { } while(0)

This one is a classic C trick; it is documented in the K&R book. With
this fake loop, the macro can be used like a statement anywhere. For
instance, compare the two following :

#define macro1()	{ /* some stuff */ }
#define macro2()	do { /* some stuff */ } while (0)

if (foo) macro1(); else bar;
if (foo) macro2(); else bar;

The second one is correct, but the first one is incorrect (the extra
semi-colon unlinks the `else' from the `if').


Besides, a fake loop, within or outside a macro, can be useful: you jump
out of it with a `break' statement; you could do it with a `goto' but
with the `break' you do not have to bother about managing label names.


	--Thomas Pornin

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

* Re: fake loop
  2001-08-03 15:57 fake loop Andrey Ilinykh
  2001-08-03 16:07 ` Thomas Pornin
@ 2001-08-03 16:11 ` Martin Mačok
  2001-08-03 16:13 ` Crutcher Dunnavant
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Martin Mačok @ 2001-08-03 16:11 UTC (permalink / raw)
  To: linux-kernel

On Fri, Aug 03, 2001 at 09:57:34AM -0600, Andrey Ilinykh wrote:
> #define prepare_to_switch()     do { } while(0)
> 
> Who can explain me a reason for these fake loops?

http://kernelnewbies.org/faq/index.php3#dowhile.xml

There are a couple of reasons:

    * (from Dave Miller) Empty statements give a warning from the compiler so
        this is why you see #define FOO do { } while(0). 
    * (from Dave Miller) It gives
        you a basic block in which to declare local variables.
    * (from Ben Collins) It allows you to use more complex macros in
        conditional code. 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.

Have a nice day

-- 
   Martin Mačok
  underground.cz
    openbsd.cz

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

* Re: fake loop
  2001-08-03 15:57 fake loop Andrey Ilinykh
  2001-08-03 16:07 ` Thomas Pornin
  2001-08-03 16:11 ` Martin Mačok
@ 2001-08-03 16:13 ` Crutcher Dunnavant
  2001-08-03 16:25 ` Mike Frisch
  2001-08-03 16:44 ` Richard B. Johnson
  4 siblings, 0 replies; 8+ messages in thread
From: Crutcher Dunnavant @ 2001-08-03 16:13 UTC (permalink / raw)
  To: linux-kernel

++ 03/08/01 09:57 -0600 - Andrey Ilinykh:
> Hi!
> Very often I see in kernel such code as
> do {
>   dosomthing();
> } while(0);

This is a fake function. Macros often use this to give themselves an environment
to allocate stack variables in. Example:

 #define swap(A, B) \
 { \
	int C; \
	C = (A); (A) = (B); (B) = C; \
 } while(0)

swap will now act almost exactly like a function. Please note that this macro
does NOT have a semicolon on the end, as that would cause bad things if I did:

 if (test)
	swap(a,b);
 else
	do_something();

> or even
> #define prepare_to_switch()     do { } while(0)

This is most often found in situations where a code block becomes trivial when
a config option is turned off. The spinlock functions mostly become this when
SMP is not turned on, so they get optimized out of the code.

-- 
Crutcher        <crutcher@datastacks.com>
GCS d--- s+:>+:- a-- C++++$ UL++++$ L+++$>++++ !E PS+++ PE Y+ PGP+>++++
    R-(+++) !tv(+++) b+(++++) G+ e>++++ h+>++ r* y+>*$

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

* Re: fake loop
  2001-08-03 15:57 fake loop Andrey Ilinykh
                   ` (2 preceding siblings ...)
  2001-08-03 16:13 ` Crutcher Dunnavant
@ 2001-08-03 16:25 ` Mike Frisch
  2001-08-03 16:44 ` Richard B. Johnson
  4 siblings, 0 replies; 8+ messages in thread
From: Mike Frisch @ 2001-08-03 16:25 UTC (permalink / raw)
  To: linux-kernel

On Fri, Aug 03, 2001 at 09:57:34AM -0600, Andrey Ilinykh wrote:
> Very often I see in kernel such code as
> do {
>   dosomthing();
> } while(0);
> 
> or even
> 
> #define prepare_to_switch()     do { } while(0)
> 
> Who can explain me a reason for these fake loops?

This is answered in the Kernelnewbies FAQ @
http://kernelnewbies.org/faq/index.php3#dowhile.xml.

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

* Re: fake loop
  2001-08-03 15:57 fake loop Andrey Ilinykh
                   ` (3 preceding siblings ...)
  2001-08-03 16:25 ` Mike Frisch
@ 2001-08-03 16:44 ` Richard B. Johnson
  2001-08-04  0:13   ` J . A . Magallon
  4 siblings, 1 reply; 8+ messages in thread
From: Richard B. Johnson @ 2001-08-03 16:44 UTC (permalink / raw)
  To: Andrey Ilinykh; +Cc: linux-kernel

On 3 Aug 2001, Andrey Ilinykh wrote:

> Hi!
> Very often I see in kernel such code as
> do {
>   dosomthing();
> } while(0);
> 
> or even
> 
> #define prepare_to_switch()     do { } while(0)
> 
> Who can explain me a reason for these fake loops?
> Thank you,
>   Andrey
> 

Yes! This is neat! The { } defines a new program unit. Therefore,
you can allocate temporary variables within it, like:

    do {
        int i;
        for(i=0; i< MAX; i++)
          do_something(i);
       } while (0);

The new "i" doesn't interfere with any previous one because it is
an independent program-unit and it executes just once.

Then, the second reason is also real neat.

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

In the code, you can now do:

    if(event)
        foo;
    else
        bar;

Since the program unit contains its own {}, you don't have to worry
about what the "else" refers to, it always refers to if(event) even
if the "do while {} (0)" contains conditional statements.

FYI, it is an ISO C compatible construct, not a "gnuism". Therefore,
it is a safe and effective way to even make statements disappear
under certain conditions:

#ifdef __SMP__
#define foo something_that_exists_only_under_these_conditions()
#else
#define foo do { } while(0)
#


Cheers,
Dick Johnson

Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips).

    I was going to compile a list of innovations that could be
    attributed to Microsoft. Once I realized that Ctrl-Alt-Del
    was handled in the BIOS, I found that there aren't any.



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

* Re: fake loop
  2001-08-03 16:44 ` Richard B. Johnson
@ 2001-08-04  0:13   ` J . A . Magallon
  2001-08-04 18:47     ` Thomas Pornin
  0 siblings, 1 reply; 8+ messages in thread
From: J . A . Magallon @ 2001-08-04  0:13 UTC (permalink / raw)
  To: root; +Cc: Andrey Ilinykh, linux-kernel


On 20010803 Richard B. Johnson wrote:
>
>Yes! This is neat! The { } defines a new program unit. Therefore,
>you can allocate temporary variables within it, like:
>
>    do {
>        int i;
>        for(i=0; i< MAX; i++)
>          do_something(i);
>       } while (0);
>

I have heard many times that kernel is not thought to be compiled by anything
but gcc. Please, start useing gcc features, like statement expressions:

({
	int i;
	for(i=0; i< MAX; i++)
		do_something(i); 
})
-- 
J.A. Magallon                           #  Let the source be with you...        
mailto:jamagallon@able.es
Mandrake Linux release 8.1 (Cooker) for i586
Linux werewolf 2.4.7-ac3 #1 SMP Mon Jul 30 16:39:36 CEST 2001 i686

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

* Re: fake loop
  2001-08-04  0:13   ` J . A . Magallon
@ 2001-08-04 18:47     ` Thomas Pornin
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Pornin @ 2001-08-04 18:47 UTC (permalink / raw)
  To: jamagallon; +Cc: linux-kernel

In article <20010804021304.A21339@werewolf.able.es> you write:
> I have heard many times that kernel is not thought to be compiled by
> anything but gcc. Please, start useing gcc features

-- There is little point in using gcc-specific features when there is
a completely standard idiom that does the job just as well. Unless your
goal is to obliterate all potential hopes to compile the kernel with
another compiler at some time in the future.

-- I heard that the gcc people are not especially happy with that
feature anyway, and they will maintain it only for compatibility;
which means any potential optimisation will rather go into the
standard construct (the do...while(0)) rather than the gcc-ism.


	--Thomas Pornin

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

end of thread, other threads:[~2001-08-04 18:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-08-03 15:57 fake loop Andrey Ilinykh
2001-08-03 16:07 ` Thomas Pornin
2001-08-03 16:11 ` Martin Mačok
2001-08-03 16:13 ` Crutcher Dunnavant
2001-08-03 16:25 ` Mike Frisch
2001-08-03 16:44 ` Richard B. Johnson
2001-08-04  0:13   ` J . A . Magallon
2001-08-04 18:47     ` Thomas Pornin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).