From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Akira Yokosawa <akiyks@gmail.com>
Cc: perfbook@vger.kernel.org
Subject: Re: [PATCH] Convert code snippets to 'listing' env (SMPdesign, locking, defer)
Date: Wed, 11 Oct 2017 15:56:21 -0700 [thread overview]
Message-ID: <20171011225621.GT3521@linux.vnet.ibm.com> (raw)
In-Reply-To: <a83ce6f6-cb5f-ab17-b65f-b77203ed51db@gmail.com>
On Thu, Oct 12, 2017 at 07:07:17AM +0900, Akira Yokosawa wrote:
> >From 096ac85c06a27b8e8895e35bb58c634869a5a979 Mon Sep 17 00:00:00 2001
> From: Akira Yokosawa <akiyks@gmail.com>
> Date: Wed, 11 Oct 2017 23:04:11 +0900
> Subject: [PATCH] Convert code snippets to 'listing' env (SMPdesign, locking, defer)
>
> Signed-off-by: Akira Yokosawa <akiyks@gmail.com>
Very good, queued, thank you!
One question...
o Figure 6.22: "SEQ Pseudocode" is still in the old style.
Ditto Figure 6.23: "SEQ Helper Pseudocode", Figure 6.26:
"Partitioned Parallel Solver Pseudocode", and Figure 6.27:
"Partitioned Parallel Helper Pseudocode". Are these to be
handled by a later commit, or is there something problematic
about these figures?
Thanx, Paul
> ---
> SMPdesign/SMPdesign.tex | 72 +++++++++++++++++------------------
> SMPdesign/partexercises.tex | 32 ++++++++--------
> defer/defer.tex | 8 ++--
> defer/hazptr.tex | 36 +++++++++---------
> defer/rcuapi.tex | 16 ++++----
> defer/rcufundamental.tex | 46 +++++++++++-----------
> defer/rcuusage.tex | 76 ++++++++++++++++++-------------------
> defer/refcnt.tex | 32 ++++++++--------
> defer/seqlock.tex | 52 ++++++++++++-------------
> locking/locking-existence.tex | 20 +++++-----
> locking/locking.tex | 88 +++++++++++++++++++++----------------------
> 11 files changed, 239 insertions(+), 239 deletions(-)
>
> diff --git a/SMPdesign/SMPdesign.tex b/SMPdesign/SMPdesign.tex
> index 81219cb..0dbef1e 100644
> --- a/SMPdesign/SMPdesign.tex
> +++ b/SMPdesign/SMPdesign.tex
> @@ -111,7 +111,7 @@ Again, if a program runs quickly enough on a single processor,
> spare yourself the overhead and complexity of SMP synchronization
> primitives.
> The simplicity of the hash-table lookup code in
> -Figure~\ref{fig:SMPdesign:Sequential-Program Hash Table Search}
> +Listing~\ref{lst:SMPdesign:Sequential-Program Hash Table Search}
> underscores this point.\footnote{
> The examples in this section are taken from Hart et
> al.~\cite{ThomasEHart2006a}, adapted for clarity
> @@ -121,7 +121,7 @@ limited to the number of CPUs.
> In contrast, speedups due to sequential optimizations, for example,
> careful choice of data structure, can be arbitrarily large.
>
> -\begin{figure}[tbhp]
> +\begin{listing}[tbhp]
> { \scriptsize
> \begin{verbbox}
> 1 struct hash_table
> @@ -153,8 +153,8 @@ careful choice of data structure, can be arbitrarily large.
> \centering
> \theverbbox
> \caption{Sequential-Program Hash Table Search}
> -\label{fig:SMPdesign:Sequential-Program Hash Table Search}
> -\end{figure}
> +\label{lst:SMPdesign:Sequential-Program Hash Table Search}
> +\end{listing}
>
> % ./test_hash_null.exe 1000 0/100 1 1024 1
> % ./test_hash_null.exe: nmilli: 1000 update/total: 0/100 nelements: 1 nbuckets: 1024 nthreads: 1
> @@ -191,14 +191,14 @@ from which only modest scaling is required. In these cases,
> code locking will provide a relatively simple program that is
> very similar to its sequential counterpart,
> as can be seen in
> -Figure~\ref{fig:SMPdesign:Code-Locking Hash Table Search}.
> +Listing~\ref{lst:SMPdesign:Code-Locking Hash Table Search}.
> However, note that the simple return of the comparison in
> \co{hash_search()} in
> -Figure~\ref{fig:SMPdesign:Sequential-Program Hash Table Search}
> +Listing~\ref{lst:SMPdesign:Sequential-Program Hash Table Search}
> has now become three statements due to the need to release the
> lock before returning.
>
> -\begin{figure}[tbhp]
> +\begin{listing}[tbhp]
> { \scriptsize
> \begin{verbbox}
> 1 spinlock_t hash_lock;
> @@ -237,8 +237,8 @@ lock before returning.
> \centering
> \theverbbox
> \caption{Code-Locking Hash Table Search}
> -\label{fig:SMPdesign:Code-Locking Hash Table Search}
> -\end{figure}
> +\label{lst:SMPdesign:Code-Locking Hash Table Search}
> +\end{listing}
>
> Unfortunately, code locking is particularly prone to ``lock contention'',
> where multiple CPUs need to acquire the lock concurrently.
> @@ -289,11 +289,11 @@ Data locking reduces contention by distributing the instances
> of the overly-large critical section across multiple data structures,
> for example, maintaining per-hash-bucket critical sections in a
> hash table, as shown in
> -Figure~\ref{fig:SMPdesign:Data-Locking Hash Table Search}.
> +Listing~\ref{lst:SMPdesign:Data-Locking Hash Table Search}.
> The increased scalability again results in a slight increase in complexity
> in the form of an additional data structure, the \co{struct bucket}.
>
> -\begin{figure}[tb]
> +\begin{listing}[tb]
> { \scriptsize
> \begin{verbbox}
> 1 struct hash_table
> @@ -337,8 +337,8 @@ in the form of an additional data structure, the \co{struct bucket}.
> \centering
> \theverbbox
> \caption{Data-Locking Hash Table Search}
> -\label{fig:SMPdesign:Data-Locking Hash Table Search}
> -\end{figure}
> +\label{lst:SMPdesign:Data-Locking Hash Table Search}
> +\end{listing}
>
> In contrast with the contentious situation
> shown in Figure~\ref{fig:SMPdesign:Lock Contention},
> @@ -405,7 +405,7 @@ A key challenge with data locking on dynamically allocated structures
> is ensuring that the structure remains in existence while the lock is
> being acquired.
> The code in
> -Figure~\ref{fig:SMPdesign:Data-Locking Hash Table Search}
> +Listing~\ref{lst:SMPdesign:Data-Locking Hash Table Search}
> finesses this challenge by placing the locks in the statically allocated
> hash buckets, which are never freed.
> However, this trick would not work if the hash table were resizeable,
> @@ -524,7 +524,7 @@ results resembling that shown in Figure~\ref{fig:SMPdesign:Data and Skew}.
> However, in situations where no sharing is required, data ownership
> achieves ideal performance, and with code that can be as simple
> as the sequential-program case shown in
> -Figure~\ref{fig:SMPdesign:Sequential-Program Hash Table Search}.
> +Listing~\ref{lst:SMPdesign:Sequential-Program Hash Table Search}.
> Such situations are often referred to as ``embarrassingly
> parallel'', and, in the best case, resemble the situation
> previously shown in Figure~\ref{fig:SMPdesign:Data Locking}.
> @@ -803,10 +803,10 @@ Writers exclude both readers and each other.
> There are many implementations of reader-writer locking, including
> the POSIX implementation described in
> Section~\ref{sec:toolsoftrade:POSIX Reader-Writer Locking}.
> -Figure~\ref{fig:SMPdesign:Reader-Writer-Locking Hash Table Search}
> +Listing~\ref{lst:SMPdesign:Reader-Writer-Locking Hash Table Search}
> shows how the hash search might be implemented using reader-writer locking.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 rwlock_t hash_lock;
> @@ -845,8 +845,8 @@ shows how the hash search might be implemented using reader-writer locking.
> \centering
> \theverbbox
> \caption{Reader-Writer-Locking Hash Table Search}
> -\label{fig:SMPdesign:Reader-Writer-Locking Hash Table Search}
> -\end{figure}
> +\label{lst:SMPdesign:Reader-Writer-Locking Hash Table Search}
> +\end{listing}
>
> Reader/writer locking is a simple instance of asymmetric locking.
> Snaman~\cite{Snaman87} describes a more ornate six-mode
> @@ -861,7 +861,7 @@ Chapter~\ref{chp:Locking}.
> The idea behind hierarchical locking is to have a coarse-grained lock
> that is held only long enough to work out which fine-grained lock
> to acquire.
> -Figure~\ref{fig:SMPdesign:Hierarchical-Locking Hash Table Search}
> +Listing~\ref{lst:SMPdesign:Hierarchical-Locking Hash Table Search}
> shows how our hash-table search might be adapted to do hierarchical
> locking, but also shows the great weakness of this approach:
> we have paid the overhead of acquiring a second lock, but we only
> @@ -869,7 +869,7 @@ hold it for a short time.
> In this case, the simpler data-locking approach would be simpler
> and likely perform better.
>
> -\begin{figure}[tb]
> +\begin{listing}[tb]
> { \scriptsize
> \begin{verbbox}
> 1 struct hash_table
> @@ -916,14 +916,14 @@ and likely perform better.
> \centering
> \theverbbox
> \caption{Hierarchical-Locking Hash Table Search}
> -\label{fig:SMPdesign:Hierarchical-Locking Hash Table Search}
> -\end{figure}
> +\label{lst:SMPdesign:Hierarchical-Locking Hash Table Search}
> +\end{listing}
>
> \QuickQuiz{}
> In what situation would hierarchical locking work well?
> \QuickQuizAnswer{
> If the comparison on line~31 of
> - Figure~\ref{fig:SMPdesign:Hierarchical-Locking Hash Table Search}
> + Listing~\ref{lst:SMPdesign:Hierarchical-Locking Hash Table Search}
> were replaced by a much heavier-weight operation,
> then releasing \co{bp->bucket_lock} \emph{might} reduce lock
> contention enough to outweigh the overhead of the extra
> @@ -987,7 +987,7 @@ blocks from the global pool.
>
> The actual data structures for a ``toy'' implementation of allocator
> caches are shown in
> -Figure~\ref{fig:SMPdesign:Allocator-Cache Data Structures}.
> +Listing~\ref{lst:SMPdesign:Allocator-Cache Data Structures}.
> The ``Global Pool'' of Figure~\ref{fig:SMPdesign:Allocator Cache Schematic}
> is implemented by \co{globalmem} of type \co{struct globalmempool},
> and the two CPU pools by the per-CPU variable \co{percpumem} of
> @@ -1006,7 +1006,7 @@ must be empty.\footnote{
> size makes it easier to single-step the program in order to get
> a feel for its operation.}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 #define TARGET_POOL_SIZE 3
> @@ -1029,8 +1029,8 @@ must be empty.\footnote{
> \centering
> \theverbbox
> \caption{Allocator-Cache Data Structures}
> -\label{fig:SMPdesign:Allocator-Cache Data Structures}
> -\end{figure}
> +\label{lst:SMPdesign:Allocator-Cache Data Structures}
> +\end{listing}
>
> The operation of the pool data structures is illustrated by
> Figure~\ref{fig:SMPdesign:Allocator Pool Schematic},
> @@ -1053,7 +1053,7 @@ smaller than the number of non-\co{NULL} pointers.
> \subsubsection{Allocation Function}
>
> The allocation function \co{memblock_alloc()} may be seen in
> -Figure~\ref{fig:SMPdesign:Allocator-Cache Allocator Function}.
> +Listing~\ref{lst:SMPdesign:Allocator-Cache Allocator Function}.
> Line~7 picks up the current thread's per-thread pool,
> and line~8 check to see if it is empty.
>
> @@ -1068,7 +1068,7 @@ In either case, line~18 checks for the per-thread pool still being
> empty, and if not, lines~19-21 remove a block and return it.
> Otherwise, line~23 tells the sad tale of memory exhaustion.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct memblock *memblock_alloc(void)
> @@ -1100,12 +1100,12 @@ Otherwise, line~23 tells the sad tale of memory exhaustion.
> \centering
> \theverbbox
> \caption{Allocator-Cache Allocator Function}
> -\label{fig:SMPdesign:Allocator-Cache Allocator Function}
> -\end{figure}
> +\label{lst:SMPdesign:Allocator-Cache Allocator Function}
> +\end{listing}
>
> \subsubsection{Free Function}
>
> -Figure~\ref{fig:SMPdesign:Allocator-Cache Free Function} shows
> +Listing~\ref{lst:SMPdesign:Allocator-Cache Free Function} shows
> the memory-block free function.
> Line~6 gets a pointer to this thread's pool, and
> line~7 checks to see if this per-thread pool is full.
> @@ -1119,7 +1119,7 @@ value.
> In either case, line~16 then places the newly freed block into the
> per-thread pool.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 void memblock_free(struct memblock *p)
> @@ -1144,8 +1144,8 @@ per-thread pool.
> \centering
> \theverbbox
> \caption{Allocator-Cache Free Function}
> -\label{fig:SMPdesign:Allocator-Cache Free Function}
> -\end{figure}
> +\label{lst:SMPdesign:Allocator-Cache Free Function}
> +\end{listing}
>
> \subsubsection{Performance}
>
> diff --git a/SMPdesign/partexercises.tex b/SMPdesign/partexercises.tex
> index f158f57..db4b5d8 100644
> --- a/SMPdesign/partexercises.tex
> +++ b/SMPdesign/partexercises.tex
> @@ -341,7 +341,7 @@ parallel double-ended queue.
> Each underlying single-lock double-ended queue holds a one-quarter
> slice of the full parallel double-ended queue.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct pdeq {
> @@ -356,10 +356,10 @@ slice of the full parallel double-ended queue.
> \centering
> \theverbbox
> \caption{Lock-Based Parallel Double-Ended Queue Data Structure}
> -\label{fig:SMPdesign:Lock-Based Parallel Double-Ended Queue Data Structure}
> -\end{figure}
> +\label{lst:SMPdesign:Lock-Based Parallel Double-Ended Queue Data Structure}
> +\end{listing}
>
> -Figure~\ref{fig:SMPdesign:Lock-Based Parallel Double-Ended Queue Data Structure}
> +Listing~\ref{lst:SMPdesign:Lock-Based Parallel Double-Ended Queue Data Structure}
> shows the corresponding C-language data structure, assuming an
> existing \co{struct deq} that provides a trivially locked
> double-ended-queue implementation.
> @@ -371,7 +371,7 @@ of simple lock-based double-ended queues on line~6.
> A high-performance implementation would of course use padding or special
> alignment directives to avoid false sharing.
>
> -\begin{figure*}[bp]
> +\begin{listing*}[bp]
> { \scriptsize
> \begin{verbbox}
> 1 struct cds_list_head *pdeq_pop_l(struct pdeq *d)
> @@ -428,10 +428,10 @@ alignment directives to avoid false sharing.
> \centering
> \theverbbox
> \caption{Lock-Based Parallel Double-Ended Queue Implementation}
> -\label{fig:SMPdesign:Lock-Based Parallel Double-Ended Queue Implementation}
> -\end{figure*}
> +\label{lst:SMPdesign:Lock-Based Parallel Double-Ended Queue Implementation}
> +\end{listing*}
>
> -Figure~\ref{fig:SMPdesign:Lock-Based Parallel Double-Ended Queue Implementation}
> +Listing~\ref{lst:SMPdesign:Lock-Based Parallel Double-Ended Queue Implementation}
> (\path{lockhdeq.c})
> shows the implementation of the enqueue and dequeue functions.\footnote{
> One could easily create a polymorphic implementation in any
> @@ -510,7 +510,7 @@ the previous section, the compound implementation will build on
> a sequential implementation of a double-ended queue that uses
> neither locks nor atomic operations.
>
> -\begin{figure*}[bp]
> +\begin{listing*}[bp]
> { \scriptsize
> \begin{verbbox}
> 1 struct cds_list_head *pdeq_pop_l(struct pdeq *d)
> @@ -574,10 +574,10 @@ neither locks nor atomic operations.
> \centering
> \theverbbox
> \caption{Compound Parallel Double-Ended Queue Implementation}
> -\label{fig:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> -\end{figure*}
> +\label{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> +\end{listing*}
>
> -Figure~\ref{fig:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> +Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> shows the implementation.
> Unlike the hashed implementation, this compound implementation is
> asymmetric, so that we must consider the \co{pdeq_pop_l()}
> @@ -626,7 +626,7 @@ Either way, line~34 releases the left-hand lock.
> \QuickQuiz{}
> Why is it necessary to retry the right-dequeue operation
> on line~28 of
> - Figure~\ref{fig:SMPdesign:Compound Parallel Double-Ended Queue Implementation}?
> + Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}?
> \QuickQuizAnswer{
> This retry is necessary because some other thread might have
> enqueued an element between the time that this thread dropped
> @@ -637,7 +637,7 @@ Either way, line~34 releases the left-hand lock.
> \QuickQuiz{}
> Surely the left-hand lock must \emph{sometimes} be available!!!
> So why is it necessary that line~25 of
> - Figure~\ref{fig:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> + Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> unconditionally release the right-hand lock?
> \QuickQuizAnswer{
> It would be possible to use \co{spin_trylock()} to attempt
> @@ -649,7 +649,7 @@ Either way, line~34 releases the left-hand lock.
> } \QuickQuizEnd
>
> The \co{pdeq_push_l()} implementation is shown on lines~40-47 of
> -Figure~\ref{fig:SMPdesign:Compound Parallel Double-Ended Queue Implementation}.
> +Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}.
> Line~44 acquires the left-hand spinlock, line~45 left-enqueues the
> element onto the left-hand queue, and finally line~46 releases
> the lock.
> @@ -659,7 +659,7 @@ is quite similar.
> \QuickQuiz{}
> But in the case where data is flowing in only one direction,
> the algorithm shown in
> - Figure~\ref{fig:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> + Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}
> will have both ends attempting to acquire the same lock
> whenever the consuming end empties its underlying
> double-ended queue.
> diff --git a/defer/defer.tex b/defer/defer.tex
> index 020b8b9..190bd36 100644
> --- a/defer/defer.tex
> +++ b/defer/defer.tex
> @@ -68,7 +68,7 @@ list to evaluate a number of read-mostly synchronization techniques.
> \label{fig:defer:Pre-BSD Packet Routing List}
> \end{figure}
>
> -\begin{figure}[tb]
> +\begin{listing}[tb]
> { \scriptsize
> \begin{verbbox}
> 1 struct route_entry {
> @@ -126,10 +126,10 @@ list to evaluate a number of read-mostly synchronization techniques.
> \centering
> \theverbbox
> \caption{Sequential Pre-BSD Routing Table}
> -\label{fig:defer:Sequential Pre-BSD Routing Table}
> -\end{figure}
> +\label{lst:defer:Sequential Pre-BSD Routing Table}
> +\end{listing}
>
> -Figure~\ref{fig:defer:Sequential Pre-BSD Routing Table}
> +Listing~\ref{lst:defer:Sequential Pre-BSD Routing Table}
> shows a simple single-threaded implementation corresponding to
> Figure~\ref{fig:defer:Pre-BSD Packet Routing List}.
> Lines~1-5 define a \co{route_entry} structure and line~6 defines
> diff --git a/defer/hazptr.tex b/defer/hazptr.tex
> index bd4fd64..bd2ff24 100644
> --- a/defer/hazptr.tex
> +++ b/defer/hazptr.tex
> @@ -19,7 +19,7 @@ Therefore, if that element has been rendered inaccessible to readers,
> and there are no longer any hazard pointers referencing it, that element
> may safely be freed.
>
> -\begin{figure}[btp]
> +\begin{listing}[btp]
> { \scriptsize
> \begin{verbbox}
> 1 int hp_store(void **p, void **hp)
> @@ -48,14 +48,14 @@ may safely be freed.
> \centering
> \theverbbox
> \caption{Hazard-Pointer Storage and Erasure}
> -\label{fig:defer:Hazard-Pointer Storage and Erasure}
> -\end{figure}
> +\label{lst:defer:Hazard-Pointer Storage and Erasure}
> +\end{listing}
>
> Of course, this means that hazard-pointer acquisition must be carried
> out quite carefully in order to avoid destructive races with concurrent
> deletion.
> One implementation is shown in
> -Figure~\ref{fig:defer:Hazard-Pointer Storage and Erasure},
> +Listing~\ref{lst:defer:Hazard-Pointer Storage and Erasure},
> which shows \co{hp_store()} on lines~1-13 and \co{hp_erase()} on
> lines~15-20.
> The \co{smp_mb()} primitive will be described in detail in
> @@ -73,7 +73,7 @@ recorded a hazard pointer for the data element.
>
> \QuickQuiz{}
> Why does \co{hp_store()} in
> - Figure~\ref{fig:defer:Hazard-Pointer Storage and Erasure}
> + Listing~\ref{lst:defer:Hazard-Pointer Storage and Erasure}
> take a double indirection to the data element?
> Why not \co{void *} instead of \co{void **}?
> \QuickQuizAnswer{
> @@ -178,7 +178,7 @@ Performance comparisons with other mechanisms may be found in
> Chapter~\ref{chp:Data Structures}
> and in other publications~\cite{ThomasEHart2007a,McKenney:2013:SDS:2483852.2483867,MagedMichael04a}.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct route_entry {
> @@ -222,10 +222,10 @@ and in other publications~\cite{ThomasEHart2007a,McKenney:2013:SDS:2483852.24838
> \centering
> \theverbbox
> \caption{Hazard-Pointer Pre-BSD Routing Table Lookup}
> -\label{fig:defer:Hazard-Pointer Pre-BSD Routing Table Lookup}
> -\end{figure}
> +\label{lst:defer:Hazard-Pointer Pre-BSD Routing Table Lookup}
> +\end{listing}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int route_add(unsigned long addr,
> @@ -275,24 +275,24 @@ and in other publications~\cite{ThomasEHart2007a,McKenney:2013:SDS:2483852.24838
> \centering
> \theverbbox
> \caption{Hazard-Pointer Pre-BSD Routing Table Add/Delete}
> -\label{fig:defer:Hazard-Pointer Pre-BSD Routing Table Add/Delete}
> -\end{figure}
> +\label{lst:defer:Hazard-Pointer Pre-BSD Routing Table Add/Delete}
> +\end{listing}
>
> The Pre-BSD routing example can use hazard pointers as shown in
> -Figure~\ref{fig:defer:Hazard-Pointer Pre-BSD Routing Table Lookup}
> +Listing~\ref{lst:defer:Hazard-Pointer Pre-BSD Routing Table Lookup}
> for data structures and \co{route_lookup()}, and in
> -Figure~\ref{fig:defer:Hazard-Pointer Pre-BSD Routing Table Add/Delete}
> +Listing~\ref{lst:defer:Hazard-Pointer Pre-BSD Routing Table Add/Delete}
> for \co{route_add()} and \co{route_del()}
> (\path{route_hazptr.c}).
> As with reference counting, the hazard-pointers implementation
> is quite similar to the sequential algorithm shown in
> -Figure~\ref{fig:defer:Sequential Pre-BSD Routing Table}
> +Listing~\ref{lst:defer:Sequential Pre-BSD Routing Table}
> on
> -page~\pageref{fig:defer:Sequential Pre-BSD Routing Table},
> +page~\pageref{lst:defer:Sequential Pre-BSD Routing Table},
> so only differences will be discussed.
>
> Starting with
> -Figure~\ref{fig:defer:Hazard-Pointer Pre-BSD Routing Table Lookup},
> +Listing~\ref{lst:defer:Hazard-Pointer Pre-BSD Routing Table Lookup},
> line~2 shows the \co{->hh} field used to queue objects pending
> hazard-pointer free,
> line~6 shows the \co{->re_freed} field used to detect use-after-free bugs,
> @@ -300,7 +300,7 @@ and lines~24-30 attempt to acquire a hazard pointer, branching
> to line~18's \co{retry} label on failure.
>
> In
> -Figure~\ref{fig:defer:Hazard-Pointer Pre-BSD Routing Table Add/Delete},
> +Listing~\ref{lst:defer:Hazard-Pointer Pre-BSD Routing Table Add/Delete},
> line~11 initializes \co{->re_freed},
> lines~32 and~33 poison the \co{->re_next} field of the newly removed
> object, and
> @@ -308,7 +308,7 @@ line~35 passes that object to the hazard pointers's
> \co{hazptr_free_later()} function, which will free that object once it
> is safe to do so.
> The spinlocks work the same as in
> -Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}.
> +Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}.
>
> \begin{figure}[tb]
> \centering
> diff --git a/defer/rcuapi.tex b/defer/rcuapi.tex
> index d60a0dd..6b4337a 100644
> --- a/defer/rcuapi.tex
> +++ b/defer/rcuapi.tex
> @@ -375,10 +375,10 @@ returns a value that must be passed into the corresponding
> \co{srcu_struct}.
> In practice, however, doing this is almost certainly a bad idea.
> In particular, the code shown in
> - Figure~\ref{fig:defer:Multistage SRCU Deadlocks}
> + Listing~\ref{lst:defer:Multistage SRCU Deadlocks}
> could still result in deadlock.
>
> -\begin{figure}[htbp]
> +\begin{listing}[htbp]
> {
> \begin{verbbox}
> 1 idx = srcu_read_lock(&ssa);
> @@ -395,8 +395,8 @@ returns a value that must be passed into the corresponding
> \centering
> \theverbbox
> \caption{Multistage SRCU Deadlocks}
> -\label{fig:defer:Multistage SRCU Deadlocks}
> -\end{figure}
> +\label{lst:defer:Multistage SRCU Deadlocks}
> +\end{listing}
> %
> } \QuickQuizEnd
>
> @@ -622,9 +622,9 @@ dereferences are protected by RCU.
> work out which type of RCU read-side critical section a given
> RCU traversal primitive corresponds to.
> For example, consider the code shown in
> - Figure~\ref{fig:defer:Diverse RCU Read-Side Nesting}.
> + Listing~\ref{lst:defer:Diverse RCU Read-Side Nesting}.
>
> -\begin{figure}[htbp]
> +\begin{listing}[htbp]
> { \scriptsize
> \begin{verbbox}
> 1 rcu_read_lock();
> @@ -640,8 +640,8 @@ dereferences are protected by RCU.
> \centering
> \theverbbox
> \caption{Diverse RCU Read-Side Nesting}
> -\label{fig:defer:Diverse RCU Read-Side Nesting}
> -\end{figure}
> +\label{lst:defer:Diverse RCU Read-Side Nesting}
> +\end{listing}
>
> Is the \co{rcu_dereference()} primitive in an RCU Classic
> or an RCU Sched critical section?
> diff --git a/defer/rcufundamental.tex b/defer/rcufundamental.tex
> index 27193aa..a500f51 100644
> --- a/defer/rcufundamental.tex
> +++ b/defer/rcufundamental.tex
> @@ -68,7 +68,7 @@ summarizes RCU fundamentals.
> \subsubsection{Publish-Subscribe Mechanism}
> \label{sec:defer:Publish-Subscribe Mechanism}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct foo {
> @@ -90,8 +90,8 @@ summarizes RCU fundamentals.
> \centering
> \theverbbox
> \caption{Data Structure Publication (Unsafe)}
> -\label{fig:defer:Data Structure Publication (Unsafe)}
> -\end{figure}
> +\label{lst:defer:Data Structure Publication (Unsafe)}
> +\end{listing}
>
> One key attribute of RCU is the ability to safely scan data, even
> though that data is being modified concurrently.
> @@ -101,7 +101,7 @@ For example, consider an initially \co{NULL} global pointer
> \co{gp} that is to be modified to point to a newly allocated
> and initialized data structure.
> The code fragment shown in
> -Figure~\ref{fig:defer:Data Structure Publication (Unsafe)}
> +Listing~\ref{lst:defer:Data Structure Publication (Unsafe)}
> (with the addition of appropriate locking)
> might be used for this purpose.
>
> @@ -239,7 +239,7 @@ This notation is cumbersome, and will therefore be abbreviated as shown in
> Figure~\ref{fig:defer:Linux Linked List Abbreviated},
> which shows only the non-header (blue) elements.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct foo {
> @@ -262,12 +262,12 @@ which shows only the non-header (blue) elements.
> \centering
> \theverbbox
> \caption{RCU Data Structure Publication}
> -\label{fig:defer:RCU Data Structure Publication}
> -\end{figure}
> +\label{lst:defer:RCU Data Structure Publication}
> +\end{listing}
>
> Adapting the pointer-publish example for the linked list results in
> the code shown in
> -Figure~\ref{fig:defer:RCU Data Structure Publication}.
> +Listing~\ref{lst:defer:RCU Data Structure Publication}.
>
> Line~15 must be protected by some synchronization mechanism (most
> commonly some sort of lock) to prevent multiple \co{list_add_rcu()}
> @@ -330,7 +330,7 @@ As before, this notation is cumbersome, so hlists will be abbreviated
> in the same way lists are, as shown in
> Figure~\ref{fig:defer:Linux Linked List Abbreviated}.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct foo {
> @@ -353,12 +353,12 @@ Figure~\ref{fig:defer:Linux Linked List Abbreviated}.
> \centering
> \theverbbox
> \caption{RCU {\tt hlist} Publication}
> -\label{fig:defer:RCU hlist Publication}
> -\end{figure}
> +\label{lst:defer:RCU hlist Publication}
> +\end{listing}
>
> Publishing a new element to an RCU-protected hlist is quite similar
> to doing so for the circular list,
> -as shown in Figure~\ref{fig:defer:RCU hlist Publication}.
> +as shown in Listing~\ref{lst:defer:RCU hlist Publication}.
>
> As before, line~15 must be protected by some sort of synchronization
> mechanism, for example, a lock.
> @@ -485,7 +485,7 @@ RCU to wait for readers:
> \item Clean up, for example, free the element that was replaced above.
> \end{enumerate}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct foo {
> @@ -514,11 +514,11 @@ RCU to wait for readers:
> \centering
> \theverbbox
> \caption{Canonical RCU Replacement Example}
> -\label{fig:defer:Canonical RCU Replacement Example}
> -\end{figure}
> +\label{lst:defer:Canonical RCU Replacement Example}
> +\end{listing}
>
> The code fragment shown in
> -Figure~\ref{fig:defer:Canonical RCU Replacement Example},
> +Listing~\ref{lst:defer:Canonical RCU Replacement Example},
> adapted from those in Section~\ref{sec:defer:Publish-Subscribe Mechanism},
> demonstrates this process, with field \co{a} being the search key.
>
> @@ -560,7 +560,7 @@ but now with the benefit of a firm understanding of the fundamental
> concepts underlying RCU.
> To begin this new version of the deletion example,
> we will modify lines~11-21 in
> -Figure~\ref{fig:defer:Canonical RCU Replacement Example}
> +Listing~\ref{lst:defer:Canonical RCU Replacement Example}
> to read as follows:
>
> \vspace{5pt}
> @@ -641,7 +641,7 @@ The following example covers replacement.
> To start the replacement example,
> here are the last few lines of the
> example shown in
> -Figure~\ref{fig:defer:Canonical RCU Replacement Example}:
> +Listing~\ref{lst:defer:Canonical RCU Replacement Example}:
>
> \vspace{5pt}
> \begin{minipage}[t]{\columnwidth}
> @@ -745,9 +745,9 @@ versions of the list active at a given time.
> versions of the list to be active?
> \QuickQuizAnswer{
> One way of accomplishing this is as shown in
> - Figure~\ref{fig:defer:Concurrent RCU Deletion}.
> + Listing~\ref{lst:defer:Concurrent RCU Deletion}.
>
> -\begin{figure}[htbp]
> +\begin{listing}[htbp]
> {
> \begin{verbbox}
> 1 spin_lock(&mylock);
> @@ -765,8 +765,8 @@ versions of the list active at a given time.
> \centering
> \theverbbox
> \caption{Concurrent RCU Deletion}
> -\label{fig:defer:Concurrent RCU Deletion}
> -\end{figure}
> +\label{lst:defer:Concurrent RCU Deletion}
> +\end{listing}
>
> Note that this means that multiple concurrent deletions might be
> waiting in \co{synchronize_rcu()}.
> @@ -784,7 +784,7 @@ versions of the list active at a given time.
> \co{list_replace_rcu()} were protected by a lock, so that
> the \co{synchronize_rcu()} was outside of that lock, similar
> to the code shown in
> - Figure~\ref{fig:defer:Concurrent RCU Deletion}.
> + Listing~\ref{lst:defer:Concurrent RCU Deletion}.
> Suppose further that a large number of threads undertook an
> RCU replacement at about the same time, and that readers
> are also constantly traversing the data structure.
> diff --git a/defer/rcuusage.tex b/defer/rcuusage.tex
> index 74be9fc..9ad1a1e 100644
> --- a/defer/rcuusage.tex
> +++ b/defer/rcuusage.tex
> @@ -41,7 +41,7 @@ Section~\ref{sec:defer:RCU Usage Summary} provides a summary.
> \subsubsection{RCU for Pre-BSD Routing}
> \label{sec:defer:RCU for Pre-BSD Routing}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct route_entry {
> @@ -78,10 +78,10 @@ Section~\ref{sec:defer:RCU Usage Summary} provides a summary.
> \centering
> \theverbbox
> \caption{RCU Pre-BSD Routing Table Lookup}
> -\label{fig:defer:RCU Pre-BSD Routing Table Lookup}
> -\end{figure}
> +\label{lst:defer:RCU Pre-BSD Routing Table Lookup}
> +\end{listing}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int route_add(unsigned long addr,
> @@ -132,22 +132,22 @@ Section~\ref{sec:defer:RCU Usage Summary} provides a summary.
> \centering
> \theverbbox
> \caption{RCU Pre-BSD Routing Table Add/Delete}
> -\label{fig:defer:RCU Pre-BSD Routing Table Add/Delete}
> -\end{figure}
> +\label{lst:defer:RCU Pre-BSD Routing Table Add/Delete}
> +\end{listing}
>
> -Figures~\ref{fig:defer:RCU Pre-BSD Routing Table Lookup}
> -and~\ref{fig:defer:RCU Pre-BSD Routing Table Add/Delete}
> +Listings~\ref{lst:defer:RCU Pre-BSD Routing Table Lookup}
> +and~\ref{lst:defer:RCU Pre-BSD Routing Table Add/Delete}
> show code for an RCU-protected Pre-BSD routing table
> (\path{route_rcu.c}).
> The former shows data structures and \co{route_lookup()},
> and the latter shows \co{route_add()} and \co{route_del()}.
>
> -In Figure~\ref{fig:defer:RCU Pre-BSD Routing Table Lookup},
> +In Listing~\ref{lst:defer:RCU Pre-BSD Routing Table Lookup},
> line~2 adds the \co{->rh} field used by RCU reclamation,
> line~6 adds the \co{->re_freed} use-after-free-check field,
> lines~16, 17, 23, and~27 add RCU read-side protection,
> and lines~21 and~22 add the use-after-free check.
> -In Figure~\ref{fig:defer:RCU Pre-BSD Routing Table Add/Delete},
> +In Listing~\ref{lst:defer:RCU Pre-BSD Routing Table Add/Delete},
> lines~12, 14, 31, 36, and~41 add update-side locking,
> lines~13 and~35 add RCU update-side protection,
> line~37 causes \co{route_cb()} to be invoked after a grace period elapses,
> @@ -596,14 +596,14 @@ situations.
>
> In the best case, the conversion from reader-writer locking to RCU
> is quite simple, as shown in
> -Figures~\ref{fig:defer:Converting Reader-Writer Locking to RCU: Data},
> -\ref{fig:defer:Converting Reader-Writer Locking to RCU: Search},
> +Listings~\ref{lst:defer:Converting Reader-Writer Locking to RCU: Data},
> +\ref{lst:defer:Converting Reader-Writer Locking to RCU: Search},
> and
> -\ref{fig:defer:Converting Reader-Writer Locking to RCU: Deletion},
> +\ref{lst:defer:Converting Reader-Writer Locking to RCU: Deletion},
> all taken from
> Wikipedia~\cite{WikipediaRCU}.
>
> -\begin{figure*}[htbp]
> +\begin{listing*}[htbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct el { 1 struct el {
> @@ -620,10 +620,10 @@ Wikipedia~\cite{WikipediaRCU}.
> \hspace*{0.9in}\OneColumnHSpace{-0.5in}
> \theverbbox
> \caption{Converting Reader-Writer Locking to RCU: Data}
> -\label{fig:defer:Converting Reader-Writer Locking to RCU: Data}
> -\end{figure*}
> +\label{lst:defer:Converting Reader-Writer Locking to RCU: Data}
> +\end{listing*}
>
> -\begin{figure*}[htbp]
> +\begin{listing*}[htbp]
> { \scriptsize
> \begin{verbbox}
> 1 int search(long key, int *result) 1 int search(long key, int *result)
> @@ -646,10 +646,10 @@ Wikipedia~\cite{WikipediaRCU}.
> \hspace*{0.9in}\OneColumnHSpace{-0.5in}
> \theverbbox
> \caption{Converting Reader-Writer Locking to RCU: Search}
> -\label{fig:defer:Converting Reader-Writer Locking to RCU: Search}
> -\end{figure*}
> +\label{lst:defer:Converting Reader-Writer Locking to RCU: Search}
> +\end{listing*}
>
> -\begin{figure*}[htbp]
> +\begin{listing*}[htbp]
> { \scriptsize
> \begin{verbbox}
> 1 int delete(long key) 1 int delete(long key)
> @@ -674,8 +674,8 @@ Wikipedia~\cite{WikipediaRCU}.
> \hspace*{0.9in}\OneColumnHSpace{-0.5in}
> \theverbbox
> \caption{Converting Reader-Writer Locking to RCU: Deletion}
> -\label{fig:defer:Converting Reader-Writer Locking to RCU: Deletion}
> -\end{figure*}
> +\label{lst:defer:Converting Reader-Writer Locking to RCU: Deletion}
> +\end{listing*}
>
> More-elaborate cases of replacing reader-writer locking with RCU
> are beyond the scope of this document.
> @@ -874,7 +874,7 @@ within an RCU read-side critical section, that data element is
> guaranteed to remain in existence for the duration of that RCU
> read-side critical section.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int delete(int key)
> @@ -907,10 +907,10 @@ read-side critical section.
> \centering
> \theverbbox
> \caption{Existence Guarantees Enable Per-Element Locking}
> -\label{fig:defer:Existence Guarantees Enable Per-Element Locking}
> -\end{figure}
> +\label{lst:defer:Existence Guarantees Enable Per-Element Locking}
> +\end{listing}
>
> -Figure~\ref{fig:defer:Existence Guarantees Enable Per-Element Locking}
> +Listing~\ref{lst:defer:Existence Guarantees Enable Per-Element Locking}
> demonstrates how RCU-based existence guarantees can enable
> per-element locking via a function that deletes an element from
> a hash table.
> @@ -924,10 +924,10 @@ indicates failure.
> \QuickQuiz{}
> What if the element we need to delete is not the first element
> of the list on line~9 of
> - Figure~\ref{fig:defer:Existence Guarantees Enable Per-Element Locking}?
> + Listing~\ref{lst:defer:Existence Guarantees Enable Per-Element Locking}?
> \QuickQuizAnswer{
> As with
> - Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees},
> + Listing~\ref{lst:locking:Per-Element Locking Without Existence Guarantees},
> this is a very simple hash table with no chaining, so the only
> element in a given bucket is the first element.
> The reader is again invited to adapt this example to a hash table with
> @@ -948,7 +948,7 @@ and line~24 indicates failure to delete the specified key.
> \QuickQuiz{}
> Why is it OK to exit the RCU read-side critical section on
> line~15 of
> - Figure~\ref{fig:defer:Existence Guarantees Enable Per-Element Locking}
> + Listing~\ref{lst:defer:Existence Guarantees Enable Per-Element Locking}
> before releasing the lock on line~17?
> \QuickQuizAnswer{
> First, please note that the second check on line~14 is
> @@ -973,7 +973,7 @@ and line~24 indicates failure to delete the specified key.
> \QuickQuiz{}
> Why not exit the RCU read-side critical section on
> line~23 of
> - Figure~\ref{fig:defer:Existence Guarantees Enable Per-Element Locking}
> + Listing~\ref{lst:defer:Existence Guarantees Enable Per-Element Locking}
> before releasing the lock on line~22?
> \QuickQuizAnswer{
> Suppose we reverse the order of these two lines.
> @@ -1122,9 +1122,9 @@ In this example, the \co{timer_stop} function uses
> \co{synchronize_sched()} to ensure that all in-flight NMI
> notifications have completed before freeing the associated resources.
> A simplified version of this code is shown
> -Figure~\ref{fig:defer:Using RCU to Wait for NMIs to Finish}.
> +Listing~\ref{lst:defer:Using RCU to Wait for NMIs to Finish}.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct profile_buffer {
> @@ -1159,8 +1159,8 @@ Figure~\ref{fig:defer:Using RCU to Wait for NMIs to Finish}.
> \centering
> \theverbbox
> \caption{Using RCU to Wait for NMIs to Finish}
> -\label{fig:defer:Using RCU to Wait for NMIs to Finish}
> -\end{figure}
> +\label{lst:defer:Using RCU to Wait for NMIs to Finish}
> +\end{listing}
>
> Lines~1-4 define a \co{profile_buffer} structure, containing a
> size and an indefinite array of entries.
> @@ -1213,9 +1213,9 @@ It is therefore safe to free the buffer, in this case using the
> in \co{nmi_profile()}, and to replace the
> \co{synchronize_sched()} with \co{synchronize_rcu()},
> perhaps as shown in
> - Figure~\ref{fig:defer:Using RCU to Wait for Mythical Preemptible NMIs to Finish}.
> + Listing~\ref{lst:defer:Using RCU to Wait for Mythical Preemptible NMIs to Finish}.
> %
> -\begin{figure}[tb]
> +\begin{listing}[tb]
> {\scriptsize
> \begin{verbbox}
> 1 struct profile_buffer {
> @@ -1257,8 +1257,8 @@ It is therefore safe to free the buffer, in this case using the
> \centering
> \theverbbox
> \caption{Using RCU to Wait for Mythical Preemptible NMIs to Finish}
> -\label{fig:defer:Using RCU to Wait for Mythical Preemptible NMIs to Finish}
> -\end{figure}
> +\label{lst:defer:Using RCU to Wait for Mythical Preemptible NMIs to Finish}
> +\end{listing}
> %
> } \QuickQuizEnd
>
> diff --git a/defer/refcnt.tex b/defer/refcnt.tex
> index 942f529..ebf9111 100644
> --- a/defer/refcnt.tex
> +++ b/defer/refcnt.tex
> @@ -3,7 +3,7 @@
> \section{Reference Counting}
> \label{sec:defer:Reference Counting}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct route_entry { /* BUGGY!!! */
> @@ -61,10 +61,10 @@
> \centering
> \theverbbox
> \caption{Reference-Counted Pre-BSD Routing Table Lookup (BUGGY!!!)}
> -\label{fig:defer:Reference-Counted Pre-BSD Routing Table Lookup}
> -\end{figure}
> +\label{lst:defer:Reference-Counted Pre-BSD Routing Table Lookup}
> +\end{listing}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int route_add(unsigned long addr, /* BUGGY!!! */
> @@ -114,8 +114,8 @@
> \centering
> \theverbbox
> \caption{Reference-Counted Pre-BSD Routing Table Add/Delete (BUGGY!!!)}
> -\label{fig:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> -\end{figure}
> +\label{lst:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> +\end{listing}
>
> Reference counting tracks the number of references to a given object in
> order to prevent that object from being prematurely freed.
> @@ -133,18 +133,18 @@ Reference counting is thus an excellent candidate for a concurrent
> implementation of Pre-BSD routing.
>
> To that end,
> -Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Lookup}
> +Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Lookup}
> shows data structures and the \co{route_lookup()} function and
> -Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> +Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> shows the \co{route_add()} and \co{route_del()} functions
> (all at \path{route_refcnt.c}).
> Since these algorithms are quite similar to the sequential algorithm
> shown in
> -Figure~\ref{fig:defer:Sequential Pre-BSD Routing Table},
> +Listing~\ref{lst:defer:Sequential Pre-BSD Routing Table},
> only the differences will be discussed.
>
> Starting with
> -Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Lookup},
> +Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Lookup},
> line~2 adds the actual reference counter, line~6 adds a \co{->re_freed}
> use-after-free check field, line~9 adds the \co{routelock} that will
> be used to synchronize concurrent updates,
> @@ -174,7 +174,7 @@ and~37 performing the use-after-free check.
> of increasing the probability of finding bugs.
> } \QuickQuizEnd
>
> -In Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Add/Delete},
> +In Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Add/Delete},
> lines~12, 16, 25, 33, and~40 introduce locking to synchronize
> concurrent updates.
> Line~14 initializes the \co{->re_freed} use-after-free-check field,
> @@ -183,7 +183,7 @@ the reference count is zero.
>
> \QuickQuiz{}
> Why doesn't \co{route_del()} in
> - Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> + Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> use reference counts to
> protect the traversal to the element to be freed?
> \QuickQuizAnswer{
> @@ -203,7 +203,7 @@ shows the performance and scalability of reference counting on a
> read-only workload with a ten-element list running on a
> single-socket four-core hyperthreaded 2.5\,GHz x86 system.
> The ``ideal'' trace was generated by running the sequential code shown in
> -Figure~\ref{fig:defer:Sequential Pre-BSD Routing Table},
> +Listing~\ref{lst:defer:Sequential Pre-BSD Routing Table},
> which works only because this is a read-only workload.
> The reference-counting performance is abysmal and its scalability even
> more so, with the ``refcnt'' trace dropping down onto the x-axis.
> @@ -250,7 +250,7 @@ But it gets worse.
> Running multiple updater threads repeatedly invoking
> \co{route_add()} and \co{route_del()} will quickly encounter the
> \co{abort()} statement on line~37 of
> -Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Lookup},
> +Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Lookup},
> which indicates a use-after-free bug.
> This in turn means that the reference counts are not only profoundly
> degrading scalability and performance, but also failing to provide
> @@ -263,11 +263,11 @@ Figure~\ref{fig:defer:Pre-BSD Packet Routing List}:
> \begin{enumerate}
> \item Thread~A looks up address~42, reaching line~33 of
> \co{route_lookup()} in
> - Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Lookup}.
> + Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Lookup}.
> In other words, Thread~A has a pointer to the first element,
> but has not yet acquired a reference to it.
> \item Thread~B invokes \co{route_del()} in
> - Figure~\ref{fig:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> + Listing~\ref{lst:defer:Reference-Counted Pre-BSD Routing Table Add/Delete}
> to delete the route entry for address~42.
> It completes successfully, and because this entry's \co{->re_refcnt}
> field was equal to the value one, it invokes
> diff --git a/defer/seqlock.tex b/defer/seqlock.tex
> index cb5e4e6..e537628 100644
> --- a/defer/seqlock.tex
> +++ b/defer/seqlock.tex
> @@ -47,7 +47,7 @@ very rarely need to retry.
> a lock.
> } \QuickQuizEnd
>
> -\begin{figure}[bp]
> +\begin{listing}[bp]
> { \scriptsize
> \begin{verbbox}
> 1 do {
> @@ -59,10 +59,10 @@ very rarely need to retry.
> \centering
> \theverbbox
> \caption{Sequence-Locking Reader}
> -\label{fig:defer:Sequence-Locking Reader}
> -\end{figure}
> +\label{lst:defer:Sequence-Locking Reader}
> +\end{listing}
>
> -\begin{figure}[bp]
> +\begin{listing}[bp]
> { \scriptsize
> \begin{verbbox}
> 1 write_seqlock(&test_seqlock);
> @@ -73,8 +73,8 @@ very rarely need to retry.
> \centering
> \theverbbox
> \caption{Sequence-Locking Writer}
> -\label{fig:defer:Sequence-Locking Writer}
> -\end{figure}
> +\label{lst:defer:Sequence-Locking Writer}
> +\end{listing}
>
> The key component of sequence locking is the sequence number, which has
> an even value in the absence of updaters and an odd value if there
> @@ -84,12 +84,12 @@ If either snapshot has an odd value, or if the two snapshots differ,
> there has been a concurrent update, and the reader must discard
> the results of the access and then retry it.
> Readers therefore use the \co{read_seqbegin()} and \co{read_seqretry()}
> -functions shown in Figure~\ref{fig:defer:Sequence-Locking Reader}
> +functions shown in Listing~\ref{lst:defer:Sequence-Locking Reader}
> when accessing data protected by a sequence lock.
> Writers must increment the value before and after each update,
> and only one writer is permitted at a given time.
> Writers therefore use the \co{write_seqlock()} and \co{write_sequnlock()}
> -functions shown in Figure~\ref{fig:defer:Sequence-Locking Writer}
> +functions shown in Listing~\ref{lst:defer:Sequence-Locking Writer}
> when updating data protected by a sequence lock.
>
> As a result, sequence-lock-protected data can have an arbitrarily
> @@ -98,7 +98,7 @@ Sequence locking is used in the Linux kernel to protect calibration
> quantities used for timekeeping.
> It is also used in pathname traversal to detect concurrent rename operations.
>
> -\begin{figure}[tb]
> +\begin{listing}[tb]
> { \scriptsize
> \begin{verbbox}
> 1 typedef struct {
> @@ -149,11 +149,11 @@ It is also used in pathname traversal to detect concurrent rename operations.
> \centering
> \theverbbox
> \caption{Sequence-Locking Implementation}
> -\label{fig:defer:Sequence-Locking Implementation}
> -\end{figure}
> +\label{lst:defer:Sequence-Locking Implementation}
> +\end{listing}
>
> A simple implementation of sequence locks is shown in
> -Figure~\ref{fig:defer:Sequence-Locking Implementation}
> +Listing~\ref{lst:defer:Sequence-Locking Implementation}
> (\path{seqlock.h}).
> The \co{seqlock_t} data structure is shown on lines~1-4, and contains
> the sequence number along with a lock to serialize writers.
> @@ -170,7 +170,7 @@ will pass to a later call to \co{read_seqretry()}.
>
> \QuickQuiz{}
> Why not have \co{read_seqbegin()} in
> - Figure~\ref{fig:defer:Sequence-Locking Implementation}
> + Listing~\ref{lst:defer:Sequence-Locking Implementation}
> check for the low-order bit being set, and retry
> internally, rather than allowing a doomed read to start?
> \QuickQuizAnswer{
> @@ -193,7 +193,7 @@ in other words, that there has been no writer, and returns true if so.
>
> \QuickQuiz{}
> Why is the \co{smp_mb()} on line~26 of
> - Figure~\ref{fig:defer:Sequence-Locking Implementation}
> + Listing~\ref{lst:defer:Sequence-Locking Implementation}
> needed?
> \QuickQuizAnswer{
> If it was omitted, both the compiler and the CPU would be
> @@ -206,7 +206,7 @@ in other words, that there has been no writer, and returns true if so.
>
> \QuickQuiz{}
> Can't weaker memory barriers be used in the code in
> - Figure~\ref{fig:defer:Sequence-Locking Implementation}?
> + Listing~\ref{lst:defer:Sequence-Locking Implementation}?
> \QuickQuizAnswer{
> In older versions of the Linux kernel, no.
>
> @@ -247,7 +247,7 @@ increment of the sequence number on line~44, then releases the lock.
>
> \QuickQuiz{}
> Why isn't \co{seq} on line~2 of
> - Figure~\ref{fig:defer:Sequence-Locking Implementation}
> + Listing~\ref{lst:defer:Sequence-Locking Implementation}
> \co{unsigned} rather than \co{unsigned long}?
> After all, if \co{unsigned} is good enough for the Linux
> kernel, shouldn't it be good enough for everyone?
> @@ -287,7 +287,7 @@ increment of the sequence number on line~44, then releases the lock.
> that is 64 bits on 64-bit systems.
> } \QuickQuizEnd
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct route_entry {
> @@ -330,10 +330,10 @@ increment of the sequence number on line~44, then releases the lock.
> \centering
> \theverbbox
> \caption{Sequence-Locked Pre-BSD Routing Table Lookup (BUGGY!!!)}
> -\label{fig:defer:Sequence-Locked Pre-BSD Routing Table Lookup}
> -\end{figure}
> +\label{lst:defer:Sequence-Locked Pre-BSD Routing Table Lookup}
> +\end{listing}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int route_add(unsigned long addr,
> @@ -383,20 +383,20 @@ increment of the sequence number on line~44, then releases the lock.
> \centering
> \theverbbox
> \caption{Sequence-Locked Pre-BSD Routing Table Add/Delete (BUGGY!!!)}
> -\label{fig:defer:Sequence-Locked Pre-BSD Routing Table Add/Delete}
> -\end{figure}
> +\label{lst:defer:Sequence-Locked Pre-BSD Routing Table Add/Delete}
> +\end{listing}
>
> So what happens when sequence locking is applied to the Pre-BSD
> routing table?
> -Figure~\ref{fig:defer:Sequence-Locked Pre-BSD Routing Table Lookup}
> +Listing~\ref{lst:defer:Sequence-Locked Pre-BSD Routing Table Lookup}
> shows the data structures and \co{route_lookup()}, and
> -Figure~\ref{fig:defer:Sequence-Locked Pre-BSD Routing Table Add/Delete}
> +Listing~\ref{lst:defer:Sequence-Locked Pre-BSD Routing Table Add/Delete}
> shows \co{route_add()} and \co{route_del()} (\path{route_seqlock.c}).
> This implementation is once again similar to its counterparts in earlier
> sections, so only the differences will be highlighted.
>
> In
> -Figure~\ref{fig:defer:Sequence-Locked Pre-BSD Routing Table Lookup},
> +Listing~\ref{lst:defer:Sequence-Locked Pre-BSD Routing Table Lookup},
> line~5 adds \co{->re_freed}, which is checked on lines~29 and~30.
> Line~8 adds a sequence lock, which is used by \co{route_lookup()}
> on lines~18, 23, and~32, with lines~24 and~33 branching back to
> @@ -404,7 +404,7 @@ the \co{retry} label on line~17.
> The effect is to retry any lookup that runs concurrently with an update.
>
> In
> -Figure~\ref{fig:defer:Sequence-Locked Pre-BSD Routing Table Add/Delete},
> +Listing~\ref{lst:defer:Sequence-Locked Pre-BSD Routing Table Add/Delete},
> lines~12, 15, 24, and~40 acquire and release the sequence lock,
> while lines~11, 33, and~44 handle \co{->re_freed}.
> This implementation is therefore quite straightforward.
> diff --git a/locking/locking-existence.tex b/locking/locking-existence.tex
> index 7629c1c..9fcbbf9 100644
> --- a/locking/locking-existence.tex
> +++ b/locking/locking-existence.tex
> @@ -3,7 +3,7 @@
> \section{Lock-Based Existence Guarantees}
> \label{sec:locking:Lock-Based Existence Guarantees}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int delete(int key)
> @@ -26,8 +26,8 @@
> \centering
> \theverbbox
> \caption{Per-Element Locking Without Existence Guarantees}
> -\label{fig:locking:Per-Element Locking Without Existence Guarantees}
> -\end{figure}
> +\label{lst:locking:Per-Element Locking Without Existence Guarantees}
> +\end{listing}
>
> A key challenge in parallel programming is to provide
> \emph{existence guarantees}~\cite{Gamsa99},
> @@ -95,12 +95,12 @@ structure.
> Unfortunately, putting the lock that is to protect a data element
> in the data element itself is subject to subtle race conditions,
> as shown in
> -Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees}.
> +Listing~\ref{lst:locking:Per-Element Locking Without Existence Guarantees}.
>
> \QuickQuiz{}
> What if the element we need to delete is not the first element
> of the list on line~8 of
> - Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees}?
> + Listing~\ref{lst:locking:Per-Element Locking Without Existence Guarantees}?
> \QuickQuizAnswer{
> This is a very simple hash table with no chaining, so the only
> element in a given bucket is the first element.
> @@ -110,7 +110,7 @@ Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees}.
>
> \QuickQuiz{}
> What race condition can occur in
> - Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees}?
> + Listing~\ref{lst:locking:Per-Element Locking Without Existence Guarantees}?
> \QuickQuizAnswer{
> Consider the following sequence of events:
> \begin{enumerate}
> @@ -134,7 +134,7 @@ Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees}.
> that element's lock on line~10!
> } \QuickQuizEnd
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 int delete(int key)
> @@ -161,12 +161,12 @@ Figure~\ref{fig:locking:Per-Element Locking Without Existence Guarantees}.
> \centering
> \theverbbox
> \caption{Per-Element Locking With Lock-Based Existence Guarantees}
> -\label{fig:locking:Per-Element Locking With Lock-Based Existence Guarantees}
> -\end{figure}
> +\label{lst:locking:Per-Element Locking With Lock-Based Existence Guarantees}
> +\end{listing}
>
> One way to fix this example is to use a hashed set of global locks, so
> that each hash bucket has its own lock, as shown in
> -Figure~\ref{fig:locking:Per-Element Locking With Lock-Based Existence Guarantees}.
> +Listing~\ref{lst:locking:Per-Element Locking With Lock-Based Existence Guarantees}.
> This approach allows acquiring the proper lock (on line~9) before
> gaining a pointer to the data element (on line~10).
> Although this approach works quite well for elements contained in a
> diff --git a/locking/locking.tex b/locking/locking.tex
> index 562ff09..0737f85 100644
> --- a/locking/locking.tex
> +++ b/locking/locking.tex
> @@ -358,7 +358,7 @@ we therefore have three layers to the global deadlock hierarchy, the
> first containing Locks~A and B, the second containing Lock~C, and
> the third containing Lock~D.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct locked_list {
> @@ -389,8 +389,8 @@ the third containing Lock~D.
> \centering
> \theverbbox
> \caption{Concurrent List Iterator}
> -\label{fig:locking:Concurrent List Iterator}
> -\end{figure}
> +\label{lst:locking:Concurrent List Iterator}
> +\end{listing}
>
> Please note that it is not typically possible to mechanically
> change \co{cmp()} to use the new Lock~D.
> @@ -401,14 +401,14 @@ a small price to pay in order to avoid deadlock.
>
> For another example where releasing all locks before invoking unknown
> code is impractical, imagine an iterator over a linked list, as shown in
> -Figure~\ref{fig:locking:Concurrent List Iterator} (\path{locked_list.c}).
> +Listing~\ref{lst:locking:Concurrent List Iterator} (\path{locked_list.c}).
> The \co{list_start()} function acquires a lock on the list and returns
> the first element (if there is one), and
> \co{list_next()} either returns a pointer to the next element in the list
> or releases the lock and returns \co{NULL} if the end of the list has
> been reached.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 struct list_ints {
> @@ -433,10 +433,10 @@ been reached.
> \centering
> \theverbbox
> \caption{Concurrent List Iterator Usage}
> -\label{fig:locking:Concurrent List Iterator Usage}
> -\end{figure}
> +\label{lst:locking:Concurrent List Iterator Usage}
> +\end{listing}
>
> -Figure~\ref{fig:locking:Concurrent List Iterator Usage} shows how
> +Listing~\ref{lst:locking:Concurrent List Iterator Usage} shows how
> this list iterator may be used.
> Lines~1-4 define the \co{list_ints} element containing a single integer,
> and lines~6-17 show how to iterate over the list.
> @@ -513,7 +513,7 @@ this is unlikely.
> \subsubsection{Conditional Locking}
> \label{sec:locking:Conditional Locking}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 spin_lock(&lock2);
> @@ -528,8 +528,8 @@ this is unlikely.
> \centering
> \theverbbox
> \caption{Protocol Layering and Deadlock}
> -\label{fig:locking:Protocol Layering and Deadlock}
> -\end{figure}
> +\label{lst:locking:Protocol Layering and Deadlock}
> +\end{listing}
>
> But suppose that there is no reasonable locking hierarchy.
> This can happen in real life, for example, in layered network protocol stacks
> @@ -538,14 +538,14 @@ In the networking case, it might be necessary to hold the locks from
> both layers when passing a packet from one layer to another.
> Given that packets travel both up and down the protocol stack, this
> is an excellent recipe for deadlock, as illustrated in
> -Figure~\ref{fig:locking:Protocol Layering and Deadlock}.
> +Listing~\ref{lst:locking:Protocol Layering and Deadlock}.
> Here, a packet moving down the stack towards the wire must acquire
> the next layer's lock out of order.
> Given that packets moving up the stack away from the wire are acquiring
> -the locks in order, the lock acquisition in line~4 of the figure
> +the locks in order, the lock acquisition in line~4 of the listing
> can result in deadlock.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 retry:
> @@ -570,13 +570,13 @@ can result in deadlock.
> \centering
> \theverbbox
> \caption{Avoiding Deadlock Via Conditional Locking}
> -\label{fig:locking:Avoiding Deadlock Via Conditional Locking}
> -\end{figure}
> +\label{lst:locking:Avoiding Deadlock Via Conditional Locking}
> +\end{listing}
>
> One way to avoid deadlocks in this case is to impose a locking hierarchy,
> but when it is necessary to acquire a lock out of order, acquire it
> conditionally, as shown in
> -Figure~\ref{fig:locking:Avoiding Deadlock Via Conditional Locking}.
> +Listing~\ref{lst:locking:Avoiding Deadlock Via Conditional Locking}.
> Instead of unconditionally acquiring the layer-1 lock, line~5
> conditionally acquires the lock using the \co{spin_trylock()} primitive.
> This primitive acquires the lock immediately if the lock is available
> @@ -597,8 +597,8 @@ must release the locks and start over.
>
> \QuickQuiz{}
> Can the transformation from
> - Figure~\ref{fig:locking:Protocol Layering and Deadlock} to
> - Figure~\ref{fig:locking:Avoiding Deadlock Via Conditional Locking}
> + Listing~\ref{lst:locking:Protocol Layering and Deadlock} to
> + Listing~\ref{lst:locking:Avoiding Deadlock Via Conditional Locking}
> be applied universally?
> \QuickQuizAnswer{
> Absolutely not!
> @@ -613,7 +613,7 @@ must release the locks and start over.
>
> \QuickQuiz{}
> But the complexity in
> - Figure~\ref{fig:locking:Avoiding Deadlock Via Conditional Locking}
> + Listing~\ref{lst:locking:Avoiding Deadlock Via Conditional Locking}
> is well worthwhile given that it avoids deadlock, right?
> \QuickQuizAnswer{
> Maybe.
> @@ -836,7 +836,7 @@ quite useful in many settings.
> \subsection{Livelock and Starvation}
> \label{sec:locking:Livelock and Starvation}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 void thread1(void)
> @@ -871,13 +871,13 @@ quite useful in many settings.
> \centering
> \theverbbox
> \caption{Abusing Conditional Locking}
> -\label{fig:locking:Abusing Conditional Locking}
> -\end{figure}
> +\label{lst:locking:Abusing Conditional Locking}
> +\end{listing}
>
> Although conditional locking can be an effective deadlock-avoidance
> mechanism, it can be abused.
> Consider for example the beautifully symmetric example shown in
> -Figure~\ref{fig:locking:Abusing Conditional Locking}.
> +Listing~\ref{lst:locking:Abusing Conditional Locking}.
> This example's beauty hides an ugly livelock.
> To see this, consider the following sequence of events:
>
> @@ -899,10 +899,10 @@ To see this, consider the following sequence of events:
>
> \QuickQuiz{}
> How can the livelock shown in
> - Figure~\ref{fig:locking:Abusing Conditional Locking}
> + Listing~\ref{lst:locking:Abusing Conditional Locking}
> be avoided?
> \QuickQuizAnswer{
> - Figure~\ref{fig:locking:Avoiding Deadlock Via Conditional Locking}
> + Listing~\ref{lst:locking:Avoiding Deadlock Via Conditional Locking}
> provides some good hints.
> In many cases, livelocks are a hint that you should revisit your
> locking design.
> @@ -930,7 +930,7 @@ a group of threads starve, rather than just one of them.\footnote{
> forward progress is a problem that needs to be fixed, regardless
> of what name you choose for it.}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 void thread1(void)
> @@ -971,8 +971,8 @@ a group of threads starve, rather than just one of them.\footnote{
> \centering
> \theverbbox
> \caption{Conditional Locking and Exponential Backoff}
> -\label{fig:locking:Conditional Locking and Exponential Backoff}
> -\end{figure}
> +\label{lst:locking:Conditional Locking and Exponential Backoff}
> +\end{listing}
>
> Livelock and starvation are serious issues in software transactional
> memory implementations, and so the concept of \emph{contention
> @@ -981,11 +981,11 @@ In the case of locking, simple exponential backoff can often address
> livelock and starvation.
> The idea is to introduce exponentially increasing delays before each
> retry, as shown in
> -Figure~\ref{fig:locking:Conditional Locking and Exponential Backoff}.
> +Listing~\ref{lst:locking:Conditional Locking and Exponential Backoff}.
>
> \QuickQuiz{}
> What problems can you spot in the code in
> - Figure~\ref{fig:locking:Conditional Locking and Exponential Backoff}?
> + Listing~\ref{lst:locking:Conditional Locking and Exponential Backoff}?
> \QuickQuizAnswer{
> Here are a couple:
> \begin{enumerate}
> @@ -1509,7 +1509,7 @@ This acquire-then-release sequence continues until either the
> one of the attempts to acquire an \co{->fqslock} fails, or
> the root \co{rcu_node} structure's \co{->fqslock} as been acquired.
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 void force_quiescent_state(struct rcu_node *rnp_leaf)
> @@ -1539,11 +1539,11 @@ the root \co{rcu_node} structure's \co{->fqslock} as been acquired.
> \centering
> \theverbbox
> \caption{Conditional Locking to Reduce Contention}
> -\label{fig:locking:Conditional Locking to Reduce Contention}
> -\end{figure}
> +\label{lst:locking:Conditional Locking to Reduce Contention}
> +\end{listing}
>
> Simplified code to implement this is shown in
> -Figure~\ref{fig:locking:Conditional Locking to Reduce Contention}.
> +Listing~\ref{lst:locking:Conditional Locking to Reduce Contention}.
> The purpose of this function is to mediate between CPUs who have concurrently
> detected a need to invoke the \co{do_force_quiescent_state()} function.
> At any given time, it only makes sense for one instance of
> @@ -1578,7 +1578,7 @@ Either way, line~21 releases the root \co{rcu_node} structure's
>
> \QuickQuiz{}
> The code in
> - Figure~\ref{fig:locking:Conditional Locking to Reduce Contention}
> + Listing~\ref{lst:locking:Conditional Locking to Reduce Contention}
> is ridiculously complicated!
> Why not conditionally acquire a single global lock?
> \QuickQuizAnswer{
> @@ -1593,7 +1593,7 @@ Either way, line~21 releases the root \co{rcu_node} structure's
> \QuickQuiz{}
> Wait a minute!
> If we ``win'' the tournament on line~16 of
> - Figure~\ref{fig:locking:Conditional Locking to Reduce Contention},
> + Listing~\ref{lst:locking:Conditional Locking to Reduce Contention},
> we get to do all the work of \co{do_force_quiescent_state()}.
> Exactly how is that a win, really?
> \QuickQuizAnswer{
> @@ -1623,7 +1623,7 @@ environments.
> \subsection{Sample Exclusive-Locking Implementation Based on Atomic Exchange}
> \label{sec:locking:Sample Exclusive-Locking Implementation Based on Atomic Exchange}
>
> -\begin{figure}[tbp]
> +\begin{listing}[tbp]
> { \scriptsize
> \begin{verbbox}
> 1 typedef int xchglock_t;
> @@ -1646,11 +1646,11 @@ environments.
> \centering
> \theverbbox
> \caption{Sample Lock Based on Atomic Exchange}
> -\label{fig:locking:Sample Lock Based on Atomic Exchange}
> -\end{figure}
> +\label{lst:locking:Sample Lock Based on Atomic Exchange}
> +\end{listing}
>
> This section reviews the implementation shown in
> -Figure~\ref{fig:locking:Sample Lock Based on Atomic Exchange}.
> +Listing~\ref{lst:locking:Sample Lock Based on Atomic Exchange}.
> The data structure for this lock is just an \co{int}, as shown on
> line~1, but could be any integral type.
> The initial value of this lock is zero, meaning ``unlocked'',
> @@ -1660,7 +1660,7 @@ as shown on line~2.
> Why not rely on the C language's default initialization of
> zero instead of using the explicit initializer shown on
> line~2 of
> - Figure~\ref{fig:locking:Sample Lock Based on Atomic Exchange}?
> + Listing~\ref{lst:locking:Sample Lock Based on Atomic Exchange}?
> \QuickQuizAnswer{
> Because this default initialization does not apply to locks
> allocated as auto variables within the scope of a function.
> @@ -1678,7 +1678,7 @@ makes another attempt to acquire the lock.
>
> \QuickQuiz{}
> Why bother with the inner loop on lines~7-8 of
> - Figure~\ref{fig:locking:Sample Lock Based on Atomic Exchange}?
> + Listing~\ref{lst:locking:Sample Lock Based on Atomic Exchange}?
> Why not simply repeatedly do the atomic exchange operation
> on line~6?
> \QuickQuizAnswer{
> @@ -1700,7 +1700,7 @@ the lock, thus marking it as having been released.
>
> \QuickQuiz{}
> Why not simply store zero into the lock word on line~14 of
> - Figure~\ref{fig:locking:Sample Lock Based on Atomic Exchange}?
> + Listing~\ref{lst:locking:Sample Lock Based on Atomic Exchange}?
> \QuickQuizAnswer{
> This can be a legitimate implementation, but only if
> this store is preceded by a memory barrier and makes use
> --
> 2.7.4
>
next prev parent reply other threads:[~2017-10-11 22:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-11 22:07 [PATCH] Convert code snippets to 'listing' env (SMPdesign, locking, defer) Akira Yokosawa
2017-10-11 22:56 ` Paul E. McKenney [this message]
2017-10-11 23:19 ` Akira Yokosawa
2017-10-12 0:16 ` Paul E. McKenney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171011225621.GT3521@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=akiyks@gmail.com \
--cc=perfbook@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.