This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangyang-variable-monitor/source/module/monitor_timer.c

163 lines
4.7 KiB
C
Raw Normal View History

2023-11-16 17:39:26 +08:00
#include "monitor_timer.h"
2023-11-16 18:26:49 +08:00
// 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
2023-11-16 17:39:26 +08:00
#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
{
2023-11-27 01:18:15 -05:00
// cancel and destroy timer.work
// make sure empty timer has no work active
cancel_work_sync(&timer->wk);
destroy_work_on_stack(&timer->wk);
2023-11-16 17:39:26 +08:00
if (i != kernel_wtimer_num - 1) {
memcpy(timer, &kernel_wtimer_list[kernel_wtimer_num - 1],
sizeof(kernel_watch_timer));
}
kernel_wtimer_num--;
i--;
2023-11-27 01:18:15 -05:00
2023-11-16 17:39:26 +08:00
}
}
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);
}
2023-11-16 21:08:27 -05:00
printk(KERN_INFO "HrTimer cancel,module keep %d hrtimer for now\n", kernel_wtimer_num);
2023-11-16 17:39:26 +08:00
}