Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2d23563

Browse files
committed
Add RCU locking while iterating over task structs; thanks to @iwoeruhsdfwoi
PacktPublishing#11
1 parent 7c72a6e commit 2d23563

File tree

2 files changed

+35
-11
lines changed

2 files changed

+35
-11
lines changed

ch6/foreach/prcs_showall/prcs_showall.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ static int show_prcs_in_tasklist(void)
4848
char hdr[] = " Name | TGID | PID | RUID | EUID";
4949

5050
pr_info("%s\n", &hdr[0]);
51+
/*
52+
* The for_each_process() is a macro that iterates over the task structures in memory.
53+
* The task structs are global of course; this implies we should hold a lock of some
54+
* sort while working on them (even if only reading!). So, doing
55+
* read_lock(&tasklist_lock);
56+
* [...]
57+
* read_unlock(&tasklist_lock);
58+
* BUT, this lock - tasklist_lock - isn't exported and thus unavailable to modules.
59+
* So, using an RCU read lock is indicated here (this has been added later to this code).
60+
* FYI: a) Ch 12 and Ch 13 cover the details on kernel synchronization.
61+
* b) Read Copy Update (RCU) is a complex synchronization mechanism; it's
62+
* conceptually explained really well within this blog article:
63+
* https://reberhardt.com/blog/2020/11/18/my-first-kernel-module.html
64+
*/
65+
rcu_read_lock();
5166
for_each_process(p) {
5267
memset(tmp, 0, 128);
5368
n = snprintf(tmp, 128, "%-16s|%8d|%8d|%7u|%7u\n", p->comm, p->tgid, p->pid,
@@ -64,6 +79,7 @@ static int show_prcs_in_tasklist(void)
6479
cond_resched();
6580
total++;
6681
} // for_each_process()
82+
rcu_read_unlock();
6783

6884
return total;
6985
}

ch6/foreach/thrd_showall/thrd_showall.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,25 @@ static int showthrds(void)
6262
"------------------------------------------------------------------------------------------\n";
6363

6464
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]);
7266
disp_idle_thread();
7367

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();
7484
do_each_thread(g, t) { /* 'g' : process ptr; 't': thread ptr */
7585
task_lock(t);
7686

@@ -121,10 +131,8 @@ static int showthrds(void)
121131
memset(tmp, 0, sizeof(tmp));
122132
task_unlock(t);
123133
} 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+
128136
return total;
129137
}
130138

0 commit comments

Comments
 (0)