\documentclass{article}

\usepackage{amssymb}
\usepackage{amsmath}

\usepackage{enumerate}
\usepackage{enumitem}

\usepackage{hyperref}
\usepackage{listings}
\usepackage{fontspec}
\newfontfamily\lstlistingfamily[Scale=0.7]{DejaVu Sans Mono}

\usepackage{listings}
\lstset{language=c,
  showstringspaces=false,
  literate={-}{{\texttt{-}}}1{--}{{\texttt{-{}-}}}2{---}{{\texttt{-{}-{}-}}}3,
  basicstyle=\lstlistingfamily
}
\usepackage{mdframed}

\usepackage{makecell}
\usepackage{multirow}
\usepackage{tabularx}
\usepackage[table]{xcolor}

\usepackage{tikz}
\usepackage{multicol}
\usetikzlibrary{arrows,arrows.meta,automata,babel,backgrounds,decorations,backgrounds,positioning,fit}

% compact itemized and then enumerated
\setlist{leftmargin=*,
  noitemsep,
  topsep=5pt,
  parsep=0pt,
  partopsep=0pt,
}

\setlist[enumerate]{leftmargin=*,
  itemsep=2pt,
  topsep=0pt,
  parsep=0pt,
  partopsep=0pt,
}

\begin{document}
\begin{center}
{\Large Operating Systems: Concurrency Study Guide}
\end{center}

\noindent\textbf{Three [4] Easy Pieces; Where We Are}
\begin{description}
\item[Persistence] Saving data across computer power cycles;
  \emph{non-volatile} memory can use magnetic or optical media or
  solid-state memory that remembers its state.
\item[Virtualization] Emulating part (or all) hardware in
  system software to protect the actual hardware from direct access by
  running software. Can apply to the \emph{processor} and the
  \emph{memory}.
\item[\emph{Concurrency}] Safely sharing resources across multiple processes
  that are running ``at the same time'', typically by ordering their
  instruction interleaving such that they behave as if they were run
  serially.
\item[Abstraction] Dr. Ladd's \emph{Fourth Easy Piece} The operating
  system provides a facade over heterogeneous hardware, an abstract
  interface that hides the complexity of the underlying systems.
\end{description}

\noindent \textbf{Mechanism} v. \textbf{Policy} --- Remember that
mechanism is \emph{how} the system can do something and policy is
deciding \emph{when} or \emph{why} to do it.

\vspace{3mm}
\hrule{}
\vspace{1mm}

\begin{multicols}{2}[\textbf{\hspace{2cm}Address Space w/ Multiple Threads}]

\noindent
\textbf{Process Segments}

\begin{tikzpicture}
  \tikzstyle{RAMBox} = [right, draw, fill=black!30, minimum height=3cm, minimum width = 1.25cm, anchor=north,rectangle]
  \tikzstyle{SegmentBox} = [right, draw,  fill=white, minimum
  height=0.5cm, minimum width = 1.25cm, anchor=north, rectangle]
  \tikzstyle{StackSegmentBox} = [right, draw,  fill=white, minimum
  height=0.5cm, minimum width = 1.25cm, anchor=south, rectangle]
  \draw (0,0) node[RAMBox, minimum height=8cm] (RAM) {};
  \draw (0,0) node[SegmentBox, minimum width=1.25cm, minimum height=1.cm] (codeSegment) {};
  \draw node [left=of codeSegment] {\texttt{text}};
  \draw node [right=0.25cm of codeSegment.north east,anchor=north west] {\texttt{0x0000}};

  \draw (0,-1.) node[SegmentBox, minimum width=1.25cm, minimum height=1.cm] (dataSegment) {};
  \draw node [left=of dataSegment] {\texttt{data}};
  \draw node [right=0.25cm of dataSegment.north east,anchor=north west] {\texttt{0x0400}};

  \draw (0,-2.) node[SegmentBox, minimum width=1.25cm, minimum height=1.cm] (heapSegment) {};
  \draw node [left=of heapSegment] {\texttt{heap}};
  \draw node [right=0.25cm of heapSegment.north east,anchor=north west] {\texttt{0x0800}};

  \draw (0, -6) node [StackSegmentBox, minimum width=1.25cm, minimum height=1.cm] (stackSegmentB) {};
  \draw node [left=of stackSegmentB] {\texttt{stack B}};
  \draw node [right=0.25cm of stackSegmentB.north east,anchor=north west] {\texttt{0xF400}};
  \draw node [right=0.25cm of stackSegmentB.south east,anchor=south west] {\texttt{0xF7FF}};

  \draw node[StackSegmentBox, at=(RAM.south), minimum width=1.25cm, minimum height=1.cm] (stackSegmentA) {};
  \draw node [left=of stackSegmentA] {\texttt{stack A}};
  \draw node [right=0.25cm of stackSegmentA.north east,anchor=north west] {\texttt{0xFC00}};
  \draw node [right=0.25cm of stackSegmentA.south east,anchor=south west] {\texttt{0xFFFF}};
