summaryrefslogtreecommitdiff
path: root/source/module/monitor_perf.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/module/monitor_perf.c')
-rw-r--r--source/module/monitor_perf.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/source/module/monitor_perf.c b/source/module/monitor_perf.c
new file mode 100644
index 0000000..549d7ac
--- /dev/null
+++ b/source/module/monitor_perf.c
@@ -0,0 +1,102 @@
+#include "monitor_perf.h"
+
+static struct perf_event *pe;
+
+void vm_perf_overflow_callback(struct perf_event *event,
+ struct perf_sample_data *data,
+ struct pt_regs *regs) {
+ // handle perf event data
+ // struct perf_callchain_entry *callchain;
+ // int nr, i;
+
+ pr_info("perf event callback\n");
+
+ // 如果 perf_sample_data 有调用堆栈信息
+ // if (data->callchain) {
+ // callchain = data->callchain;
+ // nr = callchain->nr; // 调用堆栈的长度
+
+ // // 遍历堆栈条目并处理它们
+ // for (i = 0; i < nr; i++) {
+ // // callchain->ip[i] 包含了堆栈的每个条目
+ // // 在这里可以调用 to_buff 将堆栈信息写入缓冲区
+ // // to_buff(&callchain->ip[i], sizeof(callchain->ip[i]));
+ // pr_info("callchain->ip[%d] = %llx\n", i, callchain->ip[i]);
+ // }
+ // }
+}
+
+// static struct perf_event_attr pea = {
+// .type = PERF_TYPE_SOFTWARE, // software event
+// .size = sizeof(struct perf_event_attr), // size of attr
+// .config = PERF_COUNT_SW_CPU_CLOCK, // no care
+// PERF_COUNT_SW_DUMMY PERF_COUNT_SW_CPU_CLOCK .sample_period = 1, // sample
+// every 1 event .sample_type =
+// PERF_SAMPLE_CALLCHAIN, // sample callchain | means include stacktrace
+// // .exclude_kernel = 1, // no kernel stacktrace | may need to change
+// after test
+// // .exclude_hv = 1, // no hypervisor stacktrace | may need to change
+// after test .disabled = 0, // disabled at first
+// };
+
+struct perf_event_attr pea = {
+ .type = PERF_TYPE_SOFTWARE,
+ .size = sizeof(struct perf_event_attr),
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ .sample_period = 1,
+ .sample_type = PERF_SAMPLE_CALLCHAIN,
+ // .disabled = 1,
+};
+
+#include <linux/cpumask.h>
+#include <linux/smp.h>
+/**
+ * @brief Set the up perf event for task object
+ *
+ * @param tsk
+ */
+void setup_perf_event_for_task(struct task_struct *tsk) {
+ pr_info("setup_perf_event_for_task: cpu = %d\n", tsk->on_cpu);
+ if (pe) {
+ pr_info("Perf event already created\n");
+ return;
+ }
+ int cpu;
+ struct perf_event **events;
+ for_each_possible_cpu(cpu) {
+ struct perf_event **event = per_cpu_ptr(events, cpu);
+ if (cpu_is_offline(cpu)) {
+ *event = NULL;
+ continue;
+ }
+ *event = perf_event_create_kernel_counter(&pea, cpu, tsk,
+ vm_perf_overflow_callback, NULL);
+ if (IS_ERR(*event)) {
+ printk(KERN_INFO "create perf event failure\n");
+ // return -1;
+ }
+ }
+
+ // pe = perf_event_create_kernel_counter(&pea, tsk->on_cpu, tsk,
+ // vm_perf_callback, NULL);
+ pe = perf_event_create_kernel_counter(&pea, tsk->on_cpu, tsk,
+ vm_perf_overflow_callback, NULL);
+ if (IS_ERR(pe)) {
+ pr_info("Error in perf_event_create_kernel_counter\n");
+ return;
+ }
+
+ // perf_event_enable(pe); // enable perf event
+}
+
+/**
+ * @brief Disable perf event
+ *
+ */
+void cleanup_perf_event(void) {
+ if (pe) {
+ perf_event_disable(pe);
+ perf_event_release_kernel(pe);
+ pe = NULL;
+ }
+} \ No newline at end of file