From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=Kcs2BpmGDwIqZBy2k9Y15wBtLGRfxn1zEW5mQIGvFdU=; b=JGClNIa57nQCoqAMFQmH73FsSHVDmehpfKBUD7NZCFNTUYQ7mrS3XgRQnXr1Z80o9/ ++VVLVcmRxJSJF1IpaC9UeUZzzeQSipUClGorpygeQmu1eF0t76Ff4zWDsCUcLsNTNrz PRL+aNbYoFXuQrSYoPvt2+0TRiLLaalDrkhvRqUJtbA4ttcfwvlqaVKBDDRwOKycM8AW OLiGATfpTmFJFBlJ8xilljXjpCowwKQCTl8L4JvSfk4rp4nFDO4k8X4VBzsC3hTzAey9 XmAJEvNsdPF6EVMcafHacVV57MIAPthGiFLTxB8ilbpZcIFrv3JznSBfsePvhDw6gt+R DWCQ== Subject: [PATCH 1/6] Rename environments 'linelabel' and 'lineref' References: From: Akira Yokosawa Message-ID: <4e1ae97b-3d87-e13b-8700-aecf2a3ac960@gmail.com> Date: Fri, 31 Jan 2020 07:33:10 +0900 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit To: "Paul E. McKenney" Cc: perfbook@vger.kernel.org, Akira Yokosawa List-ID: >From 25f6cd58afa619edfd088e4a935b10f7dddf450f Mon Sep 17 00:00:00 2001 From: Akira Yokosawa Date: Sat, 25 Jan 2020 15:56:47 +0900 Subject: [PATCH 1/6] Rename environments 'linelabel' and 'lineref' It turns out that the "lineno" package has variables \linelabel and \lineref as its parameters. The "fvextra" package, which enhances fancyvrb and enables (semi-) automatic line breaking in code snippets, requires the "lineno" package. This commit renames our custom environments of the same name to "fcvlabel" and "fcvref" for us to be able to make use of fvextra. Signed-off-by: Akira Yokosawa --- SMPdesign/SMPdesign.tex | 12 +- SMPdesign/beyond.tex | 44 ++-- SMPdesign/partexercises.tex | 32 +-- advsync/advsync.tex | 8 +- advsync/rt.tex | 40 ++-- appendix/questions/after.tex | 4 +- appendix/styleguide/samplecodesnippetfcv.tex | 4 +- appendix/styleguide/styleguide.tex | 52 ++-- appendix/toyrcu/toyrcu.tex | 128 +++++----- appendix/whymb/whymemorybarriers.tex | 16 +- count/count.tex | 200 ++++++++-------- datastruct/datastruct.tex | 80 +++---- debugging/debugging.tex | 12 +- defer/defer.tex | 16 +- defer/hazptr.tex | 20 +- defer/rcuapi.tex | 8 +- defer/rcufundamental.tex | 4 +- defer/rcuintro.tex | 4 +- defer/rcuusage.tex | 52 ++-- defer/refcnt.tex | 20 +- defer/seqlock.tex | 40 ++-- formal/axiomatic.tex | 40 ++-- formal/dyntickrcu.tex | 148 ++++++------ formal/ppcmem.tex | 24 +- formal/spinhint.tex | 44 ++-- future/formalregress.tex | 4 +- future/htm.tex | 28 +-- locking/locking-existence.tex | 20 +- locking/locking.tex | 76 +++--- memorder/memorder.tex | 240 +++++++++---------- owned/owned.tex | 12 +- perfbook.tex | 4 +- together/applyrcu.tex | 32 +-- together/refcnt.tex | 32 +-- toolsoftrade/toolsoftrade.tex | 184 +++++++------- utilities/checkfcv.pl | 8 +- utilities/fcvextract.pl | 10 +- 37 files changed, 851 insertions(+), 851 deletions(-) diff --git a/SMPdesign/SMPdesign.tex b/SMPdesign/SMPdesign.tex index 5fdf2a21..3c1fc41a 100644 --- a/SMPdesign/SMPdesign.tex +++ b/SMPdesign/SMPdesign.tex @@ -859,7 +859,7 @@ In this case, the simpler data-locking approach would be simpler and likely perform better. \begin{listing}[tb] -\begin{linelabel}[ln:SMPdesign:Hierarchical-Locking Hash Table Search] +\begin{fcvlabel}[ln:SMPdesign:Hierarchical-Locking Hash Table Search] \begin{VerbatimL}[commandchars=\\\[\]] struct hash_table { @@ -901,7 +901,7 @@ int hash_search(struct hash_table *h, long key) return 0; } \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Hierarchical-Locking Hash Table Search} \label{lst:SMPdesign:Hierarchical-Locking Hash Table Search} \end{listing} @@ -1020,7 +1020,7 @@ smaller than the number of non-\co{NULL} pointers. \subsubsection{Allocation Function} -\begin{lineref}[ln:SMPdesign:smpalloc:alloc] +\begin{fcvref}[ln:SMPdesign:smpalloc:alloc] The allocation function \co{memblock_alloc()} may be seen in Listing~\ref{lst:SMPdesign:Allocator-Cache Allocator Function}. Line~\lnref{pick} picks up the current thread's per-thread pool, @@ -1039,7 +1039,7 @@ In either case, line~\lnref{chk:notempty} checks for the per-thread pool still being empty, and if not, \clnrefrange{rem:b}{rem:e} remove a block and return it. Otherwise, line~\lnref{ret:NULL} tells the sad tale of memory exhaustion. -\end{lineref} +\end{fcvref} \begin{listing}[tbp] \input{CodeSamples/SMPdesign/smpalloc@alloc.fcv} @@ -1049,7 +1049,7 @@ Otherwise, line~\lnref{ret:NULL} tells the sad tale of memory exhaustion. \subsubsection{Free Function} -\begin{lineref}[ln:SMPdesign:smpalloc:free] +\begin{fcvref}[ln:SMPdesign:smpalloc:free] Listing~\ref{lst:SMPdesign:Allocator-Cache Free Function} shows the memory-block free function. Line~\lnref{get} gets a pointer to this thread's pool, and @@ -1065,7 +1065,7 @@ value. In either case, line~\lnref{place} then places the newly freed block into the per-thread pool. -\end{lineref} +\end{fcvref} \begin{listing}[tbp] \input{CodeSamples/SMPdesign/smpalloc@free.fcv} diff --git a/SMPdesign/beyond.tex b/SMPdesign/beyond.tex index cb0008c2..12e9237a 100644 --- a/SMPdesign/beyond.tex +++ b/SMPdesign/beyond.tex @@ -65,7 +65,7 @@ The maze is represented by a 2D array of cells and a linear-array-based work queue named \co{->visited}. \begin{listing}[tbp] -\begin{linelabel}[ln:SMPdesign:SEQ Pseudocode] +\begin{fcvlabel}[ln:SMPdesign:SEQ Pseudocode] \begin{VerbatimL}[commandchars=\\\@\$] int maze_solve(maze *mp, cell sc, cell ec) { @@ -90,12 +90,12 @@ int maze_solve(maze *mp, cell sc, cell ec) } \lnlbl@loop:e$ } \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{SEQ Pseudocode} \label{lst:SMPdesign:SEQ Pseudocode} \end{listing} -\begin{lineref}[ln:SMPdesign:SEQ Pseudocode] +\begin{fcvref}[ln:SMPdesign:SEQ Pseudocode] Line~\lnref{initcell} visits the initial cell, and each iteration of the loop spanning \clnrefrange{loop:b}{loop:e} traverses passages headed by one cell. The loop spanning @@ -104,10 +104,10 @@ visited cell with an unvisited neighbor, and the loop spanning \clnrefrange{loop3:b}{loop3:e} traverses one fork of the submaze headed by that neighbor. Line~\lnref{finalize} initializes for the next pass through the outer loop. -\end{lineref} +\end{fcvref} \begin{listing}[tbp] -\begin{linelabel}[ln:SMPdesign:SEQ Helper Pseudocode] +\begin{fcvlabel}[ln:SMPdesign:SEQ Helper Pseudocode] \begin{VerbatimL}[commandchars=\\\@\$] int maze_try_visit_cell(struct maze *mp, cell c, cell t, \lnlbl@try:b$ cell *n, int d) @@ -138,12 +138,12 @@ int maze_find_any_next_cell(struct maze *mp, cell c, \lnlbl@find:b$ return 0; \lnlbl@find:ret:false$ } \lnlbl@find:e$ \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{SEQ Helper Pseudocode} \label{lst:SMPdesign:SEQ Helper Pseudocode} \end{listing} -\begin{lineref}[ln:SMPdesign:SEQ Helper Pseudocode:try] +\begin{fcvref}[ln:SMPdesign:SEQ Helper Pseudocode:try] The pseudocode for \co{maze_try_visit_cell()} is shown on \clnrefrange{b}{e} of Listing~\ref{lst:SMPdesign:SEQ Helper Pseudocode} @@ -160,9 +160,9 @@ slot of the \co{->visited[]} array, line~\lnref{next:visited} indicates that this slot is now full, and line~\lnref{mark:visited} marks this cell as visited and also records the distance from the maze start. Line~\lnref{ret:success} then returns success. -\end{lineref} +\end{fcvref} -\begin{lineref}[ln:SMPdesign:SEQ Helper Pseudocode:find] +\begin{fcvref}[ln:SMPdesign:SEQ Helper Pseudocode:find] The pseudocode for \co{maze_find_any_next_cell()} is shown on \clnrefrange{b}{e} of Listing~\ref{lst:SMPdesign:SEQ Helper Pseudocode} @@ -177,7 +177,7 @@ return true if the corresponding cell is a candidate next cell. The \co{prevcol()}, \co{nextcol()}, \co{prevrow()}, and \co{nextrow()} each do the specified array-index-conversion operation. If none of the cells is a candidate, line~\lnref{ret:false} returns false. -\end{lineref} +\end{fcvref} \begin{figure}[tb] \centering @@ -204,18 +204,18 @@ consecutively decreasing cell numbers traverses the solution. The parallel work-queue solver is a straightforward parallelization of the algorithm shown in Listings~\ref{lst:SMPdesign:SEQ Pseudocode} and~\ref{lst:SMPdesign:SEQ Helper Pseudocode}. -\begin{lineref}[ln:SMPdesign:SEQ Pseudocode] +\begin{fcvref}[ln:SMPdesign:SEQ Pseudocode] \Clnref{ifge} of Listing~\ref{lst:SMPdesign:SEQ Pseudocode} must use fetch-and-add, and the local variable \co{vi} must be shared among the various threads. -\end{lineref} -\begin{lineref}[ln:SMPdesign:SEQ Helper Pseudocode:try] +\end{fcvref} +\begin{fcvref}[ln:SMPdesign:SEQ Helper Pseudocode:try] \Clnref{chk:not:visited,mark:visited} of Listing~\ref{lst:SMPdesign:SEQ Helper Pseudocode} must be combined into a CAS loop, with CAS failure indicating a loop in the maze. \Clnrefrange{recordnext}{next:visited} of this listing must use fetch-and-add to arbitrate concurrent attempts to record cells in the \co{->visited[]} array. -\end{lineref} +\end{fcvref} This approach does provide significant speedups on a dual-CPU Lenovo\mytexttrademark\ W500 @@ -251,7 +251,7 @@ at opposite ends of the solution path, and takes a brief look at the performance and scalability consequences. \begin{listing}[tbp] -\begin{linelabel}[ln:SMPdesign:Partitioned Parallel Solver Pseudocode] +\begin{fcvlabel}[ln:SMPdesign:Partitioned Parallel Solver Pseudocode] \begin{VerbatimL}[commandchars=\\\@\$] int maze_solve_child(maze *mp, cell *visited, cell sc) \lnlbl@b$ { @@ -279,12 +279,12 @@ int maze_solve_child(maze *mp, cell *visited, cell sc) \lnlbl@b$ return 1; } \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Partitioned Parallel Solver Pseudocode} \label{lst:SMPdesign:Partitioned Parallel Solver Pseudocode} \end{listing} -\begin{lineref}[ln:SMPdesign:Partitioned Parallel Solver Pseudocode] +\begin{fcvref}[ln:SMPdesign:Partitioned Parallel Solver Pseudocode] The partitioned parallel algorithm (PART), shown in Listing~\ref{lst:SMPdesign:Partitioned Parallel Solver Pseudocode} (\path{maze_part.c}), @@ -311,10 +311,10 @@ Finally, the \co{maze_find_any_next_cell()} function must use compare-and-swap to mark a cell as visited, however no constraints on ordering are required beyond those provided by thread creation and join. -\end{lineref} +\end{fcvref} \begin{listing}[tbp] -\begin{linelabel}[ln:SMPdesign:Partitioned Parallel Helper Pseudocode] +\begin{fcvlabel}[ln:SMPdesign:Partitioned Parallel Helper Pseudocode] \begin{VerbatimL}[commandchars=\\\@\$] int maze_try_visit_cell(struct maze *mp, int c, int t, int *n, int d) @@ -340,12 +340,12 @@ int maze_try_visit_cell(struct maze *mp, int c, int t, return 1; \lnlbl@ret:success$ } \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Partitioned Parallel Helper Pseudocode} \label{lst:SMPdesign:Partitioned Parallel Helper Pseudocode} \end{listing} -\begin{lineref}[ln:SMPdesign:Partitioned Parallel Helper Pseudocode] +\begin{fcvref}[ln:SMPdesign:Partitioned Parallel Helper Pseudocode] The pseudocode for \co{maze_find_any_next_cell()} is identical to that shown in Listing~\ref{lst:SMPdesign:SEQ Helper Pseudocode}, but the pseudocode for \co{maze_try_visit_cell()} differs, and @@ -364,7 +364,7 @@ that the solution has been located. Line~\lnref{update:new} updates to the new cell, lines~\lnref{update:visited:b} and~\lnref{update:visited:e} update this thread's visited array, and line~\lnref{ret:success} returns success. -\end{lineref} +\end{fcvref} \begin{figure}[tb] \centering diff --git a/SMPdesign/partexercises.tex b/SMPdesign/partexercises.tex index 2b8822a9..9cebe6b7 100644 --- a/SMPdesign/partexercises.tex +++ b/SMPdesign/partexercises.tex @@ -358,7 +358,7 @@ 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. -\begin{lineref}[ln:SMPdesign:lockhdeq:struct_pdeq] +\begin{fcvref}[ln:SMPdesign:lockhdeq:struct_pdeq] This data structure contains the left-hand lock on line~\lnref{llock}, the left-hand index on line~\lnref{lidx}, the right-hand lock on line~\lnref{rlock} (which is cache-aligned in the actual implementation), @@ -366,7 +366,7 @@ the right-hand index on line~\lnref{ridx}, and, finally, the hashed array of simple lock-based double-ended queues on line~\lnref{bkt}. A high-performance implementation would of course use padding or special alignment directives to avoid false sharing. -\end{lineref} +\end{fcvref} \begin{listing}[tbp] \input{CodeSamples/SMPdesign/lockhdeq@pop_push.fcv} @@ -383,7 +383,7 @@ shows the implementation of the enqueue and dequeue functions.\footnote{ Discussion will focus on the left-hand operations, as the right-hand operations are trivially derived from them. -\begin{lineref}[ln:SMPdesign:lockhdeq:pop_push:popl] +\begin{fcvref}[ln:SMPdesign:lockhdeq:pop_push:popl] \Clnrefrange{b}{e} show \co{pdeq_pop_l()}, which left\-/dequeues and returns an element if possible, returning \co{NULL} otherwise. @@ -396,9 +396,9 @@ non-\co{NULL}, line~\lnref{record} records the new left-hand index. Either way, line~\lnref{rel} releases the lock, and, finally, line~\lnref{return} returns the element if there was one, or \co{NULL} otherwise. -\end{lineref} +\end{fcvref} -\begin{lineref}[ln:SMPdesign:lockhdeq:pop_push:pushl] +\begin{fcvref}[ln:SMPdesign:lockhdeq:pop_push:pushl] \Clnrefrange{b}{e} show \co{pdeq_push_l()}, which left-enqueues the specified element. @@ -410,7 +410,7 @@ onto the double-ended queue indexed by the left-hand index. Line~\lnref{update} then updates the left-hand index and line~\lnref{rel} releases the lock. -\end{lineref} +\end{fcvref} As noted earlier, the right-hand operations are completely analogous to their left-handed counterparts, so their analysis is left as an @@ -487,7 +487,7 @@ and \co{pdeq_pop_r()} implementations separately. (see Section~\ref{sec:SMPdesign:Dining Philosophers Problem}). } \QuickQuizEnd -\begin{lineref}[ln:SMPdesign:locktdeq:pop_push:popl] +\begin{fcvref}[ln:SMPdesign:locktdeq:pop_push:popl] The \co{pdeq_pop_l()} implementation is shown on \clnrefrange{b}{e} of the figure. @@ -505,9 +505,9 @@ queue to the left-hand queue, line~\lnref{init:r} initializes the right-hand queue, and line~\lnref{rel:r} releases the right-hand lock. The element, if any, that was dequeued on line~\lnref{deq:lr} will be returned. -\end{lineref} +\end{fcvref} -\begin{lineref}[ln:SMPdesign:locktdeq:pop_push:popr] +\begin{fcvref}[ln:SMPdesign:locktdeq:pop_push:popr] The \co{pdeq_pop_r()} implementation is shown on \clnrefrange{b}{e} of the figure. As before, line~\lnref{acq:r1} acquires the right-hand lock @@ -528,19 +528,19 @@ failed, line~\lnref{deq:rl} right-dequeues an element from the left-hand queue from the left-hand queue to the right-hand queue, and line~\lnref{init:l} initializes the left-hand queue. Either way, line~\lnref{rel:l} releases the left-hand lock. -\end{lineref} +\end{fcvref} \QuickQuiz{} Why is it necessary to retry the right-dequeue operation on line~\ref{ln:SMPdesign:locktdeq:pop_push:popr:deq:rr2} of Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}? \QuickQuizAnswer{ - \begin{lineref}[ln:SMPdesign:locktdeq:pop_push:popr] + \begin{fcvref}[ln:SMPdesign:locktdeq:pop_push:popr] This retry is necessary because some other thread might have enqueued an element between the time that this thread dropped \co{d->rlock} on line~\lnref{rel:r1} and the time that it reacquired this same lock on line~\lnref{acq:r2}. - \end{lineref} + \end{fcvref} } \QuickQuizEnd \QuickQuiz{} @@ -558,7 +558,7 @@ Either way, line~\lnref{rel:l} releases the left-hand lock. it is worthwhile) is left as an exercise for the reader. } \QuickQuizEnd -\begin{lineref}[ln:SMPdesign:locktdeq:pop_push:pushl] +\begin{fcvref}[ln:SMPdesign:locktdeq:pop_push:pushl] The \co{pdeq_push_l()} implementation is shown on \clnrefrange{b}{e} of Listing~\ref{lst:SMPdesign:Compound Parallel Double-Ended Queue Implementation}. @@ -566,11 +566,11 @@ Line~\lnref{acq:l} acquires the left-hand spinlock, line~\lnref{que:l} left-enqueues the element onto the left-hand queue, and finally line~\lnref{rel:l} releases the lock. -\end{lineref} -\begin{lineref}[ln:SMPdesign:locktdeq:pop_push:pushr] +\end{fcvref} +\begin{fcvref}[ln:SMPdesign:locktdeq:pop_push:pushr] The \co{pdeq_push_r()} implementation (shown on \clnrefrange{b}{e}) is quite similar. -\end{lineref} +\end{fcvref} \QuickQuiz{} But in the case where data is flowing in only one direction, diff --git a/advsync/advsync.tex b/advsync/advsync.tex index 7dda22ad..7d637d31 100644 --- a/advsync/advsync.tex +++ b/advsync/advsync.tex @@ -165,7 +165,7 @@ Cute definitional tricks notwithstanding, this algorithm is probably the most heavily used NBS algorithm in the Linux kernel. \begin{listing}[tbp] -\begin{linelabel}[ln:count:NBS Enqueue Algorithm] +\begin{fcvlabel}[ln:count:NBS Enqueue Algorithm] \begin{VerbatimL}[commandchars=\\\[\]] static inline bool ___cds_wfcq_append(struct cds_wfcq_head *head, @@ -189,12 +189,12 @@ _cds_wfcq_enqueue(struct cds_wfcq_head *head, new_tail, new_tail); } \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{NBS Enqueue Algorithm} \label{lst:count:NBS Enqueue Algorithm} \end{listing} -\begin{lineref}[ln:count:NBS Enqueue Algorithm] +\begin{fcvref}[ln:count:NBS Enqueue Algorithm] Another common NBS algorithm is the atomic queue where elements are enqueued using an atomic exchange instruction~\cite{MagedMichael1993JPDC}, followed by a store into the \co{->next} pointer of the new element's @@ -220,7 +220,7 @@ dequeues are blocking. This algorithm is nevertheless heavily used in practice, in part because most production software is not required to tolerate arbitrary fail-stop errors. -\end{lineref} +\end{fcvref} \subsection{Applicability of NBS Benefits} \label{sec:advsync:Applicability of NBS Benefits} diff --git a/advsync/rt.tex b/advsync/rt.tex index a92b83d0..6a2f25c8 100644 --- a/advsync/rt.tex +++ b/advsync/rt.tex @@ -1156,7 +1156,7 @@ Otherwise, long RCU read-side critical sections would result in excessive real-time latencies. \begin{listing}[tb] -\begin{linelabel}[ln:advsync:Preemptible Linux-Kernel RCU] +\begin{fcvlabel}[ln:advsync:Preemptible Linux-Kernel RCU] \begin{VerbatimL}[commandchars=\\\[\]] void __rcu_read_lock(void) \lnlbl[lock:b] { @@ -1181,7 +1181,7 @@ void __rcu_read_unlock(void) \lnlbl[unl:b] } \lnlbl[unl:els:e] } \lnlbl[unl:e] \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Preemptible Linux-Kernel RCU} \label{lst:advsync:Preemptible Linux-Kernel RCU} \end{listing} @@ -1198,19 +1198,19 @@ while in one of those pre-existing critical sections have removed themselves from their lists. A simplified version of this implementation is shown in \cref{lst:advsync:Preemptible Linux-Kernel RCU}. -\begin{lineref}[ln:advsync:Preemptible Linux-Kernel RCU] +\begin{fcvref}[ln:advsync:Preemptible Linux-Kernel RCU] The \co{__rcu_read_lock()} function spans \clnrefrange{lock:b}{lock:e} and the \co{__rcu_read_unlock()} function spans \clnrefrange{unl:b}{unl:e}. -\end{lineref} +\end{fcvref} -\begin{lineref}[ln:advsync:Preemptible Linux-Kernel RCU:lock] +\begin{fcvref}[ln:advsync:Preemptible Linux-Kernel RCU:lock] \Clnref{inc} of \co{__rcu_read_lock()} increments a per-task count of the number of nested \co{rcu_read_lock()} calls, and \clnref{bar} prevents the compiler from reordering the subsequent code in the RCU read-side critical section to precede the \co{rcu_read_lock()}. -\end{lineref} +\end{fcvref} -\begin{lineref}[ln:advsync:Preemptible Linux-Kernel RCU:unl] +\begin{fcvref}[ln:advsync:Preemptible Linux-Kernel RCU:unl] \Clnref{chkn} of \co{__rcu_read_unlock()} checks to see if the nesting level count is one, in other words, if this corresponds to the outermost \co{rcu_read_unlock()} of a nested set. @@ -1246,10 +1246,10 @@ real-time software~\cite{BjoernBrandenburgPhD,DipankarSarma2004OLSscalability}. Whether or not special handling is required, \clnref{bar3} prevents the compiler from reordering the check on \clnref{chks} with the zeroing of the nesting count on \clnref{zero}. -\end{lineref} +\end{fcvref} \QuickQuiz{} - \begin{lineref}[ln:advsync:Preemptible Linux-Kernel RCU:unl] + \begin{fcvref}[ln:advsync:Preemptible Linux-Kernel RCU:unl] Suppose that preemption occurs just after the load from \co{t->rcu_read_unlock_special.s} on \clnref{chks} of \cref{lst:advsync:Preemptible Linux-Kernel RCU}. @@ -1257,7 +1257,7 @@ count on \clnref{zero}. \co{rcu_read_unlock_special()}, thus failing to remove itself from the list of tasks blocking the current grace period, in turn causing that grace period to extend indefinitely? - \end{lineref} + \end{fcvref} \QuickQuizAnswer{ That is a real problem, and it is solved in RCU's scheduler hook. If that scheduler hook sees that the value of @@ -1471,7 +1471,7 @@ OSADL runs long-term tests of systems, so referring to their website (\url{http://osadl.org/}) can be helpful. \begin{listing}[tb] -\begin{linelabel}[ln:advsync:Locating Sources of OS Jitter] +\begin{fcvlabel}[ln:advsync:Locating Sources of OS Jitter] \begin{VerbatimL}[commandchars=\\\[\]] cd /sys/kernel/debug/tracing echo 1 > max_graph_depth \lnlbl[echo1] @@ -1479,12 +1479,12 @@ echo function_graph > current_tracer # run workload cat per_cpu/cpuN/trace \lnlbl[cat] \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Locating Sources of OS Jitter} \label{lst:advsync:Locating Sources of OS Jitter} \end{listing} -\begin{lineref}[ln:advsync:Locating Sources of OS Jitter] +\begin{fcvref}[ln:advsync:Locating Sources of OS Jitter] Unfortunately, this list of OS-jitter sources can never be complete, as it will change with each new version of the kernel. This makes it necessary to be able to track down additional sources @@ -1498,7 +1498,7 @@ number of the CPU in question, and the \co{1} on \clnref{echo1} may be increased to show additional levels of function call within the kernel. The resulting trace can help track down the source of the OS jitter. -\end{lineref} +\end{fcvref} As you can see, obtaining bare-metal performance when running CPU-bound real-time threads on a general-purpose OS such as Linux @@ -1716,7 +1716,7 @@ We therefore need to schedule the fuel injection to within a time interval of about 100 microseconds. \begin{listing}[tb] -\begin{linelabel}[ln:advsync:Timed-Wait Test Program] +\begin{fcvlabel}[ln:advsync:Timed-Wait Test Program] \begin{VerbatimL} if (clock_gettime(CLOCK_REALTIME, ×tart) != 0) { perror("clock_gettime 1"); @@ -1731,7 +1731,7 @@ if (clock_gettime(CLOCK_REALTIME, &timeend) != 0) { exit(-1); } \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Timed-Wait Test Program} \label{lst:advsync:Timed-Wait Test Program} \end{listing} @@ -1799,7 +1799,7 @@ Otherwise, \co{cur_cal} points to a dynamically allocated structure providing the current calibration values. \begin{listing}[tb] -\begin{linelabel}[ln:advsync:Real-Time Calibration Using RCU] +\begin{fcvlabel}[ln:advsync:Real-Time Calibration Using RCU] \begin{VerbatimL}[commandchars=\\\[\]] struct calibration { short a; @@ -1837,19 +1837,19 @@ bool update_cal(short a, short b, short c) \lnlbl[upd:b] return true; } \lnlbl[upd:e] \end{VerbatimL} -\end{linelabel} +\end{fcvlabel} \caption{Real-Time Calibration Using RCU} \label{lst:advsync:Real-Time Calibration Using RCU} \end{listing} -\begin{lineref}[ln:advsync:Real-Time Calibration Using RCU] +\begin{fcvref}[ln:advsync:Real-Time Calibration Using RCU] \Cref{lst:advsync:Real-Time Calibration Using RCU} shows how RCU can be used to solve this problem. Lookups are deterministic, as shown in \co{calc_control()} on \clnrefrange{calc:b}{calc:e}, consistent with real-time requirements. Updates are more complex, as shown by \co{update_cal()} on \clnrefrange{upd:b}{upd:e}. -\end{lineref} +\end{fcvref} \QuickQuiz{} Given that real-time systems are often used for safety-critical diff --git a/appendix/questions/after.tex b/appendix/questions/after.tex index c56621bd..2c6c2aac 100644 --- a/appendix/questions/after.tex +++ b/appendix/questions/after.tex @@ -88,7 +88,7 @@ a large number exceeding 10 microseconds, and one exceeding even Please note that this CPU can potentially execute more than 100,000 instructions in that time. -\begin{lineref}[ln:api-pthreads:QAfter:time] +\begin{fcvref}[ln:api-pthreads:QAfter:time] One possible reason is given by the following sequence of events: \begin{enumerate} \item Consumer obtains timestamp @@ -136,7 +136,7 @@ producer's timestamp. The segments of code in each box in this figure are termed ``critical sections''; only one such critical section may be executing at a given time. -\end{lineref} +\end{fcvref} \begin{figure}[htb] \centering diff --git a/appendix/styleguide/samplecodesnippetfcv.tex b/appendix/styleguide/samplecodesnippetfcv.tex index b47b7f59..99952e5a 100644 --- a/appendix/styleguide/samplecodesnippetfcv.tex +++ b/appendix/styleguide/samplecodesnippetfcv.tex @@ -1,5 +1,5 @@ \begin{listing}[tb] -\begin{linelabel}[ln:base1] %lnlbl~beg:linelabel^ +\begin{fcvlabel}[ln:base1] %lnlbl~beg:fcvlabel^ \begin{VerbatimL}[commandchars=\$\[\]] /* * Sample Code Snippet @@ -11,7 +11,7 @@ int main(void) return 0; $lnlbl[return] } \end{VerbatimL} -\end{linelabel} %lnlbl~end:linelabel^ +\end{fcvlabel} %lnlbl~end:fcvlabel^ \caption{Sample Code Snippet} \label{lst:app:styleguide:Sample Code Snippet} \end{listing} diff --git a/appendix/styleguide/styleguide.tex b/appendix/styleguide/styleguide.tex index ca74d362..fb5671c3 100644 --- a/appendix/styleguide/styleguide.tex +++ b/appendix/styleguide/styleguide.tex @@ -383,9 +383,9 @@ They are defined in the preamble as shown below: \begin{listing}[tb] \fvset{fontsize=\scriptsize,numbers=left,numbersep=5pt,xleftmargin=9pt,obeytabs=true,tabsize=8,commandchars=\%\~\^} -\begin{linelabel}[ln:app:styleguide:LaTeX Source of Sample Code Snippet (Current)] +\begin{fcvlabel}[ln:app:styleguide:LaTeX Source of Sample Code Snippet (Current)] \VerbatimInput{appendix/styleguide/samplecodesnippetfcv.tex} -\end{linelabel} +\end{fcvlabel} \vspace*{-9pt} \caption{\LaTeX\ Source of Sample Code Snippet (Current)} \label{lst:app:styleguide:LaTeX Source of Sample Code Snippet (Current)} @@ -409,19 +409,19 @@ Labels \qco{printf} and \qco{return} in can be referred to as shown below: \begin{VerbatimU} -\begin{lineref}[ln:base1] +\begin{fcvref}[ln:base1] Lines~\lnref{printf} and~\lnref{return} can be referred to from text. -\end{lineref} +\end{fcvref} \end{VerbatimU} Above code results in the paragraph below: \begin{quote} -\begin{lineref}[ln:base1] +\begin{fcvref}[ln:base1] Lines~\lnref{printf} and~\lnref{return} can be referred to from text. -\end{lineref} +\end{fcvref} \end{quote} Macros ``\co{\\lnlbl\{\}}'' and ``\co{\\lnref\{\}}'' are defined in @@ -435,28 +435,28 @@ the preamble as follows: \newcommand{\lnref}[1]{\ref{\lnrefbase:#1}} \end{VerbatimU} -Environments \qco{linelabel} and \qco{lineref} are defined as +Environments \qco{fcvlabel} and \qco{fcvref} are defined as shown below: \begin{VerbatimU} -\newenvironment{linelabel}[1][]{% +\newenvironment{fcvlabel}[1][]{% \renewcommand{\lnlblbase}{#1}% \ignorespaces}{\ignorespacesafterend} -\newenvironment{lineref}[1][]{% +\newenvironment{fcvref}[1][]{% \renewcommand{\lnrefbase}{#1}% \ignorespaces}{\ignorespacesafterend} \end{VerbatimU} -\begin{lineref}[ln:app:styleguide:LaTeX Source of Sample Code Snippet (Current)] +\begin{fcvref}[ln:app:styleguide:LaTeX Source of Sample Code Snippet (Current)] The main part of \LaTeX\ source shown on -\Clnrefrange{beg:linelabel}{end:linelabel} in +\Clnrefrange{beg:fcvlabel}{end:fcvlabel} in \cref{lst:app:styleguide:LaTeX Source of Sample Code Snippet (Current)} can be extracted from a code sample of \cref{lst:app:styleguide:Source of Code Sample} by a perl script \path{utilities/fcvextract.pl}. All the relevant rules of extraction are described as recipes in the top level \path{Makefile} and a script to generate dependencies (\path{utilities/gen_snippet_d.pl}). -\end{lineref} +\end{fcvref} \begin{listing*}[tb] \fvset{fontsize=\scriptsize,numbers=left,numbersep=5pt,xleftmargin=9pt,obeytabs=true,tabsize=8} @@ -493,8 +493,8 @@ is a comma-spareted list of options shown below: The \qco{labelbase} option is mandatory and the string given to it will be passed to the -``\co{\\begin\{linelabel\}[