\end{tikzpicture}

\noindent
Addresses assume 64KB address space and exactly 1KB in use by each
segment. Each thread has its own, independent \lstinline|stack|
segment. This picture shows a stack segment for thread $A$ and for
thread $B$. The stack pointer (and, perhaps, stack origin) is part of
the \emph{thread context} and must be saved in the \emph{thread
  control block} (TCB).

\noindent
\textbf{Concurrency Terms}
\begin{description}
\item[critical section] a piece of code that accesses a \emph{shared} resource.
\item[race condition] when multiple \emph{threads of execution} enter
  their [same resource] critical region at roughly the same time;
  multiple updates to the shared data structure leads to potentially
  broken execution.
\item[indeterminate] programs are programs with race conditions; results of
  the computation depends on ordering of threads and can vary from run to run.
\item[mutual exclusion] structures protect critical regions,
  permitting at most one thread into the critical section. This
  eliminates race conditions, making the program determinate at the
  potential cost of parallel execution and thus speed.
\end{description}
\end{multicols}


\vspace{3mm}
\hrule{}
\vspace{1mm}
\noindent \textbf{Concurrency Primitives}
\begin{description}
\item[Locks] A \lstinline{lock} (\lstinline{Mutex} in Rust) is an ADT
  supporting
  \begin{description}[font=\ttfamily]
  \item[lock] function permits one thread past; all other threads
    \emph{spin} (keep checking the lock status) \textbf{or} are put in
    the \lstinline{Blocked} state with an \lstinline{unlock} operation
    serving to signal the thread to return to \lstinline{Ready}.
  \item[unlock] function releases some waiting thread to continue past
    its call to \lstinline|lock|. Lock is cleared if no thread is waiting.
  \end{description}

  \noindent Locks require some form of \emph{atomic update} machine
  instruction (hardware assist) such as \emph{test-and-set},
  \emph{load-linked}/\emph{store-conditional}, \emph{compare-and-swap},
  or \emph{fetch-and-add}.
\item[Condition Variables] A \lstinline{condition_variable}
  (\lstinline{Condvar} in Rust) is an ADT using an external lock and a queue to
  protect a critical region without a spin lock. The queue holds
  threads in the \lstinline{Blocked} state.
  \begin{description} [font=\ttfamily]
  \item[wait(\&lock)] thread must hold \lstinline|&lock| on call (and
    will hold it on return). \lstinline|wait| appears in a loop that
    tests the condition that would permit the thread to continue and is
    called when the condition is false. \lstinline|wait| (atomically)
    enqueues the thread, releases the lock, and then does a thread
    context switch. When the thread is made ready (dequeued),
    the \lstinline{wait} code acquires the lock and then return
    from \lstinline|wait|. (And the condition is tested again.)
  \item[signal(\&lock)] While holding \lstinline{lock}: if any threads
    await on the queue, make the first one \lstinline{Ready}. Release
    \lstinline{lock} and return.
  \end{description}

  A thread will only pass the \lstinline|wait| loop when the condition
  being tested is true.

\item[Semaphores] Initialized with a count (maximum number of threads
  allowed into the critical region) and
  \begin{description} [font=\ttfamily]
  \item[wait] decrements the counter and returns if the counter is
    non-negative (thread continues into critical section) or blocks on a
    queue otherwise.
  \item[post] increments the counter and wakes one of the waiting
    threads (if there are any).
  \end{description}

  \noindent
  Again, \lstinline|wait| is called in a loop.
\end{description}

