There are several
SAME_STACK asserts in
ensure that current thread did not run out of kernel stack.
A typical assert may looks like:
The purpose of
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
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.
$OS161_SRC/kern/arch/mips/locore/trap.c, there are a few
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
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
to 16 KB. But I still fail this assert after that. Then I take a look at the
definition of the
#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) =
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));