There are several SAME_STACK asserts in $OS161_SRC/kern/arch/mips/locore/trap.c to ensure that current thread did not run out of kernel stack.

A typical assert may looks like:

KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf)) 

The purpose of SAME_STACK assertion

In OS161, each thread has its own kernel stack. When interrupts or exceptions occur, the CPU will first switch to current thread's kernel stack, both to avoid polluting user's normal stack, and protect the stack from malicious user program.

The stack is allocated in thread_fork and in cpu_create (but not both). The initial stack size is defined in $OS161_SRC/kern/include/thread.h as STACK_SIZE.

Since stack grows downwards, to check if we run out of the stack, we put a few magic values at the bottom of the stack (thread_checkstack_init), so that we can check if the values are the same with what we filled it (thread_checkstack) to see if we run out of kernel stack.

In $OS161_SRC/kern/arch/mips/locore/trap.c, there are a few SAME_STACK assertions to make sure the trap frame at the right place.

Why would we run out of kernel stack?

Remember that any variables you define in your syscall functions are allocated in current thread's kernel stack. So if you allocated large variables, such as a big array buffer, you'll probably have a stack "downflow".

So, either try to shrink your declared buffer size, or use kmalloc instead.

Or, you can enlarge the stack size to temporally solve your pain, but this is not recommended since each thread will have a stack, if it's too large, then you'll soon run out of physical memory if you have lots of threads.

Problem of the macro

During the lab, I sometimes fail this assert. At first, I thought I've run out of kernel stack so I enlarge the STACK_SIZE to 16 KB. But I still fail this assert after that. Then I take a look at the definition of the SAME_STACK macro:

#define SAME_STACK(p1, p2) (((p1) & STACK_MASK) == ((p2) & STACK_MASK)) 

I found this macro problematic. Suppose STACK_SIZE = 0X00004000, then STACK_MASK = ~(STACK_SIZE-1) = 0XFFFFC000. Assume p1 (stack top) = 0X80070FFF, p2 (stack pointer) = 0x8006FFFF, then we've only used 0x00001000 bytes stack but SAME_STACK macro will fail, since p1 & STACK_MASK = 0X80070000, p2 & STACK_MASK = 0X8006C000.

The point here is the stack top address may not be STACK_SIZE aligned. So we can not do the same stack check by simply checking their base addresss.

So we need to modify this part to get our kernel work. This is not your fault but probably a bug shipped with the kernel.

You can use any tricky macros here but a simple pair of comparison will be suffice.

KASSERT(((vaddr_t)tf) >= ((vaddr_t)curthread->t_stack)); 
KASSERT(((vaddr_t)tf) < ((vaddr_t)curthread->t_stack+STACK_SIZE));