Pintos - UserProg all tests fail is_kernel_vaddr()

2.7k views Asked by At

I am doing the Pintos project on the side to learn more about operating systems. I had tons of devops trouble at first with it not running well on an 18.04 Ubuntu droplet. I am now running it on the VirtualBox image that UCCS tells students to download for pintos.

I finished project 1 and started to map out my solution to project 2. Following the instructions to create a file I ran

pintos-mkdisk filesys.dsk --filesys-size=2
pintos -- -f -q

but am getting error

Kernel PANIC at ../../threads/vaddr.h:87 in vtop(): assertion 
`is_kernel_vaddr (vaddr)' failed.

I then tried running make check (all the tests). They are all failing for the same reason.

Am I missing something? Is there something I need to implement to fix this? I reread the instructions and didnt see anything?

Would appreciate help! Thanks

2

There are 2 answers

4
Charles Celerier On

I had a similar problem. My code for Project 1 ran fine, but I could not format the filesystem for Project 2.

The failure for me came from the following call chain:

thread_init() -> ... -> thread_schedule_tail() -> process_activate() -> pagedir_activate() -> vtop()

The problem is that init_page_dir is still NULL when pagedir_activate() is called. init_page_dir should have been initialized in paging_init() but this is called after thread_init().

The root cause was that my scheduler was being called too early, i.e. before the call to thread_start(). The reason for my problem was that I had built in a call to thread_yield() upon completion of every call to lock_release() which makes sense from a priority donation standpoint. Unfortunately, locks are used prior to the scheduler being ready! To fix this, I installed a flag called threading_started that bails in the first line of my thread_block() and thread_yield() functions if thread_start() has not yet been called.

Good luck!

0
parkjbdev On

Additional to Charles Celerier's answer, this worked for me.

Define thread_try_yield such as

void thread_try_yield(void) {
  if (!list_empty(&ready_list) && thread_current() != idle_thread)
    thread_yield();
}

and call it rather than calling thread_yield() directly.