CSE130 Winter 2021 : Lab 3
In this lab you will implement user processes and system calls.
As supplied, Pintos is incapable of running user processes and only implements two systems calls. Pintos
does, however, have the ability to load ELF binary executable, and has a fully functioning page-based, nonvirtual memory management system.
There are three parts to this lab; each depends on the previous one.
• Allow simple user process to run.
• Support argument passing to user processes.
• Implement seven new systems calls.
(1) Pintos Calling Conventions
Pinto is a Unix-like operating system and should implement the standard Unix / C calling convention.
To understand how arguments are passed to Unix / C programs, consider the command:
/bin/ls -l foo bar
Also recall that the prototype for a C program entry point is:
int main(int argc, char *argv)
Where argc is the number of arguments passed to the program (including the program name) and argv is
an array containing pointers to each of the arguments stored as null-terminated character arrays.
To execute this program with the supplied arguments, we need to do the following:
• Break this command into words: ”/bin/ls”, ”-l”, ”foo”, and ”bar”.
• Place these words at the top of the stack, in right to left order.
• Push onto the stack the address of each string plus a null pointer sentinel, in right-to-left order.
o These are the elements of argv. The null pointer sentinel ensures that argv[argc] is a
null pointer, as required by the C standard. The order ensures that argv is at the lowest
virtual address. Word-aligned accesses are faster than unaligned accesses, so for best
performance, round the stack pointer down to a multiple of 4 before the first push.
• Push argv (the address of argv) and argc, in that order.
• Finally, push a fake “return address”. Although the entry function will never return, its stack frame
must have the same structure as any other.
(2) System Calls
Most user programs require services provided by Pintos; they access those capabilities by making system
calls. To support this feature, you will need to extend the existing rudimentary system call implementation in
The system calls of interest in this lab are:
• create : Creates a new file. Return true if successful and false otherwise.
• open : Open a file and return the corresponding file descriptor (i.e. an integer handle). Note that file
descriptor 0 is reserved for standard input and file descriptor 1 is reserved for standard output.
• read : Read a specified number of bytes from an existing, open file into a buffer in the user program,
returning the number of bytes actually read, or -1 if read failed.
• write: Write a specified number of bytes to an open file from a buffer in the user program. Return the
number of bytes actually written or -1 if an error occurs.
• close : Close an open file.
• exec : Starts the execution of a user program and returns the ID of the newly created child process if
successful. The parent process should not return from the exec system call until it knows whether
the child process has successfully loaded its executable code.
• wait : Waits for a child process to complete and retrieves the child’s exit value.