Skip to content

Commit 4efec6c

Browse files
Zi Liakpm00
authored andcommitted
samples: enhance hung_task detector test with read-write semaphore support
Extend the hung_task detector test module to include read-write semaphore support alongside existing mutex and semaphore tests. This module now creates additional debugfs files under <debugfs>/hung_task, namely 'rw_semaphore_read' and 'rw_semaphore_write', in addition to 'mutex' and 'semaphore'. Reading these files with multiple processes triggers a prolonged sleep (256 seconds) while holding the respective lock, enabling hung_task detector testing for various locking mechanisms. This change builds on the extensible hung_task_tests module, adding read-write semaphore functionality to improve test coverage for kernel locking primitives. The implementation ensures proper lock handling and includes checks to prevent redundant data reads. Usage is: > cd /sys/kernel/debug/hung_task > cat mutex & cat mutex # Test mutex blocking > cat semaphore & cat semaphore # Test semaphore blocking > cat rw_semaphore_write \ & cat rw_semaphore_read # Test rwsem blocking > cat rw_semaphore_write \ & cat rw_semaphore_write # Test rwsem blocking Update the Kconfig description to reflect the addition of read-write semaphore debugfs files. Link: https://lkml.kernel.org/r/20250627072924.36567-4-lance.yang@linux.dev Signed-off-by: Zi Li <zi.li@linux.dev> Suggested-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Cc: Anna Schumaker <anna.schumaker@oracle.com> Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Joel Granados <joel.granados@kernel.org> Cc: John Stultz <jstultz@google.com> Cc: Kent Overstreet <kent.overstreet@linux.dev> Cc: Mingzhe Yang <mingzhe.yang@ly.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tomasz Figa <tfiga@chromium.org> Cc: Waiman Long <longman@redhat.com> Cc: Will Deacon <will@kernel.org> Cc: Yongliang Gao <leonylgao@tencent.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 77da18d commit 4efec6c

2 files changed

Lines changed: 77 additions & 11 deletions

File tree

samples/Kconfig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,9 @@ config SAMPLE_HUNG_TASK
316316
depends on DETECT_HUNG_TASK && DEBUG_FS
317317
help
318318
Build a module that provides debugfs files (e.g., mutex, semaphore,
319-
etc.) under <debugfs>/hung_task. If user reads one of these files,
320-
it will sleep long time (256 seconds) with holding a lock. Thus,
321-
if 2 or more processes read the same file concurrently, it will
322-
be detected by the hung_task watchdog.
319+
rw_semaphore_read, rw_semaphore_write) under <debugfs>/hung_task.
320+
Reading these files with multiple processes triggers hung task
321+
detection by holding locks for a long time (256 seconds).
323322

324323
source "samples/rust/Kconfig"
325324

samples/hung_task/hung_task_tests.c

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
* semaphore, etc.
55
*
66
* Usage: Load this module and read `<debugfs>/hung_task/mutex`,
7-
* `<debugfs>/hung_task/semaphore`, etc., with 2 or more processes.
7+
* `<debugfs>/hung_task/semaphore`, `<debugfs>/hung_task/rw_semaphore_read`,
8+
* `<debugfs>/hung_task/rw_semaphore_write`, etc., with 2 or more processes.
89
*
910
* This is for testing kernel hung_task error messages with various locking
10-
* mechanisms (e.g., mutex, semaphore, etc.). Note that this may freeze
11-
* your system or cause a panic. Use only for testing purposes.
11+
* mechanisms (e.g., mutex, semaphore, rw_semaphore_read, rw_semaphore_write, etc.).
12+
* Note that this may freeze your system or cause a panic. Use only for testing purposes.
1213
*/
1314

1415
#include <linux/debugfs.h>
@@ -17,21 +18,29 @@
1718
#include <linux/module.h>
1819
#include <linux/mutex.h>
1920
#include <linux/semaphore.h>
21+
#include <linux/rwsem.h>
2022

21-
#define HUNG_TASK_DIR "hung_task"
22-
#define HUNG_TASK_MUTEX_FILE "mutex"
23-
#define HUNG_TASK_SEM_FILE "semaphore"
24-
#define SLEEP_SECOND 256
23+
#define HUNG_TASK_DIR "hung_task"
24+
#define HUNG_TASK_MUTEX_FILE "mutex"
25+
#define HUNG_TASK_SEM_FILE "semaphore"
26+
#define HUNG_TASK_RWSEM_READ_FILE "rw_semaphore_read"
27+
#define HUNG_TASK_RWSEM_WRITE_FILE "rw_semaphore_write"
28+
#define SLEEP_SECOND 256
2529

