Page 1 of 1

Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 10:19 am
by NickJohnson
I got bored of working on my C library for the last few months, so I've decided to try rewriting my kernel at the same time. I plan to make it well-organized, preemptive, portable, etc. (I had nearly no experience when writing it the first time), but I can't figure out the best way to organize conditional (i.e. architecture specific and test) code. For example, my thread structure will be completely different on different architectures, but it will have the same names for its utility functions. I've seen this done with lots of preprocessor macros, but that seems kind of ugly: it would be better if I could conditionally compile/link certain files (e.g. there would be a thread.c for x86 and thread.c for another arch etc.) but keep the same headers as a specification of their interface.

How is this normally done?

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 11:36 am
by fronty
I'd have something like this:

Code: Select all

/* sys/thread.h */

#include <sys/arch/thread.h>

struct thread *new_thread(int magic);

Code: Select all

/* sys/thread_arch.h */
/* Really arch/x86/sys/arch/thread_arch.h, arch/sparc/sys/arch/thread_arch.h, arch/mips... or what ever. */

struct thread {
        float pi;
        float next_pi;
};

Code: Select all

# Makefile
TARGET_ARCH= x86 # or what ever

SRCS= main.c
OBJS= ${SRCS:.c=.o}

CFLAGS+= -Iarch/${TARGET_ARCH}/

all: ${OBJS}
        ${CC} ${CFLAGS} ${OBJS}
[/size]

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 11:38 am
by Jezze
I don't know if it is the best way but what I did was to not include any headers from my arch include folder but instead simply wrote extern declarations of the methods I wanted to be able to contact in the kernel header files that need to use them. As long as those methods exist when the linking occurs it will work. What files is actually linked together you decide with your Makefile.

Is this a possible answer? I perhaps didn't understand the question.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 11:50 am
by NickJohnson
@fonty: That would work for switching structure declarations per architecture, but I'm also trying to do that with whole functions. Something like this:

Code: Select all

/* sys/thread_arch.c */
/* really arch/x86/sys/thread_arch.c */

struct thread *new_thread(int magic) {
    foo();
    /* ... */
}

Code: Select all

/* sys/thread_arch.c */
/* really arch/arm/sys/thread_arch.c */

