Browse Source

Merge pull request #234 from mechanicalamit/completions-simplify

Simplify code by removal of outer struct encapsulating struct completions
Jim Huang 1 năm trước cách đây
mục cha
commit
7f88a37f09
2 tập tin đã thay đổi với 22 bổ sung21 xóa
  1. 13 15
      examples/completions.c
  2. 9 6
      lkmpg.tex

+ 13 - 15
examples/completions.c

@@ -9,34 +9,32 @@
 #include <linux/printk.h>
 #include <linux/version.h>
 
-static struct {
-    struct completion crank_comp;
-    struct completion flywheel_comp;
-} machine;
+static struct completion crank_comp;
+static struct completion flywheel_comp;
 
 static int machine_crank_thread(void *arg)
 {
     pr_info("Turn the crank\n");
 
-    complete_all(&machine.crank_comp);
+    complete_all(&crank_comp);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
-    kthread_complete_and_exit(&machine.crank_comp, 0);
+    kthread_complete_and_exit(&crank_comp, 0);
 #else
-    complete_and_exit(&machine.crank_comp, 0);
+    complete_and_exit(&crank_comp, 0);
 #endif
 }
 
 static int machine_flywheel_spinup_thread(void *arg)
 {
-    wait_for_completion(&machine.crank_comp);
+    wait_for_completion(&crank_comp);
 
     pr_info("Flywheel spins up\n");
 
-    complete_all(&machine.flywheel_comp);
+    complete_all(&flywheel_comp);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
-    kthread_complete_and_exit(&machine.flywheel_comp, 0);
+    kthread_complete_and_exit(&flywheel_comp, 0);
 #else
-    complete_and_exit(&machine.flywheel_comp, 0);
+    complete_and_exit(&flywheel_comp, 0);
 #endif
 }
 
@@ -47,8 +45,8 @@ static int __init completions_init(void)
 
     pr_info("completions example\n");
 
-    init_completion(&machine.crank_comp);
-    init_completion(&machine.flywheel_comp);
+    init_completion(&crank_comp);
+    init_completion(&flywheel_comp);
 
     crank_thread = kthread_create(machine_crank_thread, NULL, "KThread Crank");
     if (IS_ERR(crank_thread))
@@ -73,8 +71,8 @@ ERROR_THREAD_1:
 
 static void __exit completions_exit(void)
 {
-    wait_for_completion(&machine.crank_comp);
-    wait_for_completion(&machine.flywheel_comp);
+    wait_for_completion(&crank_comp);
+    wait_for_completion(&flywheel_comp);
 
     pr_info("completions exit\n");
 }

+ 9 - 6
lkmpg.tex

@@ -1645,16 +1645,19 @@ $
 Sometimes one thing should happen before another within a module having multiple threads.
 Rather than using \sh|/bin/sleep| commands, the kernel has another way to do this which allows timeouts or interrupts to also happen.
 
-In the following example two threads are started, but one needs to start before another.
+Completions as code synchronization mechanism have three main parts, initialization of struct completion synchronization object, the waiting or barrier part through \cpp|wait_for_completion()|, and the signalling side through a call to \cpp|complete()|.
 
-\samplec{examples/completions.c}
-
-The \cpp|machine| structure stores the completion states for the two threads.
+In the subsequent example, two threads are initiated: crank and flywheel. 
+It is imperative that the crank thread starts before the flywheel thread. 
+A completion state is established for each of these threads, with a distinct completion defined for both the crank and flywheel threads.
 At the exit point of each thread the respective completion state is updated, and \cpp|wait_for_completion| is used by the flywheel thread to ensure that it does not begin prematurely.
+The crank thread uses the \cpp|complete_all()| function to update the completion, which lets the flywheel thread continue.
 
-So even though \cpp|flywheel_thread| is started first you should notice if you load this module and run \sh|dmesg| that turning the crank always happens first because the flywheel thread waits for it to complete.
+So even though \cpp|flywheel_thread| is started first you should notice when you load this module and run \sh|dmesg|, that turning the crank always happens first because the flywheel thread waits for the crank thread to complete.
 
-There are other variations upon the \cpp|wait_for_completion| function, which include timeouts or being interrupted, but this basic mechanism is enough for many common situations without adding a lot of complexity.
+There are other variations of the \cpp|wait_for_completion| function, which include timeouts or being interrupted, but this basic mechanism is enough for many common situations without adding a lot of complexity.
+
+\samplec{examples/completions.c}
 
 \section{Avoiding Collisions and Deadlocks}
 \label{sec:synchronization}