[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: multi CPU's

On Sat, Apr 08, 2000 at 10:34:18AM +0300, Eray Ozkural wrote:
> Andreas Bombe wrote:
> > > Though I'm pretty sure those preprocessor symbols are then scattered
> > > all over the megs of source code. But that seems to be less than 1000.
> > > [I've checked].
> > 
> > That's the Linux design philosophy.  Put the necessary #ifdefs into
> > header files to define macros which to avoid #ifdefs in the actual C
> > files.  That means that your count is multiplied by the count of each
> >         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > macro use.
> ^^^^^^^^^^^^
> Ha ha ha! Excuse me? Do you suggest that cpp makes multiple passes to
> further expand preprocessor symbols once again. I hadn't heard this before :)

Me neither.  "Multiplied" was probably the wrong word to use here.

> So let's see, I write
> <<
> #include <stdio.h>
> #define ENTER_SUCKY #ifdef __SUCKY__
> #define EXIT_SUCKY #endif
> printf("I suck completely\n");
> >>
> in a file called suck.c

No, what I meant is that macros or inlines are defined conditionally
one way or the other.  So the one #ifdef used in the header really
influences the many instances of the macro/inline function being
To pick out just one simple example:

#define smp_processor_id()                      0

and if SMP is enabled

#define smp_processor_id() (current->processor)

So everywhere smp_processor_id() is called the code is different,
without there being an "#ifdef CONFIG_SMP" anywhere near the code.  If
you just count occurances of CONFIG_SMP you will catch the definition,
but that is only seen by the preprocessor.  The compiler will not see
the #ifdef but the lots of places that changed because of that.

> > 
> > [1] Modules must always be compiled with the same compiler and kernel
> >     options as the kernel used.  Otherwise you really ask for
> >     problems.  Don't install separately downloaded binary modules.
> > 
> Yep, yep, yep, I guess. It's so easy to make your MT code blow up.  That's
> why I think there should be this standard kernel-image binary with SMP support
> in it. For convenience.
> OTOH, what you say if of course 100% correct. If there's a macro that handles
> some SMP stuff, and that macro is used in every device driver and alike, then
> there'd be an explosion which would surprise me. But I didn't see such a
> magic preprocessor macro.

Sorry?  I talked about spin locks.  At some point every driver which
tries to work on SMP will need them, and they are conditionally

> The extensive inlining would be a problem, because
> it could cause code explosion. [Which you mentioned as (a) ] Check this:
> you know where this beast comes from :)
> extern inline void down(struct semaphore * sem)
> {
>         __asm__ __volatile__(
>                 "# atomic down operation\n\t"
> #ifdef __SMP__
>                 "lock ; "
> #endif
>                 "decl (%0)\n\t"     /* --sem->count */
>                 "js 2f\n"
>                 "1:\n"
>                 ".section .text.lock,\"ax\"\n"
>                 "2:\tcall __down_failed\n\t"
>                 "jmp 1b\n"
>                 ".previous"
>                 :/* no outputs */
>                 :"c" (sem)
>                 :"memory");
> }
> that #ifdef there inside the inline causes the effect you're talking about.
> But again, that change ain't much.

Then let's look at spin locks.  The following is defined on UP kernels:

#define spin_lock_init(lock)    do { } while(0)                                             
#define spin_lock(lock)         (void)(lock) /* Not "unused variable". */                   
#define spin_is_locked(lock)    (0)                                                         
#define spin_trylock(lock)      ({1; })                                                     
#define spin_unlock_wait(lock)  do { } while(0)                                             
#define spin_unlock(lock)       do { } while(0)                                             

And this is on x86 SMP (I stripped the SPINLOCK_DEBUG code to make it
a bit more readable):

#define spin_lock_init(x)       do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)                  
#define spin_unlock_wait(x)     do { barrier(); } while(((volatile spinlock_t *)(x))->lock) 
#define spin_is_locked(x)       ((x)->lock != 0)                                            
#define spin_lock_string \                                                                  
        "\n1:\t" \                                                                          
        "lock ; btsl $0,%0\n\t" \                                                           
        "jc 2f\n" \                                                                         
        ".section .text.lock,\"ax\"\n" \                                                    
        "2:\t" \                                                                            
        "testb $1,%0\n\t" \                                                                 
        "rep;nop\n\t" \                                                                     
        "jne 2b\n\t" \                                                                      
        "jmp 1b\n" \                                                                        

#define spin_unlock_string \                                                                
        "lock ; btrl $0,%0"                                                                 

extern inline void spin_lock(spinlock_t *lock)                                              
        __asm__ __volatile__(                                                               
                :"=m" (__dummy_lock(lock)));                                                
extern inline void spin_unlock(spinlock_t *lock)                                            
        __asm__ __volatile__(                                                               
                :"=m" (__dummy_lock(lock)));                                                
#define spin_trylock(lock) ({ !test_and_set_bit(0,(lock)); })                               

Now that looks quite a bit different, doesn't it?

> exa@borg:/usr/src/linux$ grep -e down\(.*\) -r . | wc -l
>     626

Semaphores aren't that common.  Searching just the drivers
subdirectories (of 2.3.99-pre3) for most forms of spin locks gives a
slightly higher count:

[andreasb@storm drivers]$  grep -e 'spin_\(un\)*lock' -r . | wc -l

> In light of this, let me suggest the following. The 192KB estimate (which
> is perhaps excessive wrt how it was thought) is inaccurate, so my new estimate
> is 768KB. That will be compressed, so it makes ~384K. If that's achievable,
> then still my point holds.

If I understood you right you want to make binary diffs.  Now given
that the Linux kernel image is also compressed there will be a lot
more differences in the binary.  My whole kernel compressed image is
less than 768 kB, what would the point be in not just creating
separate kernel packages?

 Andreas E. Bombe <andreas.bombe@munich.netsurf.de>    DSA key 0x04880A44
http://home.pages.de/~andreas.bombe/    http://linux1394.sourceforge.net/

Reply to: