- How much code will I need to write?
- The kernel always panics when I run a custom test case.
- The kernel always panics with
- All my user programs die with page faults.
- All my user programs die upon making a syscall.
- How can I disassemble user programs?
- Why do many C include files not work in Pintos programs? Can I use libfoo in my Pintos programs?
- How do I compile new user programs?
- Can I run user programs under a debugger?
- What’s the difference between tid_t and pid_t?
Here’s a summary of our reference solution. The reference solution represents just one possible solution. Many other solutions are also possible and many of those differ greatly from the reference solution. Some excellent solutions may not modify all the files modified by the reference solution, and some may modify files not modified by the reference solution.
lib/float.h | 6 threads/init.c | 7 threads/interrupt.h | 1 threads/intr-stubs.S | 6 threads/start.S | 5 threads/switch.S | 4 threads/switch.h | 5 threads/thread.c | 4 threads/thread.h | 1 userprog/exception.c | 7 userprog/process.c | 268 +++++++++++++++++++++++++++++----- userprog/process.h | 37 ++++ userprog/syscall.c | 392 +++++++++++++++++++++++++++++++++++++++++++++++++-- userprog/syscall.h | 20 ++ 14 files changed, 697 insertions(+), 66 deletions(-)
Is your file name too long? The file system limits file names to 14 characters. Is the file system full? Does the file system already contain 16 files? The base Pintos file system has a 16-file limit.
This happens when you overflow your kernel stack. If you’re allocating large structures or buffers on the stack, try moving them to static memory or the heap instead. It’s also possible that you’ve made your
struct thread too large. See the comment underneath the kernel stack diagram in
threads/thread.h about the importance of keeping your
struct thread small.
This will happen if you haven’t implemented argument passing (or haven’t done so correctly). The basic C library for user programs tries to read argc and argv off the stack. If the stack isn’t properly set up, this causes a page fault.
You’ll have to implement syscall before you see anything else. Every reasonable program tries to make at least one syscall (
exit) and most programs make more than that. Notably,
printf invokes the
write syscall. The default syscall handler just handles
exit(). Until you have implemented syscalls sufficiently, you can use
hex_dump to check your argument passing implementation (see Startup).
objdump (80x86) or
i386-elf-objdump (SPARC) utility can disassemble entire user programs or object files. Invoke it as
objdump -d <file>. You can use GDB’s codedisassemble command to disassemble individual functions.
The C library we provide is very limited. It does not include many of the features that are expected of a real operating system’s C library. The C library must be built specifically for the operating system (and architecture), since it must make syscalls for I/O and memory allocation. Not all functions do, of course, but usually the library is compiled as a unit.
If the library makes syscalls (e.g, parts of the C standard library), then they almost certainly will not work with Pintos. Pintos does not support as rich a syscall interfaces as real operating systems (e.g., Linux, FreeBSD), and furthermore, uses a different interrupt number (0x30) for syscalls than is used in Linux (0x80).
The chances are good that the library you want uses parts of the C library that Pintos doesn’t implement. It will probably take at least some porting effort to make it work under Pintos. Notably, the Pintos user program C library does not have a
examples/Makefile, then run make.
Yes, with some limitations. See Adding new test to Pintos.
tid_t identifies a kernel thread, which may have a user process running in it (if created with
process_execute) or not (if created with
thread_create). It is a data type used only in the kernel. A
pid_t identifies a user process. It is used by user processes and the kernel in the
wait syscalls. You can choose whatever suitable types you like for
pid_t. By default, they’re both int. You can make them a one-to-one mapping, so that the same values in both identify the same process, or you can use a more complex mapping. It’s up to you.