SOS framework

This document describes the provided SOS framework. This is provided to make it easier for you to get started with the project. The source code itself should be reasonably well commented, and you should ensure that you understand the provided source code.

Although you are free to change the build system and layout of the project it is discouraged for the following reasons:

Makefile and build system

We have provided a fairly comprehensive build system for you, however you will need to edit the Makefile throughout your project as you add new libraries and applications. The Makefile itself is extensively commented, this documentation is meant to supplement those comments.

The Makefile basically does the following:


The list of libraries to build is held in the LIBS variable. This is the variable you should change if you add a library. To determine exactly which files are built into a library the Makefile includes a library specific makefile called You will notice that each of the provided libraries contains one of these files.

The defines some variables and a make target. For example the device library has the following

LIBDEVICE_OBJS = lib/device/dev.o 
lib/libdevice.a: lib/libdevice.a($(LIBDEVICE_OBJS))

For any libraries you create you should replace DEVICE with the name of your library.


Executables are setup in a similar way to libraries. Instead of the LIBS variable you have an APPS variable. On top of this the must also tell the build system which libraries to link against:

TTY_TEST_OBJ = tty_test/tty_test.o tty_test/ttyout.o
TTY_TEST_LIBS = -ll4 -ll4e -lc

You should note that the sos app is special, as this is your privileged server. It is linked with different crt code, and is inserted into your dit image differently. You should always ensure that sos is listed first in the APPS list.


Most of the code you will write will be in the sos directory. Currently there is a very minimal operating system implemented, which should help get you started.

The implementation has been kept very simple, (you wouldn't want us to do all the fun bits would you!). The interesting thing here is the startup procedure, which should be fairly easy to follow in main.c. On startup the following happens:

  1. Initialise the L4 environment library.
  2. Initialise malloc heap.
  3. Initialise frame table.
  4. Spawn a thread (init_thread) to finish initialisation.
  5. Start the syscall/interrupt/pager IPC loop.


You may be wondering why we spawn a separate thread to handle most of the initialisation. The main reason for this is so that we can keep things simple (no really!). In the init_thread you may wish to execute some code that waits for interrupts, or possibly waits to IPC to a user-level program. Now both interrupts and user-level code rely on the IPC loop being able to respond to IPC.

There are of course other ways you could structure your start-up protocol and operating system so that this is not required. For example, you may want to have a separate thread for each interrupt handler. Or you may wish to restrict init_thread so that is doesn't rely on user-level code or interrupts. You are free to explore these ides in the design of you system.


The provided hardware.c handles setting up device drivers and initialising hardware for you. It exports the single hardware_init function, which you should ensure is called on startup. It is unlikely that you will need to edit this file, and you should expect patches to it as other device drivers are released throughout the course.


So that you don't have to write everything from scratch we provide you with some libraries to get you going.

A simple L4 environment library to make some of the calls to L4 simpler.
A cut down libc, which includes string handling, malloc and assert.
A device driver library.
A simple serial driver for the u4600.
A library to allow access to the u4600 PCI bus.
A network driver for the u4600.
A light-weight IP stack.
A simple NFS client.
A library for parsing ELF files.


Each executable is linked with a piece of crt (C runtime) code which does some basic initialisation and calls a program's main entry point.

Two crts are provided, a crtK.S, and a crt0.S. crtK is used when linking against SOS. Your user programs will be linked against crt0.S.

If you need to execute any code that runs before or after the main() function runs, you should add it to your crt0.S file. (For example, you may have some IPC handshake on startup, and another IPC message to tell the server to do a process_delete on exit.)

Last modified: Fri Aug 8 10:54:40 EST 2003