CS 350 - Operating Systems

Hints for A1 - OS161 Kernel

This file may be updated, so check back periodically


Quick Topic Links

General

  • In the linux.student.cs environment, don't forget to re-configure your kernel for Assignment 1. We will use the OS/161 kernel that is configured as ASST2 to implement and test system calls. Therefore, all of your kernel builds will be in kern/compile/ASST2
    % cd $HOME/cs350-os161/os161-1.99/kern/conf
    % ./config ASST2
    % cd ../compile/ASST2
    % bmake depend
    % bmake
    % bmake install
    

  • Don't forget that if you add any new source files to the kernel code, you need to update the file kern/conf/conf.kern and you need to reconfigure your kernel. If you don't do this, the code in your new source file will not be included in the kernel build.

  • Don't worry about trying to reclaim physical frames in the kernel when they are no longer used. However, you should make sure that you kfree kernel memory that you've allocated using kmalloc but that the kernel no longer needs.

  • You may like to have lots of debugging information printing out from your kernel, but the kernel you submit to us must not do so. OS/161's DEBUG facility that can help with this problem - you can bury lots of debugging statements into your code, and you can turn them all off by just changing the value of a single variable. You can even turn them off conditionally by labeling them properly.

    You encountered the DEBUG mechanism in A0, but as a reminder:


  • Testing: Controlling the Number of Processors

    You can control the number of processors in the simulated machine by changing the SYS/161 configuration file, sys161.conf. Look for a line like this:

    31	mainboard  ramsize=524288  cpus=1
    
    The cpus=1 indicates that that simulated machine has a single CPU (processor). To simulate more CPUs, just use change the CPU count. For example, changing the line above to
    31	mainboard  ramsize=524288  cpus=4
    
    will give you a system with 4 CPUs.

    So that you're not constantly editing the configuration file, you can create multiple different configuration files and pass the one you want to the simulator when it starts, using the -c option, e.g,

    sys161 -c my-config-file.conf kernel
    

    _exit


    fork


    Kernel include files


    System Call Testing


    Setting up GDB

    Note that the YouTube channel for CS 350 contains a video tutorial on how to use gdb. In addition there is some information included below.

    If you type < ctrl-g > in the sys161 window, the OS pauses and waits for a debugger to attach. This is useful if you don't have a debugger already attached and you want to see what's happening.

    If you create a file called .gdbinit and put it in $HOME/cs350-os161/root directory (assuming that is where you are running cs350-gdb from) gdb will load commands from that file when it starts up. Here's an example of a simple, useful .gdbinit file:

      dir ../os161-1.11/kern/compile/ASST0
      target remote unix:.sockets/gdb
      break panic
      
    This way, you don't have to type the target command to connect to sys161 every time you run the debugger, and you don't have to type the dir command to tell gdb where to find your build files. This .gdbinit also sets a breakpoeint at the kernel's panic function, so that gdb will grab control in case the kernel panics. Note that you will want to change dir ../os161-1.11/kern/compile/ASST0 for subsequent assignments, e.g, for assignment one, your .gdbinit file should contain dir ../os161-1.11/kern/compile/ASST1 instead.

    Example using GDB

    This is an example gdb session to show what output to expect and how to up up the stack trace to look at a simple variable. This session was produced by Tim Brecht using a previous (older) version of OS/161 (so your code may not look the same). His comments are on the lines that start with "//". Each comment refers to the output that follows it.

      // Start cs350-gdb.
      % cs350-gdb kernel
      GNU gdb 6.0
      Copyright 2003 Free Software Foundation, Inc.
      GDB is free software, covered by the GNU General Public License, and you are
      welcome to change it and/or distribute copies of it under certain conditions.
      Type "show copying" to see the conditions.
      There is absolutely no warranty for GDB.  Type "show warranty" for details.
      This GDB was configured as "--host=i686-pc-linux-gnu --target=mips-elf"...
      __start () at ../../arch/mips/mips/start.S:24
      24         addiu sp, sp, -20
      Current language:  auto; currently asm
      Breakpoint 1 at 0x80010948: file ../../lib/kprintf.c, line 111.
    
      // Continue execution. This stops and waits for input into os161.
      // In the window running sys161 -w kernel after I type something like
      // p testbin/program it runs and eventually panics.
      (gdb) continue
      Continuing.
    
      Breakpoint 1, panic (fmt=0x8002fe6c "Assertion failed: %s, at %s:%d (%s)\n") at ../../lib/kprintf.c:111
      111             if (evil==0) {
      Current language:  auto; currently c
    
      // I want to find out who called panic and why.
      // Where shows the stack trace of who called what and all
      // the parameters.
      // panic is where we are currently.
      // It was called from lock_destroy at line 181 of thread/synch.c
      // It was called from proc_entry_init at line 601 of userprog/syscalls.c
      // etc.
      // proc_entry_init was the function that called lock_destroy.
      (gdb) where
      #0  panic (fmt=0x8002fe6c "Assertion failed: %s, at %s:%d (%s)\n") at ../../lib/kprintf.c:111
      #1  0xffffffff8001740c in lock_destroy (lock=0x800c3e20) at ../../thread/synch.c:181
      #2  0xffffffff80022b30 in proc_entry_init (pid=2) at ../../userprog/syscalls.c:601
      #3  0xffffffff800258dc in sys_waitpid (pid=2, status=0x7fffff90, options=0, retval=0x800fcf18)
          at ../../userprog/syscalls.c:1367
      #4  0xffffffff8000c6b8 in mips_syscall (tf=0x800fcf6c) at ../../arch/mips/mips/syscall.c:145
      #5  0xffffffff8000cb68 in mips_trap (tf=0x800fcf6c) at ../../arch/mips/mips/trap.c:134
    
      // Move up the stack.
      (gdb) up
      #1  0xffffffff8001740c in lock_destroy (lock=0x800c3e20) at ../../thread/synch.c:181
      181             assert(lock->held == 0);
    
      // Move up the stack.
      (gdb) up
      #2  0xffffffff80022b30 in proc_entry_init (pid=2) at ../../userprog/syscalls.c:601
      601                     lock_destroy(p->ft_lock);
    
      // Move up the stack.
      (gdb) up
      #3  0xffffffff800258dc in sys_waitpid (pid=2, status=0x7fffff90, options=0, retval=0x800fcf18)
          at ../../userprog/syscalls.c:1367
      1367              proc_entry_init(pid);
    
      // Print out some info about the current thread.
      (gdb) print *curthread
      $1 = {t_pcb = {pcb_switchstack = 2148519408, pcb_kstack = 2148519936, pcb_ininterrupt = 0, pcb_badfaultfunc = 0,
          pcb_copyjmp = {2148517880, 2147537544, 0, 0, 0, 0, 0, 0, 0, 0, 2148517880}},
        t_name = 0x800d2d00 "ourtests/conc-io", t_sleepaddr = 0x0, t_stack = 0x800fc000 "o?=\021o?=3", t_vmspace = 0x800f7360,
        t_cwd = 0x800d2f40, pid = 1}
    
      // Print out the value of pid as it is inside of userprog/syscalls.c in the
      // function sys_waitpid at the time of the call to proc_entry_init.
      (gdb) print pid
      $2 = 2
    
      // Print out the value of pid in hex.
      (gdb) print/x pid
      $2 = 0x2
    
      // x/i Examine (x) specified memory location as an instruction (i).
      // Print out the instruction located at address 0xffffffff8000c6b8.
      // Note that I got this address from the above stack trace.
      // It shows you that this is address is 520 bytes inside of mips_syscall.
      // This can be really helpful if OS/161 dies and sys161 just prints
      // out the epc (which contains the address of the instruction
      // that generated the execption.
      (gdb) x/i 0xffffffff8000c6b8
      0x8000c6b8 :  j       0x8000c6f0 
    
      // x/i Examine (x) specified memory location as an instruction (i).
      // Print out the instruction located at address 0xffffffff8001740c.
      // Note that I got this address from the above stack trace.
      // It shows you that this address is 148 bytes inside of lock_destroy.
      (gdb) x/i 0xffffffff8001740c
      0x8001740c :  lw      v0,32(s8)
    
    
      The list command is useful for finding the line of source that contains the faulting instruction (note the *):
    
      Something else that can be done (from a different version of the code)
      (gdb) list *0x800197c4
      0x800197c4 is in kmain (../../main/main.c:164).
      159     kmain(char *arguments)
      160     {
      161         char *bad_ptr = NULL;
      162         boot();
      163
      164         *bad_ptr = 0;
      165
      166         menu(arguments);
      167
      168         /* Should not get here *