[PATCH 5/7] SMPdesign: Employ new scheme for snippets from smpalloc.c

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

 



>From b5efb413687874a667443943069c021e6c827d7b Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <akiyks@xxxxxxxxx>
Date: Fri, 2 Nov 2018 00:22:35 +0900
Subject: [PATCH 5/7] SMPdesign: Employ new scheme for snippets from smpalloc.c

NOTE: Names "percpumem" and "percpumempool" are replaced with
"pertheardmem" and "perthreadmempool" to respect those used in
CodeSamples/SMPdesign/smpalloc.c. Wording of "per-CPU" around them
in the text is also modified to "per-thread".

Signed-off-by: Akira Yokosawa <akiyks@xxxxxxxxx>
---
 CodeSamples/SMPdesign/smpalloc.c |  57 ++++++++++--------
 SMPdesign/SMPdesign.tex          | 122 ++++++++++-----------------------------
 2 files changed, 63 insertions(+), 116 deletions(-)

diff --git a/CodeSamples/SMPdesign/smpalloc.c b/CodeSamples/SMPdesign/smpalloc.c
index 149e226..72262d6 100644
--- a/CodeSamples/SMPdesign/smpalloc.c
+++ b/CodeSamples/SMPdesign/smpalloc.c
@@ -21,13 +21,14 @@
 
 #include "../api.h"
 
+//\begin{snippet}[labelbase=ln:SMPdesign:smpalloc:data_struct,commandchars=\\\@\$]
 #define TARGET_POOL_SIZE 3
 #define GLOBAL_POOL_SIZE 40
 
