% Exam Template for UMTYMP and Math Department courses
%
% Using Philip Hirschhorn's exam.cls: http://www-math.mit.edu/~psh/#ExamCls
%
% run pdflatex on a finished exam at least three times to do the grading table on front page.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% These lines can probably stay unchanged, although you can remove the last
% two packages if you're not making pictures with tikz.
\documentclass[11pt]{exam}
\RequirePackage{amssymb, amsfonts, amsmath, latexsym, xspace, setspace}
\RequirePackage{tikz, pgflibraryplotmarks}

% By default LaTeX uses large margins.  This doesn't work well on exams; problems
% end up in the "middle" of the page, reducing the amount of space for students
% to work on them.
\usepackage[margin=1in]{geometry}
\usepackage{verbatim}

% Here's where you edit the Class, Exam, Date, etc.
\newcommand{\class}{Operating Systems}
\newcommand{\term}{Spring 2019}
\newcommand{\examnum}{Final}
\newcommand{\examdate}{06/12/2019}
\newcommand{\timelimit}{4pm - 6pm}

% For an exam, single spacing is most appropriate
\singlespacing
% \onehalfspacing
% \doublespacing

% For an exam, we generally want to turn off paragraph indentation
\parindent 0ex

\def\answers{1}


\begin{document} 

% These commands set up the running header on the top of the exam pages
\pagestyle{head}
\firstpageheader{}{}{}
\runningheader{\class}{\examnum\ - Page \thepage\ of
\numpages}{\fbox{\rule{2in}{0pt}\rule[-0.5ex]{0pt}{5ex}}}
\runningheadrule

\begin{flushright}
\begin{tabular}{p{2.8in} r l}
%\textbf{\class} & \textbf{Name (Print):} & \makebox[2in]{\hrulefill}\\
  \textbf{\class} & \textbf{Name (Print):} &
  \fbox{\rule{2in}{0pt}\rule[-0.5ex]{0pt}{5ex}}\\
\textbf{\term} &&\\
\textbf{\examnum} &&\\
\textbf{\examdate} &&\\
\textbf{Time Limit: \timelimit} & & \\
\end{tabular}\\
\end{flushright}
\rule[1ex]{\textwidth}{.1pt}




%\begin{minipage}[t]{3.7in}
%\vspace{0pt}
\begin{itemize}

