As a part of the operating systems lab, we were asked to implement various aspects of an Operating System on xv6. The end result was that we were able to create a mini-OS with basic functionalities.
We implemented the various functionalities spread across different assignments.
This assignment was mostly to familiarise ourselves with xv6. We defined a basic system call for our mini OS. The output-
We first implemented kernel threads and then built spinlocks and mutexes to synchronize access among them. To make it more real and fun, we implemented interface of the POSIX threads that are de facto standard on most UNIX systems.
For implementing threads, we created three system calls-
- thread_create()
- thread_join()
- thread_exit()
Which is not giving the correct answer which is (3200+2800) 6000 and also throwing different answers as expected because we haven’t implemented any sort of synchronisation so far.
For implementing spinlocks, we created two system calls-
- thread_spin_lock()
- thread_spin_unlock()
We got the correct answer as 6000, but it is slower. So, we implement mutexes which are comparitively faster.
For implementing mutexes, we created three system calls-
- thread_mutex_init()
- thread_mutex_lock()
- thread_mutex_unlock()
We got the correct answer as 6000, and the time taken was low as well.
It had 2 parts
This part was involved creating system calls to get information about currently active processes, much like the ps and top commands in Linux. THe following system calls were implemented-
- GetNumProc() and GetMaxPid()
- GetProcInfo()
- set_burst_time() and get_burst_time()
The current scheduler in xv6 is an unweighted round-robin scheduler. In this part, we modify the scheduler to consider user-defined process burst time and implement a shortest job first scheduler.
It had 2 parts.
In this part of the lab, we have implemented the Lazy Memory Allocation for xv6, which is a feature in most modern operating systems. In the case of the original xv6, it makes use of the sbrk() system call, to allocate physical memory and map it to the virtual address space. In the first section, we modified the sbrk() system call to remove the memory allocation and cause a page fault. In the second section, we have modified the trap.c file to resolve this page fault via lazy allocation.
The create_kernel_process() function was created in proc.c. The kernel process will remain in kernel mode the whole time. Thus, we do not need to initialise its trapframe (trapframes store userspace register values), user space and the user section of its page table. The eip register of the process’ context stores the address of the next instruction. We want the process to start executing at the entry point (which is a function pointer).
Also, we created a process queue that keeps track of the processes that were refused additional memory since there were no free pages available. We created a circular queue struct called rq. And the specific queue that holds processes with swap out requests is rqueue. We have also created the functions corresponding to rq, namely rpush() and rpop(). The queue needs to be accessed with a lock that we have initialised in pinit. We have also initialised the initial values of s and e to zero in Userinit. Since the queue and the functions relating to it are needed in other files too, we added prototypes in defs.h too.
In this assignment, we quantitatively compare and quantify the advantages of the various new features in ext and ZFS file systems.
Feature | PresentAbsent in ZFS | Present/Absent in ext4 |
---|---|---|
Deduplication | Present | Absent |
Compression | Present | Absent |
Checksum | Present | Absent |
Internal Snapshotting/Branching | Present | Absent |
Persistent Cache | Present | Absent |
Encryption | Present | Present |
Block Journaling | Present | Present |
Copy-on-write | Present | Absent |
Comparison of deduplication
Comparison of compression