% 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}{Fall 2018}
\newcommand{\examnum}{Final}
\newcommand{\examdate}{12/11/2018}
\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

\begin{parts} 

\part[5] Provide a high-level description of what happens during the context
switch?  


\if\answers1 

\textbf{Answer:}

There are two possible cases when xv6 switch from one process to another: 1)
when the timer interrupt arrives, 2) when the process is going to sleep inside
a system call and yields it's CPU time slides. In both cases the mechanics of
the context switch are similar: the process enters the kernel with either an
interrupt or a system call (in xv6 the system calls are invoked with the
\texttt{int} instruction, so the path is very much the same).  If the timer
interrupt arrives and the process is already in the kernel, the hardware saves
only 3 values on the kernel stack, since there is no change of privilege level
and hence SS and CS don't have to be saved. If however the process is running
in the user-space (CPL = 3) the hardware pushes 5 values on the kernel stack.
Note, that execution cannot continue on the user stack, and hence the hardware
locates the kernel stack by looking up the TSS. The hardware fetches the CS and
EIP of the interrupt handler from the IDT, pushes 5 values on the stack, loads
new CS segment from the GDT (the execution continues with CPL = 0) and jumps to
the entry point of the handler. 

The handler saves state of the user process with the \texttt{alltraps} assembly function, pushes the pointer to the trapframe
on the stack and invokes the C \texttt{traps()} function. Inside trap() the kernel context switches into the scheduler 
with the \texttt{swtch()} function. The scheduler picks the next process to run from the array of all processes, and switches into that 
process by invoking \texttt{swtch()} again.  

More details of how the state is saved on the stack are needed here ...  
\fi

\vfill 
\vfill

\part[5] During the context switch, where is the user register EAX saved (i.e., the value of the EAX register that was used by the preempted user program)?  

\if\answers1 


\textbf{Answer:}

On the kernel stack, inside the trap frame, proc-$>$tf-$>$eax. 

\fi

\vfill 

\newpage


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

\if\answers1 

\textbf{Answer:}

 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). 

\fi

\vfill

%\newpage

\part[10] In xv6 during the context switch the process first switches to the
scheduler and then switches to the next process. Ben thinks it is wasteful to
switch into the scheduler, and decides to change xv6 to switch directly to the
next process. What changes he needs to implement?  Be specific: describe the
data structures that need to be changed, explain why your changes are correct,
provide a sketch for the code that implements it. 

\if\answers1

\fi

\vfill


\end{parts}

\newpage

\begin{verbatim}

\end{verbatim}
\vfill

% 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.

Ben boots xv6 with a fresh fs.img and starts a program that opens a file which 
is represented by the inode 0 and writes one byte into it. The inode's dentry[0] 
contains 76.

\begin{parts} 

\part[5] Which blocks will be written as the result of the write system call? 

\if\answers1 

\textbf{Answer:}

\begin{verbatim}
block 3              // Log data (bitmap)
block 4              // Log data (actual byte)
block 5              // Log data
block 2              // Log header
block 58             // Bitmap 
block 595            // Actual byte (any number between 59 and ... is fine as answer)
                     // In xv6 some data space is taken by the file system
block 32             // Inode 
block 2              // Log header
\end{verbatim}


\fi

\vfill

\newpage

\part[5] Which block will be written more than once?

\if\answers1
Block \#2 that contains the log header. 

\fi

\vfill

\end{parts}

%\newpage
\addpoints
\question Interrupts and Exceptions

\begin{parts}

\part[5] Describe what happens when a timer interrupt arrives while a process executes in the kernel,
i.e., after entering the kernel with a system call. Will it be preempted?

\if\answers1

\textbf{Answer:}

If the timer interrupt 
arrives and the process is already in the kernel, the hardware saves only 3 values on the kernel 
stack, since there is no change of privilege level and hence SS and CS don't have to be saved. The rest of the 
interrupt path is the same: the hardware locates the interrupt handler through the IDT, and jumps to it. The interrupt 
handler goes through two assembly functions: \texttt{vector32} and \texttt{alltraps} that save current state 
of the registers on the kernel stack forming a valid trapframe, it then passes control to the \texttt{trap()} function that will 
continue with the timer interrupt and will enter the context switch by invoking the \texttt{swtch() function}.  

\fi

\vfill

\end{parts}

\newpage

\addpoints 
\question Scheduler

\begin{parts}

\part[5] Alice is booting into an xv6 system. How many processes are running when
she sees the shell command prompt after the boot (be specific: what these processes are)? 


\if\answers1

\textbf{Answer:}

Two: init and shell

\fi

\vfill

\part[5] Alice is running a single-CPU xv6 system (a machine that has only one physical 
CPU). She creates five processes
in the system. Is it possible that the same process runs for two consecutive
scheduling periods, i.e., the process is running when the timer interrupt
arrives, the timer interrupt handler forces a context switch into the
scheduler, but the scheduler chooses the same process to run again? Explain
your answer. 

