Signed-off-by: Akira Yokosawa <[email protected]>
---
 ...usync-o+o-xchg-rcusync-o+rl-o-o-rul.litmus | 26 ++++++++---------
 together/applyrcu.tex                         | 29 ++++++++++++-------
 2 files changed, 32 insertions(+), 23 deletions(-)

diff --git 
a/CodeSamples/formal/herd/C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul.litmus
 
b/CodeSamples/formal/herd/C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul.litmus
index 2f0de350..73859c24 100644
--- 
a/CodeSamples/formal/herd/C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul.litmus
+++ 
b/CodeSamples/formal/herd/C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul.litmus
@@ -5,7 +5,7 @@ C C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul
        int a=1;
        int b;
        int c;
-       int *p=a;
+       int *p=a;                       //\lnlbl[init:p]
 }
 
 P0(int *a, int *b, int *c, int **p)
@@ -13,9 +13,9 @@ P0(int *a, int *b, int *c, int **p)
        int *r1;
 
        *b = 1;
-       r1 = xchg(p, b);
-       synchronize_rcu();
-       *r1 = 0; // Emulate kfree();
+       r1 = xchg(p, b);                //\lnlbl[P0:xchg]
+       synchronize_rcu();              //\lnlbl[P0:sync]
+       *r1 = 0; // Emulate kfree();    //\lnlbl[P0:free]
 }
 
 P1(int *a, int *b, int *c, int **p)
@@ -23,9 +23,9 @@ P1(int *a, int *b, int *c, int **p)
        int *r1;
 
        *c = 1;
-       r1 = xchg(p, c);
-       synchronize_rcu();
-       *r1 = 0; // Emulate kfree();
+       r1 = xchg(p, c);                //\lnlbl[P1:xchg]
+       synchronize_rcu();              //\lnlbl[P1:sync]
+       *r1 = 0; // Emulate kfree();    //\lnlbl[P1:free]
 }
 
 P2(int *a, int *b, int *c, int **p)
@@ -33,15 +33,15 @@ P2(int *a, int *b, int *c, int **p)
        int *r1;
        int r2;
 
-       rcu_read_lock();
-       r1 = rcu_dereference(*p);
-       r2 = *r1;
-       rcu_read_unlock();
+       rcu_read_lock();                //\lnlbl[P2:lock]
+       r1 = rcu_dereference(*p);       //\lnlbl[P2:load]
+       r2 = *r1;                       //\lnlbl[P2:deref]
+       rcu_read_unlock();              //\lnlbl[P2:unlock]
 }
 
 //\end[snippet]
 locations [0:r1; 1:r1; 2:r1; 2:r2; a; b; c; p]
 (* Better not be freed!!! *)
-exists (2:r2=0 \/ a=1 \/
+exists (2:r2=0 \/ a=1 \/                       (* \lnlbl[ex:1] *)
        (* Better be only one in use! *)
-       (b=1 /\ c=1) \/ (b=0 /\ c=0))
+       (b=1 /\ c=1) \/ (b=0 /\ c=0))           (* \lnlbl[ex:2] *)
diff --git a/together/applyrcu.tex b/together/applyrcu.tex
index ff1a276b..48eaa685 100644
--- a/together/applyrcu.tex
+++ b/together/applyrcu.tex
@@ -877,25 +877,30 @@ they use \co{rcu_assign_pointer()}.
 However, if we have concurrent lockless updates, one update's
 \co{rcu_assign_pointer()} can be silently overwritten by the next update,
 resulting in a memory leak.
+\begin{fcvref}[ln:formal:C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul:whole]
 One way to avoid this is to use an atomic \co{xchg()} instruction,
-as shown on lines~15 and~25 of
+as shown on \clnref{P0:xchg, P1:xchg} of
 \cref{lst:formal:Configuration-Update Example}.
 This way, the pointer from the overwritten \co{xchg()} is returned by
 the next \co{xchg()}, allowing the caller to free it after an RCU
-grace period (lines~16 and 26).
+grace period (\clnref{P0:sync, P1:sync}).
 Because the Linux-kernel memory model does not support dynamic allocation,
 this code emulates freeing by storing the value zero.
+\end{fcvref}
 
 \QuickQuiz{
        Wait!!!
-       Isn't it necessary for lines~17 and~27 of
+       
\begin{fcvref}[ln:formal:C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul:whole]
+       Isn't it necessary for \clnref{P0:free, P1:free} of
        \cref{lst:formal:Configuration-Update Example}
-       to check for a \co{NULL} pointer returned from lines~15
-       and~25?
+       to check for a \co{NULL} pointer returned from
+       \clnref{P0:xchg, P1:xchg}?
+       \end{fcvref}
 }\QuickQuizAnswer{
        In this textbook example, no.
 
-       This is because line~7 initialized pointer \co{p} to point to
+       
\begin{fcvref}[ln:formal:C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul:whole]
+       This is because \clnref{init:p} initialized pointer \co{p} to point to
        variable \co{a}, so that this pointer will never be \co{NULL}.
        However, this is a very good question to ask because in most
        production-quality code, a \co{NULL} check would indeed be
@@ -903,19 +908,23 @@ this code emulates freeing by storing the value zero.
        On top of that, the first sentence of this section suggested
        that the pointer might in fact be \co{NULL}.
        Adding the NULL checks is left as an exercise for the reader.
+       \end{fcvref}
 }\QuickQuizEnd
 
+\begin{fcvref}[ln:formal:C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul:whole]
 The reader can then be written as a straightforward RCU reader
-(lines~35 and~38), loading the current pointer on line~36 and
-dereferencing it on line~37.
+(\clnrefrange{P2:lock}{P2:unlock}),
+loading the current pointer on \clnref{P2:load} and
+dereferencing it on \clnref{P2:deref}.
 
 Running this example
 
(\path{CodeSamples/formal/herd/C-MP+o-xchg-rcusync-o+o-xchg-rcusync-o+rl-o-o-rul.litmus})
 through \co{herd}
 (see \cref{sec:formal:Axiomatic Approaches})
-verifies that this algorithm avoid use-after-free errors (line~43) and that it
+verifies that this algorithm avoid use-after-free errors (\clnref{ex:1}) and 
that it
 emulates freeing of all but one of the objects \co{a}, \co{b}, and \co{c}
-(line~45), thus also avoiding memory leaks.
+(\clnref{ex:2}), thus also avoiding memory leaks.
+\end{fcvref}
 
 \subsection{Lockless Double-Checked Locking}
 \label{sec:together:Lockless Double-Checked Locking}
-- 
2.43.0



Reply via email to