CSC546 - Operating Systems Design


Topics

Course Outline

Paper

Nachos Project

Emacs

RCS


Course Outline

Primary: Nachos Project (70% of grade; 90% of work)

Secondary: Summary Paper (30% of grade)


Paper

Suggested reading list on the Documents page.

You may choose from these papers. Other papers are also acceptable upon approval.


Nachos Project

Developed originally at U.C., Berkeley.

Nachos = N(ot) A(nother) C(ompletely) H(euristic) O(perating) S(ystem)

This name is reminiscent of the name of a Unix utility: YACC, which stands for Yet Another Compiler Compiler, a "compiler" whose output is another compiler. (Or can be viewed that way.)

Written in C++ using the GNU g++ compiler, and set up to run on various Unix platforms.

Simulates the entire instruction set for the Mips processor used in Silicon Graphics machines.

Simulates the hardware of Mips machine


Hardware Simulation

Written in C++. You will not modify this code.

Simulates:


Nachos Operating System Code

Implements Nachos "kernel" processes (called threads).

This code is written in C++, is compiled on the actual hardware (Sun machine, running under Unix Solaris).

A Nachos kernel thread executes some Nachos C++ function in the Nachos code.

Nachos code can already do context-switches between these kernel threads.


Kernel Thread Context Switch

Does not use Solaris threads.

Kernel threads (like all the Nachos additional code you will write) runs on the actual hardware.

Kernel threads are not subject to the Mips interrupts, but can yield to another ready kernel thread.

A context switch between these kernel threads requires saving the register values on the actual machine for the first thread and restoring the machine register values for the second thread into the actual hardware registers.


Kernel Thread Data Structures

The context switch between Nachos kernel threads therefore requires a data structure (one for each kernel thread) for storing the actual hardware register values.

The Nachos code contains a C++ class, Thread to represent both Nachos kernel threads and Nachos user threads. (More about user threads below.)

Since saving and restoring the actual hardware registers cannot be done directly in C++, the Nachos code contains some assembler code for doing the part of the context switch that saves and restores registers.


Context Switch Routine

The context switch code needs pointers to two Thread objects, the old thread and the new Thread.

Note that the old thread is the one that is running when the switch routine is invoked and continues to run up until the point that the register values for the new Thread are restored into the actual hardware registers.


Nachos User Threads (Processes)

Nachos is the operating system code for the simulated Mips machine.

So the purpose of Nachos is to execute user programs on the Mips machine.

This means that user programs must be compiled and linked into Mips executable code.

In order to execute a file containing Mips executable code, it must first be loaded into the Mips memory.

The Mips machine, simulated in C++ code, simulates memory as an array whose size determines the amount of Mips "physical" main memory.


Running Mips User Programs

The initial Nachos code (before your additions) allows a single user program to be executed at a time.

However, there are severe limitations with this initial code.


User Programs Fail with Initial Nachos Code

Why? Because, like almost any user program, these user programs must make requests of the operating system (Nachos) for I/O and for terminating (Exit).

The inital Nachos code gives up when any system call is made except for the Halt system call.


User Program System Calls

The compiled/linked user programs do attempt to make system calls. The generated Mips code contains the Mips instruction: syscall ...

  • When the initial Nachos code that simulates the Mips machine encounters the syscall instruction, it "traps". That is, it invokes the Nachos routine:
    void ExceptionHandler(ExceptionType which);
    

    This action is part of the hardware simulation.

    You will need to modify this function to extend the functionality of Nachos.


    The ExceptionHandler Routine

    First, note that the ExceptionType passed to this function could indicate a "problem" exception such as OverflowException or IllegalInstrException.

    Or, ExceptionType can indicate a "normal" event that needs Nachos operatings system attention or assistance such as PageFaultException or SysCallException.


    The SysCallException "Exception"

    If the parameter passed to ExceptionHandler has the value SysCallException, this simply indicates that the user program has made some system call, but which one?

    The user Mips code that invokes syscall, first loads Mips register 2 with the integer that identifies the particular system call being invoked. Then it executes the syscall instruction. E.g., in Mips assembler:

    Halt:
            addiu $2,$0,SC_Halt
            syscall
    

    Do you need to know Mips Assembler?

    No.


    Determining the System Call

    So the ExceptionHandler routine must read Mips register 2. The simulated machine contains routines for accessing such information. E.g, the Nachos code has a gobal variable, machine, which is a pointer to the single instance of the C++ Machine class. To read register 2, the code is:

      int type = machine->ReadRegister(2);
    

    ExceptionHandler in the Initial Nachos Code

    Here is the initial code for ExceptionHandler:

    void ExceptionHandler(ExceptionType which)
    {
      int type = machine->ReadRegister(2);
    
      if ((which == SyscallException) && (type == SC_Halt)) {
          DEBUG('k', "\nShutdown, initiated by user program.\n");
          interrupt->Halt();
      } else {
          printf("Unexpected user mode exception %d %d\n", which, type);
          ASSERT(FALSE);
      }
    
    }
    

    As you can see, every user system call except for Halt falls into the else clause and executes the ASSERT(FALSE) statement which terminates Nachos.


    Other Nachos System Calls

    The other system calls (not implemented in the initial Nachos code, except for SC_Halt) are specified in the header file, syscall.h:

    #define SC_Halt         0
    #define SC_Exit         1
    #define SC_Exec         2
    #define SC_Join         3
    #define SC_Create       4
    #define SC_Open         5
    #define SC_Read         6
    #define SC_Write        7
    #define SC_Close        8
    #define SC_Fork         9
    #define SC_Yield        10
    

    Memory and the Initial Nachos Code

    The initial Nachos Code has data structures for Page Tables.

    As noted above, the initial Nachos Code also allows you to execute user programs, at least up to the point that the user code makes a Nachos system call.

    Page tables provide a mapping from each virtual page to a physical page for user programs.

    If partial loading of programs is in effect, the page table also indicates whether a given virtual page in a user program is present in the physical memory.


    Page Tables and the Initial Nachos Code

    The initial Nachos code shows you how to read a Mips executable file and load the different parts into the correct places in the Mips memory.

    The "parts" are the segments. Each Mips executable can have:

    The Mips executable file contains a header record (the first 40 bytes or so) which describes the segments.

    Each segment description says at what virtual address that segment expects to be loaded.

    This segment information is used by the initial Nachos code to load the executable program from a file into the Mips memory.


    Initial Nachos and Virtual Memory

    The initial Nachos code cheats, however, as loads each virtual page at the same Mips physical page. That is, in the initial Nachos code, virtual addresses are always the same as Mips physical addresses.

    Don't worry about this for now. Several system calls can be implemented without worrying about virtual memory.


    Goals for the Project

    After a brief introduction to some of the features of the initial Nachos code, what are you supposed to add? What functionality is to be added?

    A unifying goal is to add enough functionality to Nachos so that it is possible to write a shell as a Mips user program. This shell would then be able to read commands (names of Mips user programs) from a command line, create a Nachos process to execute the command, wait for the user program to terminate, print a prompt and wait for the next command. As an extension, we could also arrange to execute programs in the background (by not waiting for the program to finish).

    What functionality needs to be added?


    Writing User Programs

    Since the goal is to write a shell as a Mips user program, how do we create and compile Mips user programs?

    Answer: A cross compiler is provided built from GNU's gcc compiler. This cross compiler runs on the Sun machine, but produces machine code for the Mips processor.

    So basically you can write C programs. These programs include the appropriate header for Nachos system calls.

    Compile the C programs with the cross compiler.


    Next Time

    Emacs

    Etags

    RCS