struct thread *new_thread(int magic) {
    bar();
    /* ... */
}
But my real question is whether this is the best way of switching between architectures (i.e. conditional compilation of whole files, which I've never seen), or if the best way is something like preprocessor "#if"s (which I have seen in places). My main concern is for the assembly that's bound to be in each architecture directory, which can't be easily combined with the C preprocessor, and will have to be only be assembled on the proper architecture anyway.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 12:14 pm
by fronty
my $a = "architecture independent"

I'd have this kind of structure:
src/ - $a files
src/sys/ - $a header files
src/sys/thread.h - $a defines for threading, includes sys/arch/thread.h
src/arch/ - directory for each architecture
src/arch/x/sys/arch - headers for arch x
src/arch/x/sys/thread.h - threading defines for x
src/arch/x/src - source files for arch x
src/arch/x/src/thread.c - internal wizardry of threading on x


In Makefile I'd add needed paths to include path and add needed files to be compiled with type of wizardry depending on how many and which different flavours of make I want to support.

In my eyes choices are this quite branchy directory structure with with possibly a bit "unclean" Makefiles, or sodomizing preprocessor.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 12:16 pm
by bewing
I prefer all my files to have architecture(or whatever)-specific names or directories. The makefile is built to compile only one special set of non-architecture-specific filenames. A configure script gets an argument of which target you want to compile for, and copies architecture-named files to generic-named files, just before the makefile runs. This pretty much eliminates all ifdefs -- because too many of those make my head ache.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 1:44 pm
by gerryg400
I notice that Linux has a single 'arch' directory at the top level with most of the arch specific stuff below it. I think a microkernel needs a different arrangement. The src tree for a microkernel builds a number of separate programs to make the system. Kernel, mm, vfs, drivers, etc are usually separate programs in different top level directories. It would break modularity to then have a single top level arch. My feeling is that each part of the system needs its own arch dirs. I suggest simply having x86, mips etc directories below kernel, mm, vfs etc. You will also probably need an empty top level include directory where arch-correct public headers are installed as the system is built.

I don't think this actually answers your original question, just my thoughts.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 2:01 pm
by JohnnyTheDon
gerryg400 wrote:I notice that Linux has a single 'arch' directory at the top level with most of the arch specific stuff below it. I think a microkernel needs a different arrangement. The src tree for a microkernel builds a number of separate programs to make the system. Kernel, mm, vfs, drivers, etc are usually separate programs in different top level directories. It would break modularity to then have a single top level arch. My feeling is that each part of the system needs its own arch dirs. I suggest simply having x86, mips etc directories below kernel, mm, vfs etc. You will also probably need an empty top level include directory where arch-correct public headers are installed as the system is built.

I don't think this actually answers your original question, just my thoughts.
Most microkernel components (servers, drivers) should not have to deal with anything architecture specific (at least not anything a few preprocessor directives can't handle). This could even be extended to the memory manager if it provides only scheduling and the kernel deals with the actual page tables.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 3:36 pm
by gerryg400
Most microkernel components (servers, drivers) should not have to deal with anything architecture specific (at least not anything a few preprocessor directives can't handle). This could even be extended to the memory manager if it provides only scheduling and the kernel deals with the actual page tables.
True. That's why i'm suggesting that there needn't be a top level arch directory. However there are at least 3 reasons to have arch specific code that I can think of. And they apply to any piece of code.

1. When the arch is different and requires at least a little difference in the implementation, for example some parts of mm.
2. For primitives that just need to be implemented differently because the underlying cpu is different, like spinlocks etc.
3. When you're chasing efficiency and supply for e.g. an arch specific memcpy.

Linux just bundles these all together. I think that's not suitable for a microkernel.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 3:54 pm
by Jezze
Why just for a microkernel? A monolithic kernel too I would say.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 4:12 pm
by gerryg400
Why just for a microkernel? A monolithic kernel too I would say
I was trying not to say that I think the Linux src tree is poorly organised.

Re: Organizing arctecture-specific and conditional code

Posted: Wed Aug 04, 2010 7:10 pm
by coreybrenner
Split out the architectures in an arch-specific subdir, like so:

Code: Select all

arch/blah/include
arch/blah/include/sys
arch/blah/src/mm
arch/blah/src/snazzle
...
Then, use make to work the -Is and the -Ls. If you like, do something like this:

Code: Select all

src/mm
src/snazzle
include
include/sys
...
arch/blah/include
arch/blah/include/sys
arch/blah
arch/blah/src/mm
arch/blah/src/snazzle
...
Then, use:

Code: Select all

vpath %.c $(patsubst $(TOPDIR)/%,$(TOPDIR)/arch/$(ARCH)/%,$(CURDIR))
Now, your makefile can look like:

Code: Select all

LIB_OBJS := foo.o bar.o baz.o
LIBS := libdingbat.a
BIN_OBJS := hoobajoob.o
BINS := zazzer

INCLUDE := -I$(TOPDIR)/arch/$(ARCH)/include -I$(TOPDIR)/include

${BINS} : ${BIN_OBJS} $(patsubst lib%.a,-l%,${LIBS})
        ${ARCH-}cc -o $@ $<

${LIBS} : ${LIB_OBJS}
        ${ARCH-}ar cru $@ $<

%.o : %.c
        ${ARCH-}cc ${INCLUDE} -c -o $@ $?
Architecture-specific stuff can be slurped in via VPATH, other paths by Make. If you
need to include arch-neutral include files of the same name from the arch-neutral dir,
from within your arch-specific header files, you might try the (non-portable):

Code: Select all

#include_next <frobnitz.h>
--Corey