2630
static const char dummy_string[] = "This is a dummy string.";
2731
static DEFINE_MUTEX(dummy_mutex);
2832
static DEFINE_SEMAPHORE(dummy_sem, 1);
33+
static DECLARE_RWSEM(dummy_rwsem);
2934
static struct dentry *hung_task_dir;
3035

3136
/* Mutex-based read function */
3237
static ssize_t read_dummy_mutex(struct file *file, char __user *user_buf,
3338
size_t count, loff_t *ppos)
3439
{
40+
/* Check if data is already read */
41+
if (*ppos >= sizeof(dummy_string))
42+
return 0;
43+
3544
/* Second task waits on mutex, entering uninterruptible sleep */
3645
guard(mutex)(&dummy_mutex);
3746

@@ -46,6 +55,10 @@ static ssize_t read_dummy_mutex(struct file *file, char __user *user_buf,
4655
static ssize_t read_dummy_semaphore(struct file *file, char __user *user_buf,
4756
size_t count, loff_t *ppos)
4857
{
58+
/* Check if data is already read */
59+
if (*ppos >= sizeof(dummy_string))
60+
return 0;
61+
4962
/* Second task waits on semaphore, entering uninterruptible sleep */
5063
down(&dummy_sem);
5164

@@ -58,6 +71,46 @@ static ssize_t read_dummy_semaphore(struct file *file, char __user *user_buf,
5871
sizeof(dummy_string));
5972
}
6073

74+
/* Read-write semaphore read function */
75+
static ssize_t read_dummy_rwsem_read(struct file *file, char __user *user_buf,
76+
size_t count, loff_t *ppos)
77+
{
78+
/* Check if data is already read */
79+
if (*ppos >= sizeof(dummy_string))
80+
return 0;
81+
82+
/* Acquires read lock, allowing concurrent readers but blocks if write lock is held */
83+
down_read(&dummy_rwsem);
84+
85+
/* Sleeps here, potentially triggering hung task detection if lock is held too long */
86+
msleep_interruptible(SLEEP_SECOND * 1000);
87+
88+
up_read(&dummy_rwsem);
89+
90+
return simple_read_from_buffer(user_buf, count, ppos, dummy_string,
91+
sizeof(dummy_string));
92+
}
93+
94+
/* Read-write semaphore write function */
95+
static ssize_t read_dummy_rwsem_write(struct file *file, char __user *user_buf,
96+
size_t count, loff_t *ppos)
97+
{
98+
/* Check if data is already read */
99+
if (*ppos >= sizeof(dummy_string))
100+
return 0;
101+
102+
/* Acquires exclusive write lock, blocking all other readers and writers */
103+
down_write(&dummy_rwsem);
104+
105+
/* Sleeps here, potentially triggering hung task detection if lock is held too long */
106+
msleep_interruptible(SLEEP_SECOND * 1000);
107+
108+
up_write(&dummy_rwsem);
109+
110+
return simple_read_from_buffer(user_buf, count, ppos, dummy_string,
111+
sizeof(dummy_string));
112+
}
113+
61114
/* File operations for mutex */
62115
static const struct file_operations hung_task_mutex_fops = {
63116
.read = read_dummy_mutex,
@@ -68,6 +121,16 @@ static const struct file_operations hung_task_sem_fops = {
68121
.read = read_dummy_semaphore,
69122
};
70123

124+
/* File operations for rw_semaphore read */
125+
static const struct file_operations hung_task_rwsem_read_fops = {
126+
.read = read_dummy_rwsem_read,
127+
};
128+
129+
/* File operations for rw_semaphore write */
130+
static const struct file_operations hung_task_rwsem_write_fops = {
131+
.read = read_dummy_rwsem_write,
132+
};
133+
71134
static int __init hung_task_tests_init(void)
72135
{
73136
hung_task_dir = debugfs_create_dir(HUNG_TASK_DIR, NULL);
@@ -79,6 +142,10 @@ static int __init hung_task_tests_init(void)
79142
&hung_task_mutex_fops);
80143
debugfs_create_file(HUNG_TASK_SEM_FILE, 0400, hung_task_dir, NULL,
81144
&hung_task_sem_fops);
145+
debugfs_create_file(HUNG_TASK_RWSEM_READ_FILE, 0400, hung_task_dir, NULL,
146+
&hung_task_rwsem_read_fops);
147+
debugfs_create_file(HUNG_TASK_RWSEM_WRITE_FILE, 0400, hung_task_dir, NULL,
148+
&hung_task_rwsem_write_fops);
82149

83150
return 0;
84151
}

0 commit comments

Comments
 (0)