OS/161 - KASSERT()

Learning Outcome

Use KASSERT to check invariants and debug.

Introduction

KASSERT is a macro which tests for conditions which should never occurr in a correct implementation of OS/161.

Applicable subjects

COMP3231


KASSERT

KASSERT(<expression>);

If expression is false, panic is called. Panic terminates the program, however, we can still debug at this point if the program is executed with gdb and a breakpoint is placed on panic. The OS/161 on Linux and OS/161 on WSL modules contain instructions for how to set up appropriate .gdbinit files which place this breakpoint for us.

KASSERT() is very similar to assert() with regards to its purpose and functionality. For more details on when these macros should be used, please see the assert() module.


Example

We can use KASSERT() to check invariants within OS/161 - say if we want to dereference a pointer but we want to ensure that pointer is not NULL before we do that. However, somewhere in our code, if we accidentally set it to be NULL, a KASSERT() can be used to stop the program. An example of this is given below:

Terminal 1:

$ sys161 -p 16161 kernel
sys161: System/161 release 2.0.8, compiled Feb 19 2017 14:31:53
OS/161 base system version 2.0.3
(with locks&CVs solution)
Copyright (c) 2000, 2001-2005, 2008-2011, 2013, 2014
President and Fellows of Harvard College.  All rights reserved.
Put-your-group-name-here's system version 0 (ASST0 #4)
16224k physical memory available
Device probe...
lamebus0 (system main bus)
emu0 at lamebus0
ltrace0 at lamebus0
ltimer0 at lamebus0
beep0 at ltimer0
rtclock0 at ltimer0
lrandom0 at lamebus0
random0 at lrandom0
lser0 at lamebus0
con0 at lser0
cpu0: MIPS/161 (System/161 2.x) features 0x0
panic: Assertion failed: foo != NULL, at ../../main/main.c:140 (boot)
sys161: trace: software-requested debugger stop
sys161: Waiting for debugger connection...
sys161: New debugger connection

Terminal 2:

$ os161-gdb kernel
(gdb) connect
membar_any_any () at includelinks/machine/membar.h:47
47              __asm volatile(
Breakpoint 1 at 0x8000ac8c: file ../../lib/kprintf.c, line 135.
(gdb) where
#0  membar_any_any () at includelinks/machine/membar.h:47
#1  membar_store_store () at includelinks/machine/membar.h:58
#2  lamebus_write_register (bus=<optimised out>, slot=<optimised out>, offset=offset@entry=16, val=val@entry=0)
    at ../../arch/sys161/dev/lamebus_machdep.c:184
#3  0x8000539c in ltrace_stop (code=code@entry=0) at ../../dev/lamebus/ltrace.c:87
#4  0x8000ad58 in panic (fmt=fmt@entry=0x8001f7b4 "Assertion failed: %s, at %s:%d (%s)\n") at ../../lib/kprintf.c:184
#5  0x8000add8 in badassert (expr=expr@entry=0x8001ffd4 "foo != NULL", file=file@entry=0x8001ff9c "../../main/main.c",
    line=line@entry=140, func=func@entry=0x8001db20 <__func__.2001> "boot") at ../../lib/kprintf.c:214
#6  0x8000b520 in boot () at ../../main/main.c:140
#7  0x8000b5d8 in kmain (arguments=<optimised out>) at ../../main/main.c:219
#8  0x8001d19c in __start () at ../../arch/sys161/main/start.S:216
(gdb) frame 6
#6  0x8000b520 in boot () at ../../main/main.c:140
140                     KASSERT(foo != NULL);
(gdb) print foo
$1 = 0x0
(gdb) list
135             kheap_nextgeneration();
136
137             {
138
139                     char *foo = NULL;       /* create a NULL pointer */
140                     KASSERT(foo != NULL);
141                     * foo = 'x';            /* attempt to access it */
142             }
143
144             /*
(gdb)

Module author: Liz Willer <e.willer@unsw.edu.au>

Date

2020-01-30