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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
#include "monitor_timer.h"
// Global variable
kernel_watch_timer kernel_wtimer_list[MAX_TIMER_NUM] = {
0}; // all kernel_watch_timer
int kernel_wtimer_num = 0; // current kernel_watch_timer number
EXPORT_SYMBOL(kernel_wtimer_list); // export kernel_watch_timer_list
EXPORT_SYMBOL(kernel_wtimer_num); // export kernel_watch_timer_num
#define TIMER_FILLED(timer) ((timer)->sentinel >= TIMER_MAX_WATCH_NUM)
#define TIMER_EMPTY(timer) (!((timer)->time_ns | (timer)->sentinel))
#define TIMER_NO_KWARG(timer) ((timer)->sentinel == 0)
unsigned char del_all_kwarg_by_pid(pid_t pid) {
int i = 0;
kernel_watch_timer *timer = NULL;
printk(KERN_INFO "del kwarg...");
for (i = 0; i < kernel_wtimer_num; i++) {
timer = &(kernel_wtimer_list[i]);
timer_del_watch_by_pid(timer, pid);
}
for (i = 0; i < kernel_wtimer_num; i++) {
timer = &(kernel_wtimer_list[i]);
if (TIMER_NO_KWARG(timer)) // no available kwarg
{
if (i != kernel_wtimer_num - 1) {
memcpy(timer, &kernel_wtimer_list[kernel_wtimer_num - 1],
sizeof(kernel_watch_timer));
}
kernel_wtimer_num--;
i--;
}
}
return 0;
}
/// @brief get a valuable timer
/// @param time_ns
/// @return kernel_watch_timer *, NULL means fail
kernel_watch_timer *get_timer(unsigned long long time_ns) {
int i = 0;
kernel_watch_timer *timer = NULL;
// chose a timer
for (i = 0; i < kernel_wtimer_num; i++) {
timer = &kernel_wtimer_list[i];
if (TIMER_EMPTY(timer)) {
break;
}
if ((timer->time_ns == time_ns) && (!TIMER_FILLED(timer))) {
break;
}
}
// if all timer is full
if (i >= MAX_TIMER_NUM) {
printk(KERN_ERR "No timer available\n");
return NULL;
}
// if a new timer, init it
if (i > kernel_wtimer_num - 1) {
printk(KERN_INFO "New timer\n");
kernel_wtimer_list[i].time_ns = time_ns;
kernel_wtimer_list[i].sentinel = 0;
kernel_wtimer_list[i].kt = ktime_set(0, (unsigned long)time_ns); // ns
// CLOCK_MONOTONIC: time since boot | HRTIMER_MODE_REL : relative time
hrtimer_init(&(kernel_wtimer_list[i].hr_timer), CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
kernel_wtimer_list[i].hr_timer.function =
check_variable_cb; // callback function
kernel_wtimer_num = i + 1;
}
printk(KERN_INFO "now, we have %d timers\n", kernel_wtimer_num);
return &kernel_wtimer_list[i];
}
/// @brief hrTimer add watch
/// @param timer
/// @param k_watch_arg
/// @return 0 is success
unsigned char timer_add_watch(kernel_watch_timer *timer,
kernel_watch_arg k_watch_arg) {
if (TIMER_FILLED(timer)) {
printk(KERN_ERR "Timer is full\n");
return -1;
}
memcpy(&timer->k_watch_args[timer->sentinel], &k_watch_arg,
sizeof(k_watch_arg));
// timer->k_watch_args[timer->sentinel] = k_watch_arg;
timer->sentinel++;
return 0;
}
unsigned char timer_del_watch_by_pid(kernel_watch_timer *timer, pid_t pid) {
int i = 0;
for (i = 0; i < timer->sentinel; i++) {
// if pid match, delete it and move the last one to this position, check
// again
if (timer->k_watch_args[i].task_id == pid) {
if (i != timer->sentinel - 1) {
memcpy(&timer->k_watch_args[i],
&timer->k_watch_args[timer->sentinel - 1],
sizeof(kernel_watch_arg));
}
timer->sentinel--;
i--;
}
}
return 0;
}
/// @brief start hrTimer
/// @param timeout: timeout in us
/// @return 0 is success
// int start_hrTimer(unsigned long timeout)
// {
// printk("HrTimer Start\n");
// kt = ktime_set(0, (unsigned long)timeout); // us -> ns
// // CLOCK_MONOTONIC: time since boot | HRTIMER_MODE_REL : relative time
// hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
// hr_timer.function = check_variable_cb;
// // mode the same as hrtimer_init
// hrtimer_start(&hr_timer, kt, HRTIMER_MODE_REL);
// return 0;
// }
/// @brief start all hrTimer
/// @param
void start_all_hrTimer(void) {
int i = 0;
kernel_watch_timer *timer = NULL;
for (i = 0; i < kernel_wtimer_num; i++) {
timer = &(kernel_wtimer_list[i]);
TIMER_START(timer);
}
printk("HrTimer start,module keep %d hrtimer for now\n", kernel_wtimer_num);
}
/// @brief cancel hrTimer
/// @param
void cancel_all_hrTimer(void) {
int i = 0;
kernel_watch_timer *timer = NULL;
for (i = 0; i < kernel_wtimer_num; i++) {
timer = &(kernel_wtimer_list[i]);
TIMER_CANCEL(timer);
}
printk(KERN_INFO "HrTimer cancel,module keep %d hrtimer for now\n", kernel_wtimer_num);
}
|