ECE 468: Operating Systems — PintOS Kernel Development

The PintOS series of projects—originally developed at Stanford University as a pedagogical operating systems framework—served as the foundation for this course’s kernel development work. PintOS provides a lightweight but realistic environment for implementing core OS subsystems on the 80x86 architecture, including threads, user programs, and virtual memory. Across Projects A through D, I contributed to the design, implementation, and debugging of fundamental operating system mechanisms while developing a deeper understanding of system calls, process control, synchronization, and memory management at the kernel level.

Project A focused on implementing a simple Unix-style shell capable of parsing commands, launching programs, and supporting multi-stage piping. Beginning with a basic single-command shell, the system was extended to correctly parse multiple tokens, detect pipe symbols, and establish interprocess communication using fork(), execvp(), and dup2() to route standard input and output through pipe file descriptors. The final implementation supported up to nine chained pipes, enabling complex command sequences such as cat file | grep word | hexdump -x. Through this project, I gained practical experience with process creation, stream redirection, and low-level Linux system calls while ensuring stable operation without zombie processes.

Project B expanded PintOS’s user program functionality by implementing core system calls, argument passing, and safe memory access within the kernel. Over a dozen system calls—including process control, file I/O, and termination—were added to the syscall handler, requiring modifications across syscall.c, process.c, thread.h, and exception.c. The implementation introduced argument parsing through strtok_r, validated user pointers to prevent page faults, synchronized process wait behavior, and printed process exit statuses for debugging. With 71 of 76 tests passing, the system demonstrated stable functionality while highlighting areas for refinement in corner cases involving recursion, memory pressure, and file system synchronization.

Project C strengthened the PintOS threading system by introducing an alarm clock mechanism, dynamic priority scheduling, and full priority donation to resolve priority inversion. Key structural and logical changes were added to thread.c, timer.c, and synch.c, allowing threads to sleep and wake at precise tick intervals and enabling the scheduler to always run the highest-priority ready thread. Priority donation was implemented across lock acquisition, lock release, and nested waiting chains, ensuring that high-priority threads were never starved by lower-priority holders. An advanced scheduler was also added using fixed-point arithmetic to compute recent_cpu, load_avg, and dynamic priorities. All 27 tests passed, confirming a correct and robust implementation.

Project D completed the PintOS operating system by implementing a full virtual memory subsystem supporting paging, swapping, memory-mapped files, and supplemental page tables. New modules in the VM directory—frame.c, page.c, and swap.c—introduced frame allocation with eviction via the clock algorithm, demand paging from files or swap, stack growth, and secure handling of page faults. The kernel was further expanded to include mmap and munmap system calls for memory-mapped files, and integration with user program loading and exception handling ensured seamless interaction between virtual and physical memory. With all 109 tests passing, the final system demonstrated fully functional paging, reliable page fault handling, and efficient memory utilization across complex workloads.