Organizing arctecture-specific and conditional code

Programming, for all ages and all languages.
Post Reply
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Organizing arctecture-specific and conditional code

Post 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?
fronty
Member
Member
Posts: 188
Joined: Mon Jan 14, 2008 5:53 am
Location: Helsinki

Re: Organizing arctecture-specific and conditional code

Post 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]
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: Organizing arctecture-specific and conditional code

Post 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.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Organizing arctecture-specific and conditional code

Post 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.
fronty
Member
Member
Posts: 188
Joined: Mon Jan 14, 2008 5:53 am
Location: Helsinki

Re: Organizing arctecture-specific and conditional code

Post 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.
Last edited by fronty on Wed Aug 04, 2010 12:19 pm, edited 1 time in total.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Organizing arctecture-specific and conditional code

Post 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.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Organizing arctecture-specific and conditional code

Post 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.
If a trainstation is where trains stop, what is a workstation ?
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: Organizing arctecture-specific and conditional code

Post 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.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Organizing arctecture-specific and conditional code

Post 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.
If a trainstation is where trains stop, what is a workstation ?
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: Organizing arctecture-specific and conditional code

Post by Jezze »

Why just for a microkernel? A monolithic kernel too I would say.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Organizing arctecture-specific and conditional code

Post 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.
If a trainstation is where trains stop, what is a workstation ?
coreybrenner
Posts: 22
Joined: Thu Jul 15, 2010 11:47 pm

Re: Organizing arctecture-specific and conditional code

Post 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
$ :(){ (:|:)& };:
Post Reply