renew
This commit is contained in:
195
source/module/monitor_timer.c
Normal file
195
source/module/monitor_timer.c
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "monitor_timer.h"
|
||||
|
||||
#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 hrTimer handler
|
||||
enum hrtimer_restart check_variable_cb(struct hrtimer *timer) {
|
||||
kernel_watch_timer *k_watch_timer =
|
||||
container_of(timer, kernel_watch_timer, hr_timer);
|
||||
int i = 0, j = 0;
|
||||
int buffer[TIMER_MAX_WATCH_NUM]; // Buffer to store the messages
|
||||
|
||||
// check all watched kernel_watch_arg
|
||||
for (i = 0; i < k_watch_timer->sentinel; i++) {
|
||||
if (read_and_compare(&k_watch_timer->k_watch_args[i])) {
|
||||
// snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "
|
||||
// name: %s, threshold: %lld, pid: %d\n",
|
||||
// k_watch_timer->k_watch_args[i].name,
|
||||
// k_watch_timer->k_watch_args[i].threshold,
|
||||
// k_watch_timer->k_watch_args[i].task_id);
|
||||
buffer[j] = i;
|
||||
j++;
|
||||
|
||||
// printk(KERN_INFO "j: name %s, threshold: %lld\n",
|
||||
// k_watch_timer->k_watch_args[i].name,
|
||||
// k_watch_timer->k_watch_args[i].threshold);
|
||||
// printk(KERN_INFO "j: %d\n", j);
|
||||
}
|
||||
}
|
||||
if (j > 0) // if any threshold reached
|
||||
{
|
||||
printk("-------------------------------------\n");
|
||||
printk("-------------watch monitor-----------\n");
|
||||
printk("Threshold reached:\n");
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
printk(" name: %s, threshold: %lld, pid: %d\n",
|
||||
k_watch_timer->k_watch_args[buffer[i]].name, //! todo
|
||||
k_watch_timer->k_watch_args[buffer[i]].threshold,
|
||||
k_watch_timer->k_watch_args[buffer[i]].task_id);
|
||||
}
|
||||
print_task_stack();
|
||||
// restart timer after 1s
|
||||
hrtimer_forward(timer, timer->base->get_time(), ktime_set(1, 0)); //! todo
|
||||
printk("-------------------------------------\n");
|
||||
} else {
|
||||
// keep frequency
|
||||
hrtimer_forward(timer, timer->base->get_time(), k_watch_timer->kt);
|
||||
}
|
||||
return HRTIMER_RESTART; // restart timer
|
||||
}
|
||||
|
||||
/// @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("HrTimer cancel,module keep %d hrtimer for now\n", kernel_wtimer_num);
|
||||
}
|
||||
Reference in New Issue
Block a user