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
>
> ENTER_SUCKY
> printf("I suck completely\n");
> EXIT_SUCKY
> >>
> 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
called.
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
defined.
> 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" \
".previous"
#define spin_unlock_string \
"lock ; btrl $0,%0"
extern inline void spin_lock(spinlock_t *lock)
{
__asm__ __volatile__(
spin_lock_string
:"=m" (__dummy_lock(lock)));
}
extern inline void spin_unlock(spinlock_t *lock)
{
__asm__ __volatile__(
spin_unlock_string
:"=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
3348
> 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: