@@ -62,15 +62,25 @@ static int showthrds(void)
62
62
"------------------------------------------------------------------------------------------\n" ;
63
63
64
64
pr_info ("%s" , hdr );
65
- #if 0
66
- /* the tasklist_lock reader-writer spinlock for the task list 'should'
67
- * be used here, but, it's not exported, hence unavailable to our kernel module
68
- */
69
- read_lock (& tasklist_lock );
70
- #endif
71
-
65
+ pr_info ("%s\n" , & hdr [0 ]);
72
66
disp_idle_thread ();
73
67
68
+ /*
69
+ * The do_each_thread() / while_each_thread() is a pair of macros that iterates over
70
+ * _all_ task structures in memory.
71
+ * The task structs are global of course; this implies we should hold a lock of some
72
+ * sort while working on them (even if only reading!). So, doing
73
+ * read_lock(&tasklist_lock);
74
+ * [...]
75
+ * read_unlock(&tasklist_lock);
76
+ * BUT, this lock - tasklist_lock - isn't exported and thus unavailable to modules.
77
+ * So, using an RCU read lock is indicated here (this has been added later to this code).
78
+ * FYI: a) Ch 12 and Ch 13 cover the details on kernel synchronization.
79
+ * b) Read Copy Update (RCU) is a complex synchronization mechanism; it's
80
+ * conceptually explained really well within this blog article:
81
+ * https://reberhardt.com/blog/2020/11/18/my-first-kernel-module.html
82
+ */
83
+ rcu_read_lock ();
74
84
do_each_thread (g , t ) { /* 'g' : process ptr; 't': thread ptr */
75
85
task_lock (t );
76
86
@@ -121,10 +131,8 @@ static int showthrds(void)
121
131
memset (tmp , 0 , sizeof (tmp ));
122
132
task_unlock (t );
123
133
} while_each_thread (g , t );
124
- #if 0
125
- /* <same as above, reg the reader-writer spinlock for the task list> */
126
- read_unlock (& tasklist_lock );
127
- #endif
134
+ rcu_read_unlock ();
135
+
128
136
return total ;
129
137
}
130
138
0 commit comments