Re: [PATCH -perfbook 1/2] toolsoftrade: Apply scheme of enhanced \clnref (2nd batch)

"Paul E. McKenney" <[email protected]> Sun, 2 Aug 2026 10:55:27 -0700
Newsgroups org.kernel.vger.perfbook
Message-ID <28727150-256d-4a49-bcb6-69d46002c91c@paulmck-laptop>
On Sun, Aug 02, 2026 at 07:32:46PM +0900, Akira Yokosawa wrote:
> Following commit e3dcd91d7351 ("Enhance \clnref for multi-part listing
> and employ it"), apply the enhanced scheme in listings converted since.
> 
> Signed-off-by: Akira Yokosawa <[email protected]>

Nice!!!  I have queued both, and thank you!

							Thanx, Paul

> ---
>  toolsoftrade/toolsoftrade.tex | 254 ++++++++++++++++++++--------------
>  1 file changed, 149 insertions(+), 105 deletions(-)
> 
> diff --git a/toolsoftrade/toolsoftrade.tex b/toolsoftrade/toolsoftrade.tex
> index 9c0bf4db..d6146b47 100644
> --- a/toolsoftrade/toolsoftrade.tex
> +++ b/toolsoftrade/toolsoftrade.tex
> @@ -1850,19 +1850,20 @@ first store.
>  \begin{adjustwidth}{10pt}{5pt}
>  \footnotesize
>  \renewcommand{\myfvline}{A\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -in_progress = 1;
> -do_something();
> -in_progress = 2;
> -do_something_else();
> -in_progress = 0;
> +\begin{fcvlabel}[ln:toolsoftrade:Fusing Stores]
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +in_progress = 1;		\lnlbl[A1]
> +do_something();			\lnlbl[A2]
> +in_progress = 2;		\lnlbl[A3]
> +do_something_else();		\lnlbl[A4]
> +in_progress = 0;		\lnlbl[A5]
>  \end{VerbatimT}
>  Might be transformed to:
>  \renewcommand{\myfvline}{B\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -do_something();
> -do_something_else();
> -in_progress = 0;
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +do_something();			\lnlbl[B1]
> +do_something_else();		\lnlbl[B2]
> +in_progress = 0;		\lnlbl[B3]
>  \end{VerbatimT}
>  Because this code stores to \co{in_progress}, the compiler is
>  allowed so assume that there are neither concurrent loads nor
> @@ -1871,14 +1872,15 @@ This permits the compiler to drop the first store to this variable, which
>  might frustrate those expecting it to sometimes have a non-zero value.
>  Prevent this by using \co{WRITE_ONCE()} and \co{barrier()} as follows:
>  \renewcommand{\myfvline}{C\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -WRITE_ONCE(in_progress, 1);
> -do_something();
> -WRITE_ONCE(in_progress, 2);
> -do_something_else();
> -WRITE_ONCE(in_progress, 0);
> -in_progress = false;
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +WRITE_ONCE(in_progress, 1);	\lnlbl[C1]
> +do_something();			\lnlbl[C2]
> +WRITE_ONCE(in_progress, 2);	\lnlbl[C3]
> +do_something_else();		\lnlbl[C4]
> +WRITE_ONCE(in_progress, 0);	\lnlbl[C5]
> +in_progress = false;		\lnlbl[C6]
>  \end{VerbatimT}
> +\end{fcvlabel}
>  \end{adjustwidth}
>  \caption{Fusing Stores}
>  \label{lst:toolsoftrade:Fusing Stores}
> @@ -1886,22 +1888,26 @@ in_progress = false;
>  
>  However, there are exceptions, for example as shown in
>  \cref{lst:toolsoftrade:Fusing Stores}.
> -The code on line~A1 sets the variable \co{in_progress} to the value~1
> -to indicate that \co{do_something()} is executing, line~A3 sets it to~2
> -to indicate that \co{do_something_else()} is executing, and line~A5 sets
> +\begin{fcvref}[ln:toolsoftrade:Fusing Stores]
> +\setlnpref{A}
> +The code on \clnref{A1} sets the variable \co{in_progress} to the value~1
> +to indicate that \co{do_something()} is executing, \clnref{A3} sets it to~2
> +to indicate that \co{do_something_else()} is executing, and \clnref{A5} sets
>  it to~0 to indicate that neither is executing.
>  
>  Except that these are normal stores to a normal variable, which allows the
>  compiler to assume that this variable is not subject to concurrent loads.
> -As noted above, this in turn means that the stores on lines~A1 and~A3
> -may be dropped, as shown on lines~B1-B3.
> +As noted above, this in turn means that the stores on \clnref{A1,A3}
> +\setlnpref{B}
> +may be dropped, as shown on \clnrefrange{B1}{B3}.
>  This in turn means that the value of \co{in_progress} is always zero,
>  which might confuse and frustrate users expecting its value to indicate
>  whether either of \co{do_something()} or \co{do_something_else()} is
>  currently executing.
>  
> +\setlnpref{C}
>  This problem can  be avoided by using \co{WRITE_ONCE()}, as shown
> -on lines~C1, C3, and~C5.
> +on \clnref{C1,C3,C5}.
>  This use of \co{WRITE_ONCE()} informs the compiler that there might
>  be concurrent loads and stores, preventing it from dropping the
>  first two stores.
> @@ -1910,48 +1916,54 @@ Unfortunately, there are additional problems with the code in
>  \cref{lst:toolsoftrade:Fusing Stores},
>  that those \co{WRITE_ONCE()} calls do not solve, including code
>  reordering.
> +\end{fcvref}
>  
>  \begin{listing}[tb]
>  \begin{adjustwidth}{10pt}{5pt}
>  \footnotesize
> +\begin{fcvlabel}[ln:toolsoftrade:Reordering Code]
>  \renewcommand{\myfvline}{A\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -WRITE_ONCE(in_progress, 1);
> -do_something();
> -WRITE_ONCE(in_progress, 2);
> -do_something_else();
> -WRITE_ONCE(in_progress, 0);
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +WRITE_ONCE(in_progress, 1);		\lnlbl[A1]
> +do_something();				\lnlbl[A2]
> +WRITE_ONCE(in_progress, 2);		\lnlbl[A3]
> +do_something_else();			\lnlbl[A4]
> +WRITE_ONCE(in_progress, 0);		\lnlbl[A5]
>  \end{VerbatimT}
>  Might be transformed to:
>  \renewcommand{\myfvline}{B\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -do_something();
> -do_something_else();
> -WRITE_ONCE(in_progress, 1);
> -WRITE_ONCE(in_progress, 2);
> -WRITE_ONCE(in_progress, 0);
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +do_something();				\lnlbl[B1]
> +do_something_else();			\lnlbl[B2]
> +WRITE_ONCE(in_progress, 1);		\lnlbl[B3]
> +WRITE_ONCE(in_progress, 2);		\lnlbl[B4]
> +WRITE_ONCE(in_progress, 0);		\lnlbl[B5]
>  \end{VerbatimT}
>  This can happen if neither \co{do_something()} nor
>  \co{do_something_else()} contain atomic or volatile operations.
> +\begin{fcvref}[ln:toolsoftrade:Fusing Stores]
>  The compiler is permitted to reorder these functions past both
>  \co{WRITE_ONCE()} invocations, obtaining close to the same
> -frustrating results as shown on lines~B1-B3 of
> +\setlnpref{B}
> +frustrating results as shown on \clnrefrange{B1}{B3} of
>  \cref{lst:toolsoftrade:Fusing Stores}.
> +\end{fcvref}
>  Prevent this by using \co{barrier()} as follows:
>  \renewcommand{\myfvline}{C\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -WRITE_ONCE(in_progress, 1);
> -barrier();
> -do_something();
> -barrier();
> -WRITE_ONCE(in_progress, 2);
> -barrier();
> -do_something_else();
> -barrier();
> -WRITE_ONCE(in_progress, 0);
> -barrier();
> -in_progress = false;
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +WRITE_ONCE(in_progress, 1);		\lnlbl[C1]
> +barrier();				\lnlbl[C2]
> +do_something();				\lnlbl[C3]
> +barrier();				\lnlbl[C4]
> +WRITE_ONCE(in_progress, 2);		\lnlbl[C5]
> +barrier();				\lnlbl[C6]
> +do_something_else();			\lnlbl[C7]
> +barrier();				\lnlbl[C8]
> +WRITE_ONCE(in_progress, 0);		\lnlbl[C9]
> +barrier();				\lnlbl[C10]
> +in_progress = false;			\lnlbl[C11]
>  \end{VerbatimT}
> +\end{fcvlabel}
>  \end{adjustwidth}
>  \caption{Reordering Code}
>  \label{lst:toolsoftrade:Reordering Code}
> @@ -1961,9 +1973,11 @@ in_progress = false;
>  combine common subexpressions, reduce register pressure, and
>  improve utilization of the many functional units available on
>  modern superscalar microprocessors.
> +\begin{fcvref}[ln:toolsoftrade:Reordering Code]
> +\setlnpref{A}
>  It is also another reason why the code in
>  \cref{lst:toolsoftrade:Fusing Stores}
> -is buggy, as shown on lines~A1-A3 of
> +is buggy, as shown on \clnrefrange{A1}{A3} of
>  \cref{lst:toolsoftrade:Reordering Code}.
>  
>  If the functions \co{do_something()} and \co{do_something_else()} are free
> @@ -1971,11 +1985,12 @@ of volatile and atomic operations, the compiler will assume that there
>  are no conflicting accesses to variables accessed by these two functions.
>  Here, conflicting accesses to a variable are a set of concurrent accesses
>  to that variable, at least one of which is a store.
> +\setlnpref{B}
>  Yes, the \co{WRITE_ONCE()} calls prevent the compiler from dropping
>  any of the stores, but the compiler is under no obligation to maintain
> -ordering of other code with those stores, as shown on lines~B1-B3.
> +ordering of other code with those stores, as shown on \clnrefrange{B1}{B3}.
>  Because the three stores execute in quick succession, for most purposes,
> -the first two stores (lines~B3 and~B4) might as well have been dropped!
> +the first two stores (\clnref{B3,B4}) might as well have been dropped!
>  
>  It might seem futile to prevent the compiler from changing the order of
>  accesses in cases where the underlying hardware is free to reorder them.
> @@ -1992,11 +2007,13 @@ independent of the ordering provided by the underlying hardware.\footnote{
>  	you use atomics or variables of type \apic{sig_atomic_t}, instead
>  	of \apik{READ_ONCE()} and \apik{WRITE_ONCE()}.}
>  
> +\setlnpref{C}
>  And this problem can be solved by inserting \co{barrier()}
> -calls on lines~C2, C4, C6, C6, C8, and~C10.
> +calls on \clnref{C2,C4,C6,C8,C10}.
>  See
>  \cref{sec:toolsoftrade:Assembling the Rest of a Solution}
>  for more detail on \co{barrier()}.
> +\end{fcvref}
>  
>  \QuickQuiz{
>  	This is ridiculous!!!
> @@ -2034,10 +2051,12 @@ increases in cache misses, and thus significant degradation of
>  both performance and scalability.
>  
>  \item[Invented stores] can occur in a number of situations.
> -For example, a compiler emitting code for lines~B1--B3 of
> +\begin{fcvref}[ln:toolsoftrade:Fusing Stores]
> +\setlnpref{B}
> +For example, a compiler emitting code for \clnrefrange{B1}{B3} of
>  \cref{lst:toolsoftrade:Fusing Stores}
>  might notice that \co{in_progress} is not accessed by either
> -\co{do_something()} or \co{do_something_else()}, and is stored to on line~B3.
> +\co{do_something()} or \co{do_something_else()}, and is stored to on \clnref{B3}.
>  If either function was a complex and inline, it might be
>  necessary to do a register spill, in which case one attractive
>  place to use for temporary storage is \co{in_progress}.
> @@ -2046,25 +2065,27 @@ After all, there are no accesses to it, so what is the harm?
>  Of course, a store of any value outside the range 0--2 to this variable
>  could confuse and frustrate any user who would naturally be expecting
>  its value to remain in this range.
> +\end{fcvref}
>  
>  \begin{listing}[tb]
>  \begin{adjustwidth}{10pt}{5pt}
>  \footnotesize
>  \renewcommand{\myfvline}{A\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -if (condition)
> -	a = 1;
> -else
> -	do_a_bunch_of_stuff(&a);
> +\begin{fcvlabel}[ln:toolsoftrade:Inventing Stores]
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +if (condition)				\lnlbl[A1]
> +	a = 1;				\lnlbl[A2]
> +else					\lnlbl[A3]
> +	do_a_bunch_of_stuff(&a);	\lnlbl[A4]
>  \end{VerbatimT}
>  Might be transformed to:
>  \renewcommand{\myfvline}{B\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -a = 1;
> -if (!condition) {
> -	a = 0;
> -	do_a_bunch_of_stuff(&a);
> -}
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +a = 1;					\lnlbl[B1]
> +if (!condition) {			\lnlbl[B2]
> +	a = 0;				\lnlbl[B3]
> +	do_a_bunch_of_stuff(&a);	\lnlbl[B4]
> +}					\lnlbl[B5]
>  \end{VerbatimT}
>  If \co{do_a_bunch_of_stuff()} uses a normal store to modify \co{a}, then
>  there is a store to \co{a} on both legs of the \co{if} statement.
> @@ -2072,12 +2093,13 @@ This permits compiler to insert an unconditional store and a compensating
>  store, reducing an if-then-else to an if-then.
>  Prevent this by using \co{WRITE_ONCE()} as follows:
>  \renewcommand{\myfvline}{C\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -if (condition)
> -	WRITE_ONCE(a, 1);
> -else
> -	do_a_bunch_of_stuff(&a);
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +if (condition)				\lnlbl[C1]
> +	WRITE_ONCE(a, 1);		\lnlbl[C2]
> +else					\lnlbl[C3]
> +	do_a_bunch_of_stuff(&a);	\lnlbl[C4]
>  \end{VerbatimT}
> +\end{fcvlabel}
>  \end{adjustwidth}
>  \caption{Inventing Stores}
>  \label{lst:toolsoftrade:Inventing Stores}
> @@ -2089,16 +2111,20 @@ Nevertheless, readers might be justified in wanting a less
>  outlandish example, which is provided by
>  \cref{lst:toolsoftrade:Inventing Stores}.
>  
> -A compiler emitting code for lines~A1--A4 of
> +\begin{fcvref}[ln:toolsoftrade:Inventing Stores]
> +\setlnpref{A}
> +A compiler emitting code for \clnrefrange{A1}{A4} of
>  \cref{lst:toolsoftrade:Inventing Stores}
>  might know that the value of \co{a} is initially zero and that
>  \co{do_a_bunch_of_stuff()} modifies the variable referenced by its
>  argument (in this case, \co{a}).
> +\setlnpref{B}
>  Such a compiler might be strongly tempted to optimize away one branch
> -by transforming this code to that shown in lines~B1--B5.
> -Here, line~B1 unconditionally stores \co{1} to \co{a}, then resets the
> -value back to zero on line~B3 if the value of \co{condition} was zero.
> +by transforming this code to that shown in \clnrefrange{B1}{B5}.
> +Here, \clnref{B1} unconditionally stores \co{1} to \co{a}, then resets the
> +value back to zero on \clnref{B3} if the value of \co{condition} was zero.
>  This transforms the if-then-else into an if-then, saving one branch.
> +\end{fcvref}
>  
>  \QuickQuiz{
>  	Ouch!
> @@ -2125,8 +2151,11 @@ This transforms the if-then-else into an if-then, saving one branch.
>  	By inventing the store, the compiler might be introducing a
>  	data race, which it is not permitted to do.
>  
> -	Furthermore, on line C4 of
> +\begin{fcvref}[ln:toolsoftrade:Inventing Stores]
> +\setlnpref{C}
> +	Furthermore, on \clnref{C4} of
>  	\cref{lst:toolsoftrade:Inventing Stores},
> +\end{fcvref}
>  	the address of that variable is passed to
>  	\co{do_a_bunch_of_stuff()}.
>  	If the compiler can see this function's definition, and
> @@ -2148,38 +2177,43 @@ against compiler optimizations that invent data races.
>  \begin{listing}[tb]
>  \begin{adjustwidth}{10pt}{5pt}
>  \footnotesize
> +\begin{fcvlabel}[ln:toolsoftrade:Store-to-Load Conversion]
>  \renewcommand{\myfvline}{A\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -r1 = p;
> -if (unlikely(r1))
> -	do_something_with(r1);
> -barrier();
> -p = NULL;
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +r1 = p;					\lnlbl[A1]
> +if (unlikely(r1))			\lnlbl[A2]
> +	do_something_with(r1);		\lnlbl[A3]
> +barrier();				\lnlbl[A4]
> +p = NULL;				\lnlbl[A5]
>  \end{VerbatimT}
>  Might be transformed to:
>  \renewcommand{\myfvline}{B\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -r1 = p;
> -if (unlikely(r1))
> -	do_something_with(r1);
> -barrier();
> -if (p != NULL)
> -	p = NULL;
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +r1 = p;					\lnlbl[B1]
> +if (unlikely(r1))			\lnlbl[B2]
> +	do_something_with(r1);		\lnlbl[B3]
> +barrier();				\lnlbl[B4]
> +if (p != NULL)				\lnlbl[B5]
> +	p = NULL;			\lnlbl[B6]
>  \end{VerbatimT}
> +\begin{fcvref}[ln:toolsoftrade:Store-to-Load Conversion]
> +\setlnpref{A}
>  Although the \co{barrier()} prevents the compiler from using the value
> -loaded from \co{p} on line~A1, profile-guided optimization might tell
> +loaded from \co{p} on \clnref{A1}, profile-guided optimization might tell
>  the compiler that the value of \co{p} was almost always \co{NULL}.
> +\end{fcvref}
>  Checking the value before storing might be an attractive optimization,
>  destructive though it might be to ordering in the case where
>  \co{do_something_with()} contains an \co{smp_wmb()}.
>  Prevent this by using \co{READ_ONCE()} and \co{WRITE_ONCE()} as follows:
>  \renewcommand{\myfvline}{C\arabic{FancyVerbLine}}
> -\begin{VerbatimT}
> -r1 = READ_ONCE(p);
> -if (unlikely(r1))
> -	do_something_with(r1);
> -WRITE_ONCE(p, NULL);
> +\begin{VerbatimT}[commandchars=\\\[\]]
> +r1 = READ_ONCE(p);			\lnlbl[C1]
> +if (unlikely(r1))			\lnlbl[C2]
> +	do_something_with(r1);		\lnlbl[C3]
> +WRITE_ONCE(p, NULL);			\lnlbl[C4]
>  \end{VerbatimT}
> +\end{fcvlabel}
>  \end{adjustwidth}
>  \caption{Store-to-Load Conversion}
>  \label{lst:toolsoftrade:Store-to-Load Conversion}
> @@ -2189,21 +2223,23 @@ WRITE_ONCE(p, NULL);
>  that a plain store might not actually change the value in memory.
>  For example, consider
>  \cref{lst:toolsoftrade:Store-to-Load Conversion}.
> -Line~A1 fetches \co{p}, but the \qco{if} statement on
> -line~A2 also tells the compiler that the developer thinks that
> +\begin{fcvref}[ln:toolsoftrade:Store-to-Load Conversion]\setlnpref{A}
> +\Clnref{A1} fetches \co{p}, but the \qco{if} statement on
> +\clnref{A2} also tells the compiler that the developer thinks that
>  \co{p} is usually \co{NULL}.\footnote{
>  	The \apik{unlikely()} function provides this hint to the compiler,
>  	and different compilers provide different ways of implementing
>  	\co{unlikely()}.}
> -The \apik{barrier()} statement on line~A4 forces the compiler to forget
> +The \apik{barrier()} statement on \clnref{A4} forces the compiler to forget
>  the value of \co{p}, but one could imagine a (perhaps buggy) compiler
>  choosing to remember the hint---or getting a replacement hint via
>  profile-guided optimization.
> -Doing so could cause the compiler to realize that line~A5 is often an
> +Doing so could cause the compiler to realize that \clnref{A5} is often an
>  expensive no-op.
>  
> +\setlnpref{B}
>  Such a compiler might therefore guard the store of \co{NULL}
> -with a check, as shown on lines~B5--B6.
> +with a check, as shown on \clnrefrange{B5}{B6}.
>  Although this transformation is often desirable, it could be problematic
>  if the actual store was required for ordering.
>  For example, if \co{do_something_with()} contained a write memory barrier
> @@ -2211,25 +2247,33 @@ For example, if \co{do_something_with()} contained a write memory barrier
>  check load.
>  This situation might suggest use of \apik{smp_store_release()} over
>  \apik{smp_wmb()}.
> +\setlnpref{C}
>  Or alternatively, use of \co{READ_ONCE()} and \co{WRITE_ONCE()} combined
> -with the assumed \co{smp_wmb()}, as shown on lines~C1 and~C4.
> +with the assumed \co{smp_wmb()}, as shown on \clnref{C1,C4}.
> +\end{fcvref}
>  
>  \QuickQuiz{
> -	But doesn't the \co{if} statement on line~C2 provide a control
> +\begin{fcvref}[ln:toolsoftrade:Store-to-Load Conversion]
> +	\setlnpref{C}
> +	But doesn't the \co{if} statement on \clnref{C2} provide a control
>  	dependency that makes the \co{smp_wmb} unnecessary?
> +\end{fcvref}
>  }\QuickQuizAnswer{
>  	No, and for two reasons.
>  
> +\begin{fcvref}[ln:toolsoftrade:Store-to-Load Conversion]
> +	\setlnpref{C}
>  	First, in the Linux-kernel memory model, the control dependency
> -	does not extend beyond the end of the \co{if} on line~C3, and
> -	thus does not extend to the store on line~C4.
> +	does not extend beyond the end of the \co{if} on \clnref{C3}, and
> +	thus does not extend to the store on \clnref{C4}.
>  
>  	Second, even if the control dependency did somehow extend to
> -	line~C4 (perhaps due to C4 being moved into the body of the
> +	\clnref{C4} (perhaps due to \clnref{C4} being moved into the body of the
>  	\co{if} statement), that dependency would order the load on
> -	line~C1 with the store on line~C4.
> +	line~C1 with the store on \clnref{C4}.
>  	It would \emph{not} order any stores prior to the assumed
>  	\co{smp_wmb()} in \co{do_something_with()}.
> +\end{fcvref}
>  
>  	So there is a control dependency, but it does not extend far
>  	enough and it also might not order the prior writes that the
> 
> base-commit: 6fa444b92d1158310a43074b6d680055e93fbbca
> -- 
> 2.43.0
>