[PATCH 1/4] defer/hazptr: Extract snippet from hazptr.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From fc38eb9741c49aa7907d60806158499affe36bfa Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <akiyks@xxxxxxxxx>
Date: Sun, 21 Apr 2019 15:14:25 +0900
Subject: [PATCH 1/4] defer/hazptr: Extract snippet from hazptr.c

By using "gobbleblank=yes" option of \begin{snippet} meta command,
fcvextract.pl can extract the snippet in a proper form.
Also embed line labels and reference them in the text.

Signed-off-by: Akira Yokosawa <akiyks@xxxxxxxxx>
---
 CodeSamples/defer/hazptr.c |  77 +++++++++++++------------
 defer/hazptr.tex           | 111 ++++++++++++-------------------------
 2 files changed, 76 insertions(+), 112 deletions(-)

diff --git a/CodeSamples/defer/hazptr.c b/CodeSamples/defer/hazptr.c
index ee7b8075..3def441b 100644
--- a/CodeSamples/defer/hazptr.c
+++ b/CodeSamples/defer/hazptr.c
@@ -72,12 +72,13 @@ void hazptr_reinitialize()
  *    0 : a == b
  *  > 0 : a > b
  */
-int compare (const void *a, const void *b)
+//\begin{snippet}[labelbase=ln:defer:hazptr:scan_free,gobbleblank=yes,commandchars=\%\@\$]
+int compare(const void *a, const void *b)
 {
-  return ( *(hazptr_head_t **)a - *(hazptr_head_t **)b );
+	return ( *(hazptr_head_t **)a - *(hazptr_head_t **)b );
 }