\item \textbf{Don't forget to write your name on this exam.} 

\item \textbf{This is an open book, open notes exam. But no online or 
    in-class chatting.  } 

    
\item \textbf{Ask us if something is confusing in the questions.}

\item \textbf{Organize your work}, in a reasonably neat and coherent way, in
the space provided. Work scattered all over the page without a clear ordering will 
receive very little credit.  

\item \textbf{Mysterious or unsupported answers will not receive full
credit}.  A correct answer, unsupported by explanation will receive no credit; 
an incorrect answer supported by substantially correct explanations might still 
receive partial credit.

\item If you need more space, use the back of the pages; clearly indicate when you have done this.

\item \textbf{Don't forget to write your name on this exam.} 

\item \textbf{This is an open book, open notes exam. But no online or 
    in-class chatting.  } 

\end{itemize}

%Do not write in the table to the right.
%\end{minipage}
%\hfill

%\begin{minipage}[t]{2.3in}
%\vspace{0pt}
%\cellwidth{3em}
%\gradetablestretch{2}
\vqword{Problem}
\addpoints % required here by exam.cls, even though questions haven't started yet.	
\gradetable[v]%[pages]  % Use [pages] to have grading table by page instead of question

%\end{minipage}
\newpage % End of cover page

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% See http://www-math.mit.edu/~psh/#ExamCls for full documentation, but the questions
% below give an idea of how to write questions [with parts] and have the points
% tracked automatically on the cover page.
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{questions}


\addpoints

\question Context switch. Ben is a student in cs238P. While preparing for the final exam he looks up 
the following question from the last year's exam: 

\emph{The register \texttt{EBX} gets saved twice, once by the
\texttt{pushall} instruction in the \texttt{alltraps()} function and second in
the \texttt{swtch()} function.  Can you explain why do we need to save it twice?}

He then reads the answer to this question:

\emph{First, EBX value of the user-process is saved on the trapframe inside the
proc-$>$tf-$>$ebx field of the trapframe data structure. Then since EBX is
callee saved register, the kernel cannot assume that it's value will be
presumed while some other process is switched to run on the CPU. Hence xv6
pushes it on the stack as part of the context data structure
(proc-$>$contex-$>$ebx).}

\begin{parts} 

\part[5] Ben is confused by the answer. He desides to change xv6 and don't save \texttt{EBX} inside 
alltrap(). What will go wrong? Be specific, describe in details how the system misbehaves, 
and provide a concrete example. 

\if\answers1 

\textbf{Answer:} Several answers are accepted. First of all, Ben should be
careful to implement his changes. He has to replace the \texttt{pushall}
instruction with several \texttt{push} instructions that save all registers but
\texttt{EBX}, and implement similar changes on the exit path, i.e., replaces
\texttt{popal} with a bunch of \texttt{pop} instructions. Further, he has to
change the definition of the trapframe data structure, i.e., remove the space
taken by the \texttt{ebx}. 

It's ok to base your answer on the assumption that Ben forgets to change the
trapframe data structure (in this case the kernel will crash ...)

But if Ben does all the changes correctly, the user value of the \texttt{EBX}
register does not get saved when the execution transitions into the kernel via
an interrupt, and does not get restored on the exit path. Since kernel
functions use the \texttt{EBX} register, sooner or later this will overwrite
the user state of \texttt{EBX} and the user program will crash unpredictably or
will exhibit some undefined behavior. For example, if \texttt{EBX} contains an
array index, the changed value of \texttt{EBX} will result in an out-of-bounds
access, e.g., for example to an unmapped region of memory, and a crash due to a
translation of a virtual address that is not present in the page table. 

\fi

\vfill 

\part[5] Now Ben decides to save \texttt{EBX} inside the \texttt{alltraps()} 
function, but don't save it inside the \texttt{swtch()} function. Again, 
be specific, describe in details how the system misbehaves, and provide a 
concrete example of how it crashes. 

\if\answers1 

\textbf{Answer:} The \texttt{swtch()} function implements the final steps of
the context switch from a process to the scheduler and back. If the
\texttt{EBX} register does not get saved and restored the value of the register
will sooner or later be overwritten by the code of another process or the
scheduler. I.e., sooner or later the code of the kernel will exhibit some
unpredictable behavior, e.g., overwriting random data structures (e.g., if
\texttt{EBX} contains a pointer to some data structure), accessing unmapped
virtual addresses, repeating iterations of a loop (if \texttt{EBX} contains the
loop index), etc.

\fi

\vfill

\newpage

\part[5] Ben looks through the xv6 code trying to understand where the ``context'' 
data structure of each process is allocated. Can you help Ben by explaining this to him? 


\if\answers1 

\textbf{Answer:} The context data structure is allocated by the
\texttt{allocproc()} function on the kernel stack of the process. I.e.,
\texttt{allocproc()} allocates a page of memory from the kernel memory
allocator for the kernel stack. It then uses top of this page for the
trapframe, and the space right below the trapframe for the ``context''. 

\fi

\vfill

\part[5] Ben continues preparing for the final exam. He understands that the ``context''
data structure serves the purpose of saving and restoring the callee registers and 
instruction pointer (\texttt{EIP}) of the process. Ben understands that for each process 
the ``context'' is initialized by the \texttt{allocproc()} function like this: 

\begin{verbatim}
2509   sp -= sizeof *p->context;
2510   p->context = (struct context*)sp;
2511   memset(p->context, 0, sizeof *p->context);
2512   p->context->eip = (uint)forkret;
\end{verbatim}

Can you explain why ``context'' is initialized with zeros? 

\if\answers1 

\textbf{Answer:} The context contains the values of the callee saved registers
(\texttt{edi}, \texttt{esi}, \texttt{ebx}, \texttt{ebp}). I.e., the
\texttt{swtch()} function will load these values into the actual hardware
registers switching from the scheduler to the newly allocated process. However,
since the process didn't run yet, and moreover it does not expect any specific
values in these registers, i.e., remember that the process will start from
executing the \texttt{main()} function, that expects its arguments on the
stack, but does not expect any specific values in registers, it's ok to
initialize these registers with zeros. It would be fine to leave this memory
uninitialized, since again the process does not expect anything in these
registers, but this would introduce an information leakage vulnerability, e.g.,
imagine some process kept a data structure containing a password on the same
physical page where context is now allocated. 


\fi

\vfill

\newpage
\part[5] Ben knows that the scheduler also has ``context'', but he is confused again. Can you 
explain at what point the ``context'' of the scheduler is initialized? 

\if\answers1 

\textbf{Answer:} The context of the scheduler is initialized right when the
scheduler context switches into the process for the first time. The context
data structure of the scheduler is allocated on the stack of the scheduler
process (i.e., it's not really allocated, the callee saved registers are simply
pushed on the stack by the \texttt{swtch()} function, and the pointer to the
top of the stack becomes the pointer to the ``context'' of the scheduler).

\fi

\vfill


\end{parts}


\addpoints

\question Synchronization

\begin{parts} 

\part[5] Along with the \texttt{acquire()} function, xv6 implements a different \texttt{acquiresleep()} function.

\begin{verbatim}
4621 void
4622 acquiresleep(struct sleeplock *lk)
4623 {
4624   acquire(&lk->lk);
4625   while (lk->locked) {
4626     sleep(lk, &lk->lk);
4627   }
4628   lk->locked = 1;
4629   lk->pid = myproc()->pid;
4630   release(&lk->lk);
4631 }
\end{verbatim}

Can you explain the logic of the \texttt{acquiresleep()} function and the 
difference between \texttt{acquire()} and \texttt{acquiresleep()}? 


\if\answers1 

\textbf{Answer:} The \texttt{acquiresleep()} function first acquires the
\texttt{lk-lk} lock (line 4624). It then checks the \texttt{lk->locked} flag
(line 4625), if it's set it goes to sleep passing the \texttt{lk-lk} lock as an
argument to the \texttt{sleep()} function (this allows preventing the ``lost
wakeup'' problem). It the \texttt{lk->locked} flag is not set, the function
sets it in line 4628 (note, it's ok to do that, there is no race since
\texttt{lk-lk} is already acquired). It finally releases the \texttt{lk-lk}
lock (line 4630) and exits (at this point the ``sleeplock '' is acquired). 

The main difference between \texttt{acquire()} and \texttt{acquiresleep()} is
that \texttt{acquire()} is spinning on the lock until it acquires it (this is
good for short critical section, e.g., a program on another CPU is holding the
lock for a short period of time). The \texttt{acquiresleep()} function on the
other hand allows the process to sleep instead of spinning. This is a natural
choice in the cases when the lock will be held for a long period of time by
another process in the system (e.g., in parts of the file system). Spinning
would be wasteful in this case since the lock might be acquired for several
time ``ticks''. 

\fi

\vfill 

\end{parts}

\newpage
\addpoints

\question The \texttt{sleep()} function allows the process to sleep for 
a requested number of ticks (timer interrupts). 

\begin{verbatim}
3814 int
3815 sys_sleep(void)
3816 {
3817   int n;
3818   uint ticks0;
3819 
3820   if(argint(0, &n) < 0)
3821     return -1;
3822   acquire(&tickslock);
3823   ticks0 = ticks;
3824   while(ticks - ticks0 < n){
3825     if(myproc()->killed){
3826       release(&tickslock);
3827       return −1;
3828     }
3829     sleep(&ticks, &tickslock);
3830   }
3831   release(&tickslock);
3832   return 0;
3833 }
\end{verbatim}

\begin{parts}

\part[5] What does it mean for the process to go to ``sleep()'' in line 3829 above? Be specific, describe what happens to the process and why it's not running?  

\if\answers1 

\textbf{Answer:} The process is not running because the \texttt{sleep()}
function sets the process state to \texttt{SLEEPING} and then context switches
into the scheduler picking the next process to run. Note that the scheduler
will not pick a process in the \texttt{SLEEPING} state to run, hence the
process will not be context switched into by the scheduler until it is woken up
by the \texttt{wakeup()} function. 

\fi

\vfill

\part[5] At what point this process (which part of the kernel code) ``wakes
up'' the sleeping process? 

\if\answers1 

\textbf{Answer:} The process is waken up from the timer interrupt handler from
inside the \texttt{trap()} function. Specifically the following code wakes up
every process sleeping on the address of the \texttt{ticks} variable. 

\begin{verbatim}
3413   switch(tf−>trapno){
3414   case T_IRQ0 + IRQ_TIMER:
3415     if(cpuid() == 0){
3416       acquire(&tickslock);
3417       ticks++;
3418       wakeup(&ticks);
3419       release(&tickslock);
3420     }
3421     lapiceoi();
3422     break;
\end{verbatim}

\fi

\vfill
\end{parts}

\newpage
% Basic question
\addpoints \question File system


Xv6 lays out the file system on disk as follows:

\begin{figure}[h] \centering
  \includegraphics[width=0.8\columnwidth]{figs/fs}
  \label{fig:ramengine-decomposed-app}

\end{figure}

Block 1 contains the super block. Blocks 2 through 31 contain the log header
and the log. Blocks 32 through 57 contain inodes. Block 58 contains the bitmap
of free blocks. Blocks 59 through the end of the disk contain data blocks.

\begin{parts} 

\part[5] Every file system transaction that changes the file system write one disk block
twice. What is this block (what’s its block number) and why is it written twice?

\if\answers1 

\textbf{Answer:} Block 2 is written twice since it contains the log header. The log header is first 
updated when all the other blocks are added to the log with the size of the transaction. And then after 
transaction is installed, the log header is updated with zero. 

\fi

\vfill


\part[5] If the \texttt{inode} is defined as follows, what is the maximum number of 
inodes this file system can have 

\begin{verbatim}
4073 #define NDIRECT 12
...

4077 // On−disk inode structure
4078 struct dinode {
4079   short type;           // File type
4080   short major;          // Major device number (T_DEV only)
4081   short minor;          // Minor device number (T_DEV only)
4082   short nlink;          // Number of links to inode in file system
4083   uint size;            // Size of file (bytes)
4084   uint addrs[NDIRECT+1];// Data block addresses
4085 };
\end{verbatim}


\if\answers1
\textbf{Answer:} To count up the number of inodes supported by the file system we have to see how many 
times the \texttt{dinode} structure can fit into the area of the file system dedicated for keeping 
the inodes (i.e., from block 32 to block 58). The total size of this area is $(58 - 32)*512 = 26*512 = 13312$ bytes. 

The size of the \texttt{dinode} data structure is 4 members of type \texttt{short} which is 2 bytes, and 14 members of 
type \texttt{uint} which is 4 bytes, or 64 bytes. Then the total number of inodes will be $13312/64 = 208$


\fi

\vfill

\newpage
\part[5] What is the maximum file size the xv6 file system supports? 

\if\answers1 

\textbf{Answer:} 
The xv6 supports the file size of 12 direct block and $512/4 = 128$ indirect blocks. Or
$(12 + 128)*512 = 71680$ bytes. 

\fi

\vfill


\part[5] Alice wants to double the maximum file size xv6 supports, what does she have to do? Be specific. 

\if\answers1
\textbf{Answer:} Alice has to change the definition of the \texttt{dinode} structure. One way to do this is to 
double the number of direct and indirect blocks like this

\begin{verbatim}
4084   uint addrs[2*(NDIRECT+1)];// Data block addresses
\end{verbatim}

An equivalent but slightly better way would be to change the definition of \texttt{NDIRECT} like this:

\begin{verbatim}
4073 #define NDIRECT 12*2
...
4084   uint addrs[NDIRECT+1*2];// Data block addresses
\end{verbatim}

This allows her to have 24 direct blocks and 2 indirect blocks. She then has to change the \texttt{bmap()} function 
that converts logical offsets within the file to actual block numbers on disk to accomodate for this change.
%
\iffalse
For that she needs to change the number of indirect blocks in a file

\begin{verbatim}
4074 #define NINDIRECT (2*BSIZE / sizeof(uint))
\end{verbatim}
\fi
%
For example, she can add the following lines right after line 5435

\begin{verbatim}
5436   if(bn < 2*NINDIRECT){
5437     // Load indirect block, allocating if necessary.
5438     if((addr = ip−>addrs[NDIRECT + 1]) == 0)
5439       ip−>addrs[NDIRECT + 1] = addr = balloc(ip−>dev);
5440     bp = bread(ip−>dev, addr);
5441     a = (uint*)bp−>data;
5442     if((addr = a[bn]) == 0){
5443       a[bn] = addr = balloc(ip−>dev);
5444       log_write(bp);
5445     }
5446     brelse(bp);
5447     return addr;
5448   }
\end{verbatim}


\fi

\vfill




\end{parts}

\newpage
\addpoints 
\question Processes 

\begin{parts}

\iffalse

\part[5] Alice decides that since threads of the same process share the same memory she can 
avoid invoking the \texttt{pipe()} system call for communicating between the threads of the 
same process. She decides to implement her own \texttt{tpipe()} (a function that creates a new 
pipe), \texttt{tpipewrite(struct pipe *p, char *buffer, int len)} (a function that writes the 
pipe), and \texttt{tpiperead(struct pipe *p, char *buffer, int len)} (a funciton that 
reads from the pipe) functions. Can you sketch the code for these functions? The functions should 
work similar to the pipe system calls provided by the kernel
she sees the shell command prompt after the boot (be specific: what these processes are)? 


\if\answers1

\textbf{Answer:}


\fi

\vfill

\fi

\part[5] Alice is running an xv6 system with two CPUs. Is it possible for 
the \texttt{init()} process which is created on the first CPU to run on the 
second CPU at some point in time? Be specific, explain why this may or may not 
happen.  

\if\answers1
\textbf{Answer:} Yes, this is possible. Xv6 runs a scheduler on each physical CPU. Each 
scheduler goes through the table of processes and pics the one that can run (i.e., is in the \texttt{RUNNABLE}
state). Sooner or later the \texttt{init} process will be picked up by the scheduler of 
the second CPU, will be context switched into, and will run.  


\fi

\vfill

\end{parts}

%\newpage
\addpoints

\question cs238P. I would like to hear your opinions about cs238P, so please answer the following questions. (Any answer, except
no answer, will receive full credit.)


\begin{parts}

\part[1] Grade cs238P on a scale of 0 (worst) to 10 (best)?

\vfill

\part[2] Any suggestions for how to improve cs238P?

\vfill

\newpage
\part[1] What is the best aspect of cs238P?

\vfill

\part[1] What is the worst aspect of cs238P?

\vfill

\end{parts}

\newpage

\begin{verbatim}

\end{verbatim}

% If you want the total number of points for a question displayed at the top,
% as well as the number of points for each part, then you must turn off the point-counter
% or they will be double counted.
%\newpage
%\addpoints
%\question[10] Even more work.
%\noaddpoints % If you remove this line, the grading table will show 20 points 
%for this problem.
%\begin{parts} \part[5] Even more...  \vspace{4.5in} \part[5] That's clearly
%too much \end{parts}



\end{questions}
\end{document}