-struct memblock {
-	char *bytes[CACHE_LINE_SIZE];
-} memblocks[GLOBAL_POOL_SIZE];
-
+struct memblock {				//\fcvexclude
+	char *bytes[CACHE_LINE_SIZE];		//\fcvexclude
+} memblocks[GLOBAL_POOL_SIZE];			//\fcvexclude
+						//\fcvexclude
 struct globalmempool {
 	spinlock_t mutex;
 	int cur;
@@ -40,46 +41,54 @@ struct perthreadmempool {
 };
 
 DEFINE_PER_THREAD(struct perthreadmempool, perthreadmem);
+//\end{snippet}
 
+//\begin{snippet}[labelbase=ln:SMPdesign:smpalloc:alloc,commandchars=\\\@\$]
 struct memblock *memblock_alloc(void)
 {
 	int i;
 	struct memblock *p;
-	struct perthreadmempool *pcpp = &__get_thread_var(perthreadmem);
+	struct perthreadmempool *pcpp;
 
-	if (pcpp->cur < 0) {
-		spin_lock(&globalmem.mutex);
-		for (i = 0; i < TARGET_POOL_SIZE && globalmem.cur >= 0; i++) {
+	pcpp = &__get_thread_var(perthreadmem);			//\lnlbl{pick}
+	if (pcpp->cur < 0) {					//\lnlbl{chk:empty}
+		spin_lock(&globalmem.mutex);			//\lnlbl{ack}
+		for (i = 0; i < TARGET_POOL_SIZE &&		//\lnlbl{loop:b}
+		            globalmem.cur >= 0; i++) {
 			pcpp->pool[i] = globalmem.pool[globalmem.cur];
 			globalmem.pool[globalmem.cur--] = NULL;
-		}
-		pcpp->cur = i - 1;
-		spin_unlock(&globalmem.mutex);
+		}						//\lnlbl{loop:e}
+		pcpp->cur = i - 1;				//\lnlbl{set}
+		spin_unlock(&globalmem.mutex);			//\lnlbl{rel}
 	}
-	if (pcpp->cur >= 0) {
-		p = pcpp->pool[pcpp->cur];
+	if (pcpp->cur >= 0) {					//\lnlbl{chk:notempty}
+		p = pcpp->pool[pcpp->cur];			//\lnlbl{rem:b}
 		pcpp->pool[pcpp->cur--] = NULL;
-		return p;
+		return p;					//\lnlbl{rem:e}
 	}
-	return NULL;
+	return NULL;						//\lnlbl{ret:NULL}
 }
+//\end{snippet}
 
+//\begin{snippet}[labelbase=ln:SMPdesign:smpalloc:free,commandchars=\\\@\$]
 void memblock_free(struct memblock *p)
 {
 	int i;
-	struct perthreadmempool *pcpp = &__get_thread_var(perthreadmem);
+	struct perthreadmempool *pcpp;
 
-	if (pcpp->cur >= 2 * TARGET_POOL_SIZE - 1) {
-		spin_lock(&globalmem.mutex);
-		for (i = pcpp->cur; i >= TARGET_POOL_SIZE; i--) {
+	pcpp = &__get_thread_var(perthreadmem);			//\lnlbl{get}
+	if (pcpp->cur >= 2 * TARGET_POOL_SIZE - 1) {		//\lnlbl{chk:full}
+		spin_lock(&globalmem.mutex);			//\lnlbl{acq}
+		for (i = pcpp->cur; i >= TARGET_POOL_SIZE; i--) {//\lnlbl{loop:b}
 			globalmem.pool[++globalmem.cur] = pcpp->pool[i];
 			pcpp->pool[i] = NULL;
-		}
-		pcpp->cur = i;
-		spin_unlock(&globalmem.mutex);
-	}
-	pcpp->pool[++pcpp->cur] = p;
+		}						//\lnlbl{loop:e}
+		pcpp->cur = i;					//\lnlbl{set}
+		spin_unlock(&globalmem.mutex);			//\lnlbl{rel}
+	}							//\lnlbl{empty:e}
+	pcpp->pool[++pcpp->cur] = p;				//\lnlbl{place}
 }
+//\end{snippet}
 
 void initpools(void)
 {
diff --git a/SMPdesign/SMPdesign.tex b/SMPdesign/SMPdesign.tex
index 06a0c8c..3019ef4 100644
--- a/SMPdesign/SMPdesign.tex
+++ b/SMPdesign/SMPdesign.tex
@@ -971,8 +971,8 @@ caches are shown in
 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
-type \co{struct percpumempool}.
+and the two CPU pools by the per-thread variable \co{perthreadmem} of
+type \co{struct perthreadmempool}.
 Both of these data structures have arrays of pointers to blocks
 in their \co{pool} fields, which are filled from index zero upwards.
 Thus, if \co{globalmem.pool[3]} is \co{NULL}, then the remainder of
@@ -988,27 +988,7 @@ must be empty.\footnote{
 	a feel for its operation.}
 
 \begin{listing}[tbp]
-{ \scriptsize
-\begin{verbbox}
-  1 #define TARGET_POOL_SIZE 3
-  2 #define GLOBAL_POOL_SIZE 40
-  3
-  4 struct globalmempool {
-  5   spinlock_t mutex;
-  6   int cur;
-  7   struct memblock *pool[GLOBAL_POOL_SIZE];
-  8 } globalmem;
-  9
- 10 struct percpumempool {
- 11   int cur;
- 12   struct memblock *pool[2 * TARGET_POOL_SIZE];
- 13 };
- 14
- 15 DEFINE_PER_THREAD(struct percpumempool, percpumem);
-\end{verbbox}
-}
-\centering
-\theverbbox
+\input{CodeSamples/SMPdesign/smpalloc@data_struct.fcv}
 \caption{Allocator-Cache Data Structures}
 \label{lst:SMPdesign:Allocator-Cache Data Structures}
 \end{listing}
@@ -1033,97 +1013,55 @@ smaller than the number of non-\co{NULL} pointers.
 
 \subsubsection{Allocation Function}
 
+\begin{lineref}[ln:SMPdesign:smpalloc:alloc]
 The allocation function \co{memblock_alloc()} may be seen in
 Listing~\ref{lst:SMPdesign:Allocator-Cache Allocator Function}.
-Line~7 picks up the current thread's per-thread pool,
+Line~\lnref{pick} picks up the current thread's per-thread pool,
 and line~8 check to see if it is empty.
 
-If so, lines~9-16 attempt to refill it from the global pool
-under the spinlock acquired on line~9 and released on line~16.
-Lines~10-14 move blocks from the global to the per-thread pool until
+If so, lines~\lnref{ack}-\lnref{rel} attempt to refill it
+from the global pool
+under the spinlock acquired on line~\lnref{ack} and released on line~\lnref{rel}.
+Lines~\lnref{loop:b}-\lnref{loop:e} move blocks from the global
+to the per-thread pool until
 either the local pool reaches its target size (half full) or
-the global pool is exhausted, and line~15 sets the per-thread pool's
+the global pool is exhausted, and line~\lnref{set} sets the per-thread pool's
 count to the proper value.
 
-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.
+In either case, line~\lnref{chk:notempty} checks for the per-thread
+pool still being
+empty, and if not, lines~\lnref{rem:b}-\lnref{rem:e} remove a block and return it.
+Otherwise, line~\lnref{ret:NULL} tells the sad tale of memory exhaustion.
+\end{lineref}
 
 \begin{listing}[tbp]
-{ \scriptsize
-\begin{verbbox}
-  1 struct memblock *memblock_alloc(void)
-  2 {
-  3   int i;
-  4   struct memblock *p;
-  5   struct percpumempool *pcpp;
-  6
-  7   pcpp = &__get_thread_var(percpumem);
-  8   if (pcpp->cur < 0) {
-  9     spin_lock(&globalmem.mutex);
- 10     for (i = 0; i < TARGET_POOL_SIZE &&
- 11                 globalmem.cur >= 0; i++) {
- 12       pcpp->pool[i] = globalmem.pool[globalmem.cur];
- 13       globalmem.pool[globalmem.cur--] = NULL;
- 14     }
- 15     pcpp->cur = i - 1;
- 16     spin_unlock(&globalmem.mutex);
- 17   }
- 18   if (pcpp->cur >= 0) {
- 19     p = pcpp->pool[pcpp->cur];
- 20     pcpp->pool[pcpp->cur--] = NULL;
- 21     return p;
- 22   }
- 23   return NULL;
- 24 }
-\end{verbbox}
-}
-\centering
-\theverbbox
+\input{CodeSamples/SMPdesign/smpalloc@xxxxxxxxx}
 \caption{Allocator-Cache Allocator Function}
 \label{lst:SMPdesign:Allocator-Cache Allocator Function}
 \end{listing}
 
 \subsubsection{Free Function}
 
+\begin{lineref}[ln:SMPdesign:smpalloc:free]
 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.
-
-If so, lines~8-15 empty half of the per-thread pool into the global pool,
-with lines~8 and~14 acquiring and releasing the spinlock.
-Lines~9-12 implement the loop moving blocks from the local to the
-global pool, and line~13 sets the per-thread pool's count to the proper
+Line~\lnref{get} gets a pointer to this thread's pool, and
+line~\lnref{chk:full} checks to see if this per-thread pool is full.
+
+If so, lines~\lnref{acq}-\lnref{empty:e} empty half of the per-thread pool
+into the global pool,
+with lines~\lnref{acq} and~\lnref{rel} acquiring and releasing the spinlock.
+Lines~\lnref{loop:b}-\lnref{loop:e} implement the loop moving blocks
+from the local to the
+global pool, and line~\lnref{set} sets the per-thread pool's count to the proper
 value.
 
-In either case, line~16 then places the newly freed block into the
+In either case, line~\lnref{place} then places the newly freed block into the
 per-thread pool.
+\end{lineref}
 
 \begin{listing}[tbp]
-{ \scriptsize
-\begin{verbbox}
-  1 void memblock_free(struct memblock *p)
-  2 {
-  3   int i;
-  4   struct percpumempool *pcpp;
-  5
-  6   pcpp = &__get_thread_var(percpumem);
-  7   if (pcpp->cur >= 2 * TARGET_POOL_SIZE - 1) {
-  8     spin_lock(&globalmem.mutex);
-  9     for (i = pcpp->cur; i >= TARGET_POOL_SIZE; i--) {
- 10       globalmem.pool[++globalmem.cur] = pcpp->pool[i];
- 11       pcpp->pool[i] = NULL;
- 12     }
- 13     pcpp->cur = i;
- 14     spin_unlock(&globalmem.mutex);
- 15   }
- 16   pcpp->pool[++pcpp->cur] = p;
- 17 }
-\end{verbbox}
-}
-\centering
-\theverbbox
+\input{CodeSamples/SMPdesign/smpalloc@xxxxxxxx}
 \caption{Allocator-Cache Free Function}
 \label{lst:SMPdesign:Allocator-Cache Free Function}
 \end{listing}
-- 
2.7.4





[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