-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathwait_queue.c
More file actions
106 lines (83 loc) · 2.46 KB
/
wait_queue.c
File metadata and controls
106 lines (83 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// repo: aakbar5/handy-kernel_modules.git
// An example of wait_queue
// A recurring timer is called which sets
// the wait_queue condition after sometimes.
// Once wait_queue is signalled, delete the
// timer.
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/timer.h>
// Sleep time (mseconds)
static const unsigned long sleep_time = 1000;
// Structure having module related data
struct wq_info {
int timer_count;
int condition;
struct timer_list timer;
struct wait_queue_head wait_queue;
} *g_wq_info;
// Callback to perform work
static void timer_callback(struct timer_list *timer) {
struct wq_info *info = container_of(timer, struct wq_info, timer);
pr_info("wq: timer_callback -- called (timer_count: %d)\n", info->timer_count);
info->timer_count += 1;
if (info->timer_count > 10) {
info->condition += 1;
wake_up_interruptible_all(&info->wait_queue);
}
/* Re-enable timer */
mod_timer(&info->timer, jiffies + msecs_to_jiffies(sleep_time * 2));
}
//
// Module entry point
//
static int __init wq_init(void) {
pr_info("wq: init\n");
g_wq_info = kmalloc(sizeof(struct wq_info), GFP_KERNEL);
if (!g_wq_info) {
pr_err("Fail to allocate memory\n");
return -ENOMEM;
}
g_wq_info->timer_count = 0;
g_wq_info->condition = 0;
pr_info("wq: Init wait_queue...\n");
init_waitqueue_head(&g_wq_info->wait_queue);
pr_info("wq: Setup timer...\n");
timer_setup(&g_wq_info->timer, timer_callback, 0);
pr_info("wq: Setup timeout...\n");
mod_timer(&g_wq_info->timer, jiffies + msecs_to_jiffies(sleep_time));
pr_info("wq: Going to suspend until is not done...\n");
{
wait_event_interruptible(g_wq_info->wait_queue, g_wq_info->condition != 0);
pr_info("wq: wait_queue is signalled...\n");
pr_info("wq: delete timer...\n");
del_timer(&g_wq_info->timer);
}
pr_info("wq: init -- done\n");
return 0;
}
//
// Module exit point
//
static void __exit wq_exit(void) {
pr_info("wq: exit\n");
if (!g_wq_info)
return;
kfree(g_wq_info);
g_wq_info = NULL;
}
//
// Setup module entry and exit points
//
module_init(wq_init);
module_exit(wq_exit);
//
// Setup module info
//
MODULE_VERSION("0.0.1");
MODULE_DESCRIPTION("wq: wait_queue example");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("aakbar5 <16612387+aakbar5@users.noreply.github.com>");