[bootlin/training-materials updates] master: kernel: concurrency: Add slides to explain how to use RCU (ead79c39)
Miquel Raynal
miquel.raynal at bootlin.com
Tue Oct 18 17:33:33 CEST 2022
Repository : https://github.com/bootlin/training-materials
On branch : master
Link : https://github.com/bootlin/training-materials/commit/ead79c39fcd2acbd181a3f49901e81991c53ab7b
>---------------------------------------------------------------
commit ead79c39fcd2acbd181a3f49901e81991c53ab7b
Author: Miquel Raynal <miquel.raynal at bootlin.com>
Date: Tue Oct 18 17:33:33 2022 +0200
kernel: concurrency: Add slides to explain how to use RCU
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
>---------------------------------------------------------------
ead79c39fcd2acbd181a3f49901e81991c53ab7b
.../kernel-driver-development-concurrency.tex | 94 ++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/slides/kernel-driver-development-concurrency/kernel-driver-development-concurrency.tex b/slides/kernel-driver-development-concurrency/kernel-driver-development-concurrency.tex
index 7b041d6f..9d2f846d 100644
--- a/slides/kernel-driver-development-concurrency/kernel-driver-development-concurrency.tex
+++ b/slides/kernel-driver-development-concurrency/kernel-driver-development-concurrency.tex
@@ -266,6 +266,100 @@ static unsigned int ulite_tx_empty(struct uart_port *port) {
\end{itemize}
\end{frame}
+\begin{frame}[fragile]
+ \frametitle{RCU API}
+ \begin{itemize}
+ \item Conditions where RCU is useful:
+ \begin{itemize}
+ \item Synchronization between many readers vs. one writer
+ \item Focus on getting consistent data rather than getting the
+ latest data
+ \end{itemize}
+ \item Kind of enforces ownership by enforcing space/time synchronization
+ \item RCU API (\kfile{Documentation/RCU/whatisRCU.rst}):
+ \begin{itemize}
+ \item \kfunc{rcu_read_lock} and \kfunc{rcu_read_unlock}:
+ reclaim/release read access
+ \item \kfunc{synchronize_rcu} or \kfunc{call_rcu}: wait for
+ pre-existing readers
+ \item \kfunc{rcu_assign_pointer}: update RCU-protected pointer
+ \item \kfunc{rcu_dereference}: load RCU-protected pointer
+ \end{itemize}
+ \item RCU mentorship session by Paul E. McKenney:
+ \url{https://youtu.be/K-4TI5gFsig}
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{RCU protected reads: accessing structure members in a consistent way}
+ \begin{block}{Unsafe read}
+ \begin{minted}[fontsize=\tiny]{c}
+struct myconf { int a, b; } *current_conf; /* initialized */
+
+unsafe_get(int *cur_a, int *cur_b)
+{
+ *cur_a = current_conf->a;
+ /* What if *current_conf gets updated now? The assignement is inconsistent! */
+ *cur_b = current_conf->b;
+};
+ \end{minted}
+ \end{block}
+ \begin{block}{Safe read}
+ \begin{minted}[fontsize=\tiny]{c}
+struct myconf { int a, b; } *current_conf; /* initialized */
+
+safe_get(int *cur_a, int *cur_b)
+{
+ struct myconf *conf;
+
+ rcu_read_lock();
+ conf = rcu_dereference(current_conf);
+ *cur_a = conf->a;
+ /* If *current_conf is updated, conf->a and conf->b will remain consistent! */
+ *cur_b = conf->b;
+ rcu_read_unlock();
+};
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{RCU protected writes: updating a pointer in a consistent way}
+ \begin{block}{Unsafe write}
+ \begin{minted}[fontsize=\tiny]{c}
+struct myconf { int a, b; } *current_conf; /* initialized */
+
+unsafe_set(int cur_a, int cur_b)
+{
+ struct myconf *newconf = kmalloc(...), *oldconf;
+ newconf->a = cur_a, newconf->b = cur_b;
+
+ oldconf = current_conf;
+ current_conf = newconf;
+ kfree(oldconf); /* Readers might still have a reference over the freed struct! */
+};
+ \end{minted}
+ \end{block}
+ \begin{block}{Safe write}
+ \begin{minted}[fontsize=\tiny]{c}
+struct myconf { int a, b; } *current_conf; /* initialized */
+
+safe_set(int cur_a, int cur_b)
+{
+ struct myconf *newconf = kmalloc(...), *oldconf;
+ newconf->a = cur_a, newconf->b = cur_b;
+
+ oldconf = rcu_dereference(current_conf);
+ rcu_assign_pointer(current_conf, newconf);
+ /* Readers might still have a reference over the old struct here... */
+ synchronize_rcu();
+ /* ...but not here! No more readers of the old struct, kfree() is safe! */
+ kfree(oldconf);
+};
+ \end{minted}
+ \end{block}
+\end{frame}
+
\begin{frame}[fragile]
\frametitle{Atomic variables 1/2}
\mint{c}+#include <linux/atomic.h>+
More information about the training-materials-updates
mailing list