#include "monitor_timer.h" // Global variable kernel_watch_timer kernel_wtimer_list[MAX_TIMER_NUM] = { 0}; // all kernel_watch_timer volatile 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..."); // printk(KERN_INFO "del kwarg kernel_wtimer_num:%d", kernel_wtimer_num); for (i = 0; i < kernel_wtimer_num; i++) { // printk(KERN_INFO "del watch i:%d", i); timer = &(kernel_wtimer_list[i]); timer_del_watch_by_pid(timer, pid); } // printk(KERN_INFO "del kwarg kernel_wtimer_num:%d", kernel_wtimer_num); for (i = 0; i < kernel_wtimer_num; i++) { // printk(KERN_INFO "del timer i:%d", i); timer = &(kernel_wtimer_list[i]); if (TIMER_NO_KWARG(timer)) // no available kwarg { // printk(KERN_INFO "del timer empty %d", i); // cancel and destroy timer.work // make sure empty timer has no work active cancel_work_sync(&timer->wk); destroy_work_on_stack(&timer->wk); 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) { 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 "ALL 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(KERN_INFO "HrTimer start,module keep %d hrtimer for now\n", kernel_wtimer_num); } /// @brief cancel hrTimer and stop all work /// @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); } /** * @brief cancel all work * */ void cancel_all_work(void) { int i = 0; kernel_watch_timer *timer = NULL; for (i = 0; i < kernel_wtimer_num; i++) { timer = &(kernel_wtimer_list[i]); cancel_work_sync(&timer->wk); } } /** * @brief destory all work * */ void cancel_destory_all_work(void) { int i = 0; kernel_watch_timer *timer = NULL; for (i = 0; i < kernel_wtimer_num; i++) { timer = &(kernel_wtimer_list[i]); cancel_work_sync(&timer->wk); destroy_work_on_stack(&timer->wk); } }