-
-void hazptr_scan()
+							//\fcvblank
+void hazptr_scan()				//\lnlbl{scan:b}
 {
 	/* Iteratation variables. */
 	hazptr_head_t *cur;
@@ -89,14 +90,19 @@ void hazptr_scan()
 	/* List of hazard pointers, and its size. */
 	hazptr_head_t **plist = gplist;
 	unsigned long psize;
-
-	if (plist == NULL) {
-		plist = (hazptr_head_t **)malloc(sizeof(hazptr_head_t *) * K * NR_THREADS);
+							//\fcvblank
+	if (plist == NULL) {			//\lnlbl{scan:check}
+		psize = sizeof(hazptr_head_t *) * K * NR_THREADS; //\lnlbl{scan:alloc:b}
+		plist = (hazptr_head_t **)malloc(psize);
+#ifndef FCV_SNIPPET
 		if (plist == NULL) {
 			fprintf(stderr, "hazptr_scan: out of memory\n");
 			exit(EXIT_FAILURE);
 		}
-		gplist = plist;
+#else /* FCV_SNIPPET */
+		BUG_ON(!plist);
+#endif /* FCV_SNIPPET */
+		gplist = plist;			//\lnlbl{scan:alloc:e}
 	}
 
 	/*
@@ -111,52 +117,53 @@ void hazptr_scan()
 	 *   A -> B -> C ---> A -> B      ---> A -> C
 	 *                    B -> POISON      B -> POISON
 	 */
-	smp_mb();
+	smp_mb();				//\lnlbl{scan:mb1}
 
 	/* Stage 1: Scan HP list and insert non-null values in plist. */
 	psize = 0;
-	for (i = 0; i < H; i++) {
+	for (i = 0; i < H; i++) {		//\lnlbl{scan:loop:b}
 		uintptr_t hp = (uintptr_t)READ_ONCE(HP[i].p);
-
+							//\fcvblank
 		if (!hp)
 			continue;
 		plist[psize++] = (hazptr_head_t *)(hp & ~0x1UL);
-	}
-	smp_mb(); /* ensure freeing happens after scan. */
+	}					//\lnlbl{scan:loop:e}
+	smp_mb(); /* ensure freeing happens after scan. */ //\lnlbl{scan:mb2}
 	
 	/* Stage 2: Sort the plist. */
-	qsort(plist, psize, sizeof(hazptr_head_t *), compare);
+	qsort(plist, psize, sizeof(hazptr_head_t *), compare); //\lnlbl{scan:sort}
 
 	/* Stage 3: Free non-harzardous nodes. */
-	tmplist = rlist;
-	rlist = NULL;
-	rcount = 0;
-	while (tmplist != NULL) {
+	tmplist = rlist;			//\lnlbl{scan:rem:b}
+	rlist = NULL;				//\lnlbl{scan:rem:e}
+	rcount = 0;				//\lnlbl{scan:zero}
+	while (tmplist != NULL) {		//\lnlbl{scan:loop2:b}
 		/* Pop cur off top of tmplist. */
-		cur = tmplist;
-		tmplist = tmplist->next;
+		cur = tmplist;			//\lnlbl{scan:rem1st:b}
+		tmplist = tmplist->next;	//\lnlbl{scan:rem1st:e}
 
-		if (bsearch(&cur, plist, psize, sizeof(hazptr_head_t *), compare)) {
-			cur->next = rlist;
+		if (bsearch(&cur, plist, psize,	//\lnlbl{scan:chkhazp:b}
+		            sizeof(hazptr_head_t *), compare)) { //\lnlbl{scan:chkhazp:e}
+			cur->next = rlist;	//\lnlbl{scan:back:b}
 			rlist = cur;
-			rcount++;
+			rcount++;		//\lnlbl{scan:back:e}
 		} else {
-			hazptr_free(cur);
+			hazptr_free(cur);	//\lnlbl{scan:free}
 		}
-	}
-}
-
-void hazptr_free_later(hazptr_head_t *n)
+	}					//\lnlbl{scan:loop2:e}
+}						//\lnlbl{scan:e}
+							//\fcvblank
+void hazptr_free_later(hazptr_head_t *n)	//\lnlbl{free:b}
 {
-	n->next = rlist;
-	rlist = n;
-	rcount++;
+	n->next = rlist;			//\lnlbl{free:enq:b}
+	rlist = n;				//\lnlbl{free:enq:e}
+	rcount++;				//\lnlbl{free:count}
 
-	if (rcount >= R) {
-		hazptr_scan();
+	if (rcount >= R) {			//\lnlbl{free:check}
+		hazptr_scan();			//\lnlbl{free:scan}
 	}
-}
-
+}						//\lnlbl{free:e}
+//\end{snippet}
 #ifdef TEST
 #include "hazptrtorture.h"
 #endif /* #ifdef TEST */
diff --git a/defer/hazptr.tex b/defer/hazptr.tex
index 46592957..84fd15bc 100644
--- a/defer/hazptr.tex
+++ b/defer/hazptr.tex
@@ -116,105 +116,62 @@ the hazard pointer to \co{NULL}.
 \end{lineref}
 
 \begin{listing}[tbp]
-\begin{VerbatimL}
-int compare (const void *a, const void *b)
-{
-	return (*(hazptr_head_t **)a - *(hazptr_head_t **)b);
-}
-
-void hazptr_scan()
-{
-	hazptr_head_t *cur;
-	int i;
-	hazptr_head_t *tmplist;
-	hazptr_head_t **plist = gplist;
-	unsigned long psize;
-
-	if (plist == NULL) {
-		psize = sizeof(hazptr_head_t *) * K * NR_THREADS;
-		plist = malloc(psize);
-		BUG_ON(!plist);
-		gplist = plist;
-	}
-	smp_mb();
-	psize = 0;
-	for (i = 0; i < H; i++) {
-		uintptr_t hp  = (uintptr_t)READ_ONCE(HP[i].p);
-
-		if (!hp)
-			continue;
-		plist[psize++] = (hazptr_head_t *)(hp & ~0x1UL);
-	}
-	smp_mb();
-	qsort(plist, psize, sizeof(hazptr_head_t *), compare);
-	tmplist = rlist;
-	rlist = NULL;
-	rcount = 0;
-	while (tmplist != NULL) {
-		cur = tmplist;
-		tmplist = tmplist->next;
-		if (bsearch(&cur, plist, psize,
-		    sizeof(hazptr_head_t *), compare)) {
-			cur->next = rlist;
-			rlist = cur;
-			rcount++;
-		} else {
-			hazptr_free(cur);
-		}
-	}
-}
-
-void hazptr_free_later(hazptr_head_t *n)
-{
-	n->next = rlist;
-	rlist = n;
-	rcount++;
-	if (rcount >= R) {
-		hazptr_scan();
-	}
-}
-\end{VerbatimL}
+\input{CodeSamples/defer/hazptr@scan_free.fcv}
 \caption{Hazard-Pointer Scanning and Freeing}
 \label{lst:defer:Hazard-Pointer Scanning and Freeing}
 \end{listing}
 
+\begin{lineref}[ln:defer:hazptr:scan_free:free]
 Once a hazard-pointer-protected object has been removed from its
 linked data structure, so that it is now inaccessible to future
 hazard-pointer readers, it is passed to \co{hazptr_free_later()},
-which is shown on lines~48-56 of
+which is shown on lines~\lnref{b}-\lnref{e} of
 Listing~\ref{lst:defer:Hazard-Pointer Scanning and Freeing}
 (\path{hazptr.c}).
-Lines~50 and~51 enqueue the object on a per-thread list \co{rlist}
-and line~52 counts the object in \co{rcount}.
-If line~53 sees that a sufficiently large number of objects are now
-queued, line~54 invokes \co{hazptr_scan()} to attempt to free some of them.
+Lines~\lnref{enq:b} and~\lnref{enq:e}
+enqueue the object on a per-thread list \co{rlist}
+and line~\lnref{count} counts the object in \co{rcount}.
+If line~\lnref{check} sees that a sufficiently large number of objects are now
+queued, line~\lnref{scan} invokes \co{hazptr_scan()} to attempt to
+free some of them.
+\end{lineref}
 
-The \co{hazptr_scan()} function is shown on lines~6--46 of the listing.
+\begin{lineref}[ln:defer:hazptr:scan_free:scan]
+The \co{hazptr_scan()} function is shown on lines~\lnref{b}-\lnref{e}
+of the listing.
 This function relies on a fixed maximum number of threads (\co{NR_THREADS})
 and a fixed maximum number of hazard pointers per thread (\co{K}),
 which allows a fixed-size array of hazard pointers to be used.
 Because any thread might need to scan the hazard pointers, each thread
 maintains its own array, which is referenced by the per-thread variable
 \co{gplist}.
-If line~14 determines that this thread has not yet allocated its
-\co{gplist}, lines~15--18 carry out the allocation.
-The memory barrier on line~20 ensures that all threads see the
-removal of all objects by this thread before lines~22-28 scan
+If line~\lnref{check} determines that this thread has not yet allocated its
+\co{gplist}, lines~\lnref{alloc:b}-\lnref{alloc:e} carry out the allocation.
+The memory barrier on line~\lnref{mb1} ensures that all threads see the
+removal of all objects by this thread before
+lines~\lnref{loop:b}-\lnref{loop:e} scan
 all of the hazard pointers, accumulating non-NULL pointers into
 the \co{plist} array and counting them in \co{psize}.
-The memory barrier on line~30 ensures that the reads of the hazard pointers
+The memory barrier on line~\lnref{mb2} ensures that the reads of
+the hazard pointers
 happen before any objects are freed.
-Line~30 then sorts this array to enable use of binary search below.
+Line~\lnref{sort} then sorts this array to enable use of binary search below.
 
-Lines~31 and 32 remove all elements from this thread's list of
+Lines~\lnref{rem:b} and~\lnref{rem:e}
+remove all elements from this thread's list of
 to-be-freed objects, placing them on the local \co{tmplist}
-and line~33 zeroes the count.
-Each pass through the loop spanning lines~34-45 processes each
+and line~\lnref{zero} zeroes the count.
+Each pass through the loop spanning
+lines~\lnref{loop2:b}-\lnref{loop2:e} processes each
 of the to-be-freed objects.
-Lines~35 and~36 remove the first object from \co{tmplist},
-and if lines~37 and~38 determine that there is a hazard pointer
-protecting this object, lines~39-41 place it back onto \co{rlist}.
-Otherwise, line~43 frees the object.
+Lines~\lnref{rem1st:b} and~\lnref{rem1st:e}
+remove the first object from \co{tmplist},
+and if lines~\lnref{chkhazp:b} and~\lnref{chkhazp:e}
+determine that there is a hazard pointer
+protecting this object, lines~\lnref{back:b}-\lnref{back:e}
+place it back onto \co{rlist}.
+Otherwise, line~\lnref{free} frees the object.
+\end{lineref}
 
 \begin{listing}[tbp]
 \input{CodeSamples/defer/route_hazptr@xxxxxxxxxx}
-- 
2.17.1





[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux