summaryrefslogtreecommitdiff
path: root/source/module/monitor_timer.c
diff options
context:
space:
mode:
authorzy <[email protected]>2023-11-16 17:39:26 +0800
committerzy <[email protected]>2023-11-16 17:39:26 +0800
commit67b53ae0481872acd30be0541ff679a7f41c376d (patch)
tree207168afbf24d80b3e474ea961bfcf495270d09a /source/module/monitor_timer.c
parentbd277b53c5da993ba13ae7363d8b917c18912fa7 (diff)
renew
Diffstat (limited to 'source/module/monitor_timer.c')
-rw-r--r--source/module/monitor_timer.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/source/module/monitor_timer.c b/source/module/monitor_timer.c
new file mode 100644
index 0000000..ef40d94
--- /dev/null
+++ b/source/module/monitor_timer.c
@@ -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);
+} \ No newline at end of file