\vspace{3mm}
\hrule{}
\vspace{1mm}
\noindent \textbf{Concurrent Algorithm Evaluation Criteria}
\begin{description}
\item[Safety] (or \textbf{Mutual Exclusion}) is the critical region
  actually \emph{safe}? There must be no sequence of interleaving that
  permits mutual exclusion to be violated.
\item[Fairness] does the algorithm avoid \emph{starvation}? Does a
  waiting thread enter the critical region \textbf{before} the thread
  that is in the critical region \emph{reenters} it?
\item[Performance] what is the runtime impact of the primitive? Consider
  no-contention, two-thread contention, and multi-thread
  contention. With caches and multiple processors, new performance
  concerns arise.
\end{description}
\vspace{15mm}
\hrule{}
\vspace{1mm}
\noindent \textbf{Common Concurrency Problems}
\begin{description}
\item[Producer/Consumer (Bounded Buffer)] A set, \emph{P}. of producer
  threads produce data; a set, \emph{C}, of consumer threads use data;
  communication is through a data \emph{buffer} with \emph{n} elements.

  If a producer makes data and there are no buffer slots, it must wait
  until one is free; if a consumer goes to take data and there is none
  available, it must wait until one is available.

\item[Reader-Writer] A set of readers, \emph{R}, and writers, \emph{W},
  share some data structure, \emph{D}. Readers read but do not change
  \emph{D}; writers read and \emph{may} modify \emph{D}.

  If a only readers are in their critical regions, arriving readers may
  enter theirs. If a writer comes, it must wait until all readers leave
  their critical regions; if readers arrive after a writer begins
  waiting, they wait on the writer leaving its critical region.

  Writers must enter their critical regions mutually exclusively with
  regard to both readers and writers.

  Efficient parallelism of readers and mutual exclusion for writers
  makes this a challenge.

\item[Dining Philosophers] $n$ philosophers sit at a round table with a
  bowl of rice in the middle and one chopstick between each pair of
  philosophers. Philosophers live life by thinking until they get
  hungry. When hungry, a philosopher must pick up both adjacent
  chopsticks before he can eat rice. When no longer hungry, the
  philosopher releases both chopsticks.

  The problem is making a starvation-free algorithm for chopstick
  acquisition given that a philosopher cannot communicate with his
  neighbors and only knows the number on the chair on which they sit.
\end{description}

\noindent \textbf{Atomic Instructions}
Consider \lstinline|SpinLock|:
\begin{lstlisting}[language=c++]
class SpinLock {
  public:
  SpinLock();
  void lock() volatile;
  void unlock() volatile;
};
\end{lstlisting}

\begin{lstlisting}[language=c++]
// --------------------------------------------------------------------------------------
// testAndSet(lockVar, newVal): atomically replace lockVar with newVal; return original value.
int testAndSet(int &lockVar, int newValue) {
  int original = lockVar;
  lockVar = newVal;
  return original;
}
\end{lstlisting}
\noindent
\textbf{Question:} Implement \lstinline|SpinLock| with \lstinline|testAndSet|.
\newpage
\begin{lstlisting}[language=c++]
// --------------------------------------------------------------------------------------
// compareAndSwap(lockVar, expVal, newVal): atomically swap lockVar value with newVal
// IFF lockVar's value was expVal. Return lockVar's original value
int compareAndSwap(int &lockVar, int expVal, int newVal) {
  int original = lockVar;
  if (original == expVal)
    lockVar = newVal;
  return original;
}
\end{lstlisting}
\noindent
\textbf{Question:} Implement \lstinline|SpinLock| with \lstinline|compareAndSwap|.

\begin{lstlisting}[language=c++]
// --------------------------------------------------------------------------------------
// loadLinked(lockVar) fetch and mark lockVar, return value
int loadLinked(int &lockVar) {
  return [and mark] lockVar;
}

// saveConditional(lockVar, newVal) set lockVar to newVal IFF still marked by this thread
// return whether the value was saved
bool saveConditional(int &lockVar, int newVal) {
  if (lockVar is marked by me) {
    lockVar = newVal;
    return true;
  } else
    return false;
}
\end{lstlisting}
\noindent
\textbf{Question:} Implement \lstinline|SpinLock| with \lstinline|loadLinked|/\lstinline|saveConditional|.
\end{document}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