\if\answers1
\textbf{Answer:}


Yes, it's possible, maybe all 4 other processes are waiting in the kernel, and hence are not in the RUNNABLE state. The scheduler will not be able to run them, and will come back to the original process. 
\fi

\vfill

\end{parts}

\newpage
\addpoints
\question Synchronization

\begin{parts}

\part[5] Alice removes \texttt{xchg()} from the \texttt{acquire()} function.
Explain what happens  when  she boots xv6 on a multi-processor machine, i.e.,
machine with more than one physical CPUs. 

\if\answers1 

\textbf{Answer:}


If you remove the loop that atomically sets the \texttt{locked} filed of the
lock to 1 you will break the spinlock acquisition mechanisms---the spinlock
will always be signalled as successfully acquired, two processes will be able
to enter the same critical section simultaneously and will leave kernel data
structures, e.g., process table, buffer cache, file table, etc., in an
inconsistent state. The kernel will crash sooner or later. 

\fi


\vfill

\part[5] Now Alice decides to put the following code instead of the original \texttt{xchg()} loop in the \texttt{acquire()} function 

\begin{verbatim}
for(;;) {
  if(!lk->locked)
  {
    lk->locked = 1;
    break;
  }
}
\end{verbatim}

She boots xv6 again on a multi-processor machine, explain what happens?

\if\answers1 

\textbf{Answer:}


Now the two lines (and several assembly instructions that are involved in implementing those lines): the one line 
that checks the \texttt{locked} filed and the line that sets it are not atomic. Sooner or later it will result in a race when 
two processes will try to acquire the same lock on two different CPUs. 

\fi


\vfill 

\newpage

\part[10] Alice discovered that her CPU provides hardware support for symmetric
encryption. In other words she can submit a pointer to a block of memory and a
pointer to symmetric key to a hardware device that will encrypt the content of the block. 
Later she can get the block of memory encrypted. 
Unfortunately, the hardware encryption still takes tens of
thousands of cycles, so she decides that instead of waiting for the encryption to 
finish, she
can release the CPU for another process, and then receive an interrupt from the
crypto device when encryption is done. 

Help Alice to write a submission routine and
the interrupt handler. Specifically, concentrate on correct use of
synchronization primitives. Assume that Alice already implemented a low-level
function \texttt{hw\_encrypt()} that passes two pointers (buffer and 
key) to the crypto device and is now working on two functions: 1)
submission function \texttt{encrypt\_block()} that takes a pointer to the
\texttt{cdev} structure that Alice uses to describe the state of the crypto
device in her code, and two pointers (buffer and key) that she has to pass to the 
low-level \texttt{hw\_encrypt()} function for encryption. 

Your code should correctly handle synchronization between multiple processes that 
are trying to access the crypto device, and the interrupt handler that signals completion of 
encryption. 

\begin{verbatim} 
/* Low-level function to pass buffer and the key to hardware */
void hw_encrypt(void *buf, void *key); 

struct cdev *c; 

void encrypt_block(struct cdev *c, void *buf, void *key) {

  acquire(&c->lock);  

  // Wait for device to become available
  while(c->flags != C_AVAIL){
    sleep(c, &c->lock);
  }

  // This process owns the device 
  // Submit request for encryption
  cdev = c; 
  hw_encrypt(buf, key);

  // Wait for request to finish.
  while(c->flags != C_DONE){
    sleep(c, &c->lock);
  }

  // Set device to available
  c->flags = C_AVAIL;
  // Wakeup all waiters 
  wakeup(c); 

  release(&c->lock);
  return;
}

/* Interrupt handler for the encryption device */
void encrypt_int(void) {

  c = cdev; 
  acquire(&c->lock);
    
  // Wake process waiting for this buf.
  c->flags = B_DONE;
  wakeup(c);
  
  release(&c->lock);

}

\end{verbatim}


\end{parts}

%\newpage
\addpoints
\question Process memory layout

Ben wrote a  user program  that  grows  its  address  space  with  1  byte  by  calling
the \texttt{sbrk()} system call. He runs the program  and  investigates  the  page  
table  for  the  program  before and after the call  to sbrk().

\begin{parts}

\part[5] How  much  space  has  the  kernel  allocated?  

\if\answers1 

\textbf{Answer:}


One page if it's first byte of the new page, or no pages if the page was
previously allocated. 

\fi


\vfill



\newpage
\part[5] What  does  the pte for  the  new  memory  contain?

\if\answers1 

\textbf{Answer:}


The PTE for the new memory contains the physical frame number of the page that
was allocated for the new page, and the flags: user accessible, writable, and
present. 


\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

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

\vfill

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

\vfill

\end{parts}


% 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}
