From d097868e15c81be64b21b04a67a3d994f5c6e2fd Mon Sep 17 00:00:00 2001 From: myfortune110 <492102051@qq.com> Date: Tue, 1 Jul 2025 09:02:58 +0800 Subject: [PATCH] add osprobe to systrace main --- systrace/build.sh | 6 + systrace/client/sysTracecli.cpp | 6 +- .../convert/conver_osprobe_to_timeline.py | 119 +++++++++++------- systrace/include/common/shared_constants.c | 16 +++ systrace/include/common/shared_constants.h | 6 + systrace/server/monitor_server.cpp | 18 ++- systrace/src/os/bpf_comm.h | 40 ++++++ systrace/src/os/os_probe.c | 117 ++++++++++------- systrace/src/os/os_probe.h | 4 +- systrace/src/trace/systrace_manager.cc | 23 +++- systrace/src/trace/systrace_manager.h | 2 + 11 files changed, 256 insertions(+), 101 deletions(-) diff --git a/systrace/build.sh b/systrace/build.sh index 9c177e1..65495c9 100644 --- a/systrace/build.sh +++ b/systrace/build.sh @@ -2,6 +2,12 @@ sudo dnf remove -y libunwind libunwind-devel 2>/dev/null || true mkdir -p build +mkdir -p /etc/systrace/config +rm /sys/fs/bpf/sysTrace -rf +mount -t bpf bpf /sys/fs/bpf/ +rm src/os/*.o -rf +rm src/os/*.skel.h -rf + cp -f config/PyFuncList /etc/systrace/config/PyFuncList cd protos diff --git a/systrace/client/sysTracecli.cpp b/systrace/client/sysTracecli.cpp index 331b187..d89c057 100644 --- a/systrace/client/sysTracecli.cpp +++ b/systrace/client/sysTracecli.cpp @@ -10,11 +10,11 @@ void print_help() { std::cout << "Usage: sysTrace_client [args]\n" << "Commands:\n" << " set = - Enable/disable dump level\n" - << " (levels: L0, L1, L2)\n" + << " (levels: L0, L1, L2, L3)\n" << " interval = - Set dump interval in minutes\n" - << " (levels: L1, L2)\n" + << " (levels: L1, L2, L3)\n" << " print [level|all] - Print current settings\n" - << " (levels: L0, L1, L2, all)\n\n" + << " (levels: L0, L1, L2, L3, all)\n\n" << "Examples:\n" << " sysTrace_cli set L1=true\n" << " sysTrace_cli interval L1=10\n" diff --git a/systrace/convert/conver_osprobe_to_timeline.py b/systrace/convert/conver_osprobe_to_timeline.py index 1ba9630..57e1ae5 100644 --- a/systrace/convert/conver_osprobe_to_timeline.py +++ b/systrace/convert/conver_osprobe_to_timeline.py @@ -1,7 +1,9 @@ +from tqdm import tqdm +from multiprocessing import Pool, cpu_count +import glob import json -import systrace_pb2 import argparse -import glob +import systrace_pb2 from collections import defaultdict event_type_dic = { @@ -11,57 +13,74 @@ event_type_dic = { 3: "vmscan", 4: "offcpu", 5: "unknown" - } +} -def process_timeline_file(input_path, trace_data): +def process_single_file(input_path): + trace_events = [] + cpu_trace_events = [] last_delay = {} rank_acl = defaultdict(list) rank_acl_count = defaultdict(int) - min_acl_thread = float('inf') delay = 0 - with open(input_path, "rb") as f: - osprobe_data = systrace_pb2.OSprobe() - osprobe_data.ParseFromString(f.read()) - + + try: + with open(input_path, "rb") as f: + osprobe_data = systrace_pb2.OSprobe() + osprobe_data.ParseFromString(f.read()) + except Exception as e: + print(f"[ERROR] Failed to process file '{input_path}': {e}") + return [] + for entry in osprobe_data.OSprobe_entries: - if entry.OS_event_type == 4: - if f"{entry.comm}: {entry.key}" in last_delay: - delay = entry.rundelay - last_delay[f"{entry.comm}: {entry.key}"] - last_delay[f"{entry.comm}: {entry.key}"] = entry.rundelay - if entry.comm == "ACL_thread": - rank_acl_count[entry.key] += 1 - rank_acl[entry.key].append({ + if entry.OS_event_type in [1, 2, 3]: + cpu_trace_events.append({ "name": event_type_dic[entry.OS_event_type], "cat": "osprobe", "ph": "X", - "pid": entry.rank if entry.OS_event_type in [0, 4] else f"CPU: {entry.key}", + "pid": entry.rank if entry.OS_event_type in [0, 4] else f"Rank: {entry.rank} CPU: {entry.key}", "tid": f"{entry.comm}: {entry.key}" if entry.OS_event_type in [0, 4] else entry.key , "ts": entry.start_us, "dur": entry.dur, + "args": { + "cpu_rundelay": delay, + "next_comm": entry.nxt_comm, + "next_pid": entry.nxt_pid + } if entry.OS_event_type == 4 else {} + }) + else: + if entry.OS_event_type == 4: + key_str = f"{entry.comm}: {entry.key}" + if key_str in last_delay: + delay = entry.rundelay - last_delay[key_str] + last_delay[key_str] = entry.rundelay + + event = { + "name": event_type_dic.get(entry.OS_event_type, "unknown"), + "cat": "osprobe", + "ph": "X", + "pid": entry.rank if entry.OS_event_type != 1 else f"Rank: {entry.rank} CPU: {entry.key}", + "tid": f"{entry.comm}: {entry.key}" if entry.OS_event_type != 1 else entry.key, + "ts": entry.start_us, + "dur": entry.dur, "args": { "cpu_rundelay": delay, "sus_comm": entry.nxt_comm, "sus_pid": entry.nxt_pid } if entry.OS_event_type == 4 else {} - }) - continue + } + + if entry.comm.lower() == "acl_thread": + rank_acl_count[entry.key] += 1 + rank_acl[entry.key].append(event) + else: + trace_events.append(event) + + if rank_acl_count: + acl_thread = max(rank_acl_count, key=lambda k: rank_acl_count[k]) + trace_events.extend(rank_acl[acl_thread]) + + return trace_events, cpu_trace_events - trace_data["traceEvents"].append({ - "name": event_type_dic[entry.OS_event_type], - "cat": "osprobe", - "ph": "X", - "pid": entry.rank if entry.OS_event_type in [0, 4] else f"CPU: {entry.key}", - "tid": f"{entry.comm}: {entry.key}" if entry.OS_event_type in [0, 4] else entry.key , - "ts": entry.start_us, - "dur": entry.dur, - "args": { - "cpu_rundelay": delay, - "next_comm": entry.nxt_comm, - "next_pid": entry.nxt_pid - } if entry.OS_event_type == 4 else {} - }) - acl_thread = max(rank_acl_count, key=lambda k: rank_acl_count[k]) - trace_data["traceEvents"].extend(rank_acl[acl_thread]) def aggregate_timeline_files(output_path): trace_data = { @@ -70,18 +89,24 @@ def aggregate_timeline_files(output_path): "metadata": {"format": "eBPF OSProbe"} } - for timeline_file in glob.glob("*.pb"): - print(f"Processing {timeline_file}") - process_timeline_file(timeline_file, trace_data) - - # trace_data["traceEvents"].sort(key=lambda x: x["args"]["stage_id"]) - + cpu_trace_data = { + "traceEvents": [], + "displayTimeUnit": "ns", + "metadata": {"format": "eBPF OSProbe"} + } + timeline_files = glob.glob("*.pb") + print(f"Found {len(timeline_files)} timeline files.") + + with Pool(processes=cpu_count()) as pool: + # tqdm 结合 imap_unordered 实现进度显示 + for result, cpu_result in tqdm(pool.imap_unordered(process_single_file, timeline_files), total=len(timeline_files), desc="Processing .pb files"): + trace_data["traceEvents"].extend(result) + cpu_trace_data["traceEvents"].extend(cpu_result) + with open(output_path, "w") as f: json.dump(trace_data, f, indent=None, separators=(',', ':')) + + with open(f"cpu_{output_path}", "w") as f: + json.dump(cpu_trace_data, f, indent=None, separators=(',', ':')) + print(f"Aggregated {len(trace_data['traceEvents'])} events to {output_path}") - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Aggregate all *.timeline files into a single JSON') - parser.add_argument('--output', required=True, help='Output JSON file path') - args = parser.parse_args() - aggregate_timeline_files(args.output) \ No newline at end of file diff --git a/systrace/include/common/shared_constants.c b/systrace/include/common/shared_constants.c index 7402089..a07ed03 100644 --- a/systrace/include/common/shared_constants.c +++ b/systrace/include/common/shared_constants.c @@ -55,16 +55,23 @@ int init_shared_memory() shared_data->g_dump_L0 = true; shared_data->g_dump_L1 = false; shared_data->g_dump_L2 = false; + shared_data->g_dump_L3 = false; shared_data->g_dump_L1_interval = 5; shared_data->g_dump_L2_interval = 5; + shared_data->g_dump_L3_interval = 2; shared_data->g_L1_timer_active = false; shared_data->g_L2_timer_active = false; + shared_data->g_L3_timer_active = false; shared_data->g_L1_start_time = 0; shared_data->g_L2_start_time = 0; + shared_data->g_L3_start_time = 0; shared_data->dumped_L1 = false; shared_data->dumped_L2 = false; + shared_data->dumped_L3 = false; shared_data->need_dump_L1_once = false; shared_data->need_dump_L2_once = false; + shared_data->need_dump_L3_once = false; + return 0; } @@ -132,6 +139,15 @@ bool checkAndUpdateTimer(int level) { dumped = &shared_data->dumped_L2; need_dump_once = &shared_data->need_dump_L2_once; break; + case 3: // L2 + dump_flag = &shared_data->g_dump_L3; + interval = &shared_data->g_dump_L3_interval; + timer_active = &shared_data->g_L3_timer_active; + start_time = &shared_data->g_L3_start_time; + level_name = "L3"; + dumped = &shared_data->dumped_L3; + need_dump_once = &shared_data->need_dump_L3_once; + break; default: pthread_mutex_unlock(&shared_data->g_trace_mutex); return false; diff --git a/systrace/include/common/shared_constants.h b/systrace/include/common/shared_constants.h index 831e334..a102550 100644 --- a/systrace/include/common/shared_constants.h +++ b/systrace/include/common/shared_constants.h @@ -20,16 +20,22 @@ extern "C" bool g_dump_L0; bool g_dump_L1; bool g_dump_L2; + bool g_dump_L3; unsigned int g_dump_L1_interval; unsigned int g_dump_L2_interval; + unsigned int g_dump_L3_interval; bool g_L1_timer_active; bool g_L2_timer_active; + bool g_L3_timer_active; bool dumped_L1; // Indicates if L1 has been dumped bool dumped_L2; // Indicates if L2 has been dumped + bool dumped_L3; // Indicates if L3 has been dumped bool need_dump_L1_once; // Indicates if L1 dump is needed once bool need_dump_L2_once; // Indicates if L2 dump is needed once + bool need_dump_L3_once; // Indicates if L3 dump is needed once time_t g_L1_start_time; time_t g_L2_start_time; + time_t g_L3_start_time; pthread_mutex_t g_trace_mutex; } SharedData; diff --git a/systrace/server/monitor_server.cpp b/systrace/server/monitor_server.cpp index 2df6ab5..dc2df67 100644 --- a/systrace/server/monitor_server.cpp +++ b/systrace/server/monitor_server.cpp @@ -170,6 +170,10 @@ void MonitorServer::process_command( { shared_data->g_dump_L2 = value; } + else if (level == "L3") + { + shared_data->g_dump_L3 = value; + } else { pthread_mutex_unlock(&shared_data->g_trace_mutex); @@ -215,6 +219,10 @@ void MonitorServer::process_command( { shared_data->g_dump_L2_interval = value; } + else if (level == "L3") + { + shared_data->g_dump_L3_interval = value; + } else { pthread_mutex_unlock(&shared_data->g_trace_mutex); @@ -243,8 +251,11 @@ void MonitorServer::process_command( << "\n" << " L2: " << (shared_data->g_dump_L2 ? "true" : "false") << "\n" + << " L3: " << (shared_data->g_dump_L3 ? "true" : "false") + << "\n" << " L1_interval: " << shared_data->g_dump_L1_interval << "\n" - << " L2_interval: " << shared_data->g_dump_L2_interval << "\n"; + << " L2_interval: " << shared_data->g_dump_L2_interval << "\n" + << " L3_interval: " << shared_data->g_dump_L3_interval << "\n"; } else if (level == "L0") { @@ -261,6 +272,11 @@ void MonitorServer::process_command( oss << "L2: " << (shared_data->g_dump_L2 ? "true" : "false") << "\n" << "L2_interval: " << shared_data->g_dump_L2_interval << "\n"; } + else if (level == "L3") + { + oss << "L3: " << (shared_data->g_dump_L3 ? "true" : "false") << "\n" + << "L3_interval: " << shared_data->g_dump_L3_interval << "\n"; + } else { pthread_mutex_unlock(&shared_data->g_trace_mutex); diff --git a/systrace/src/os/bpf_comm.h b/systrace/src/os/bpf_comm.h index 2665881..82c77bb 100644 --- a/systrace/src/os/bpf_comm.h +++ b/systrace/src/os/bpf_comm.h @@ -97,6 +97,46 @@ struct { __uint(max_entries, 64); } osprobe_map_7 SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_8 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_9 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_10 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_11 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_12 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_13 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_14 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 64); +} osprobe_map_15 SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(key_size, 16); diff --git a/systrace/src/os/os_probe.c b/systrace/src/os/os_probe.c index 67d492d..da5025f 100644 --- a/systrace/src/os/os_probe.c +++ b/systrace/src/os/os_probe.c @@ -56,6 +56,14 @@ MAP_SET_PIN_PATH(probe_name, osprobe_map_5, "/sys/fs/bpf/sysTrace/__osprobe_map_5" , load); \ MAP_SET_PIN_PATH(probe_name, osprobe_map_6, "/sys/fs/bpf/sysTrace/__osprobe_map_6" , load); \ MAP_SET_PIN_PATH(probe_name, osprobe_map_7, "/sys/fs/bpf/sysTrace/__osprobe_map_7" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_8, "/sys/fs/bpf/sysTrace/__osprobe_map_8" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_9, "/sys/fs/bpf/sysTrace/__osprobe_map_9" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_10, "/sys/fs/bpf/sysTrace/__osprobe_map_10" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_11, "/sys/fs/bpf/sysTrace/__osprobe_map_11" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_12, "/sys/fs/bpf/sysTrace/__osprobe_map_12" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_13, "/sys/fs/bpf/sysTrace/__osprobe_map_13" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_14, "/sys/fs/bpf/sysTrace/__osprobe_map_14" , load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_15, "/sys/fs/bpf/sysTrace/__osprobe_map_15" , load); \ MAP_SET_PIN_PATH(probe_name, proc_filter_map, PROC_FILTER_MAP_PATH, load); \ MAP_SET_PIN_PATH(probe_name, kernel_filter_map, KERNEL_FILTER_MAP_PATH, load); \ @@ -76,6 +84,8 @@ static pthread_once_t key_once = PTHREAD_ONCE_INIT; static int rank; static int local_rank; static u64 sysBootTime; +static struct bpf_prog_s *prog = NULL; + typedef struct { @@ -376,8 +386,10 @@ err: return -1; } -int update_filter_map(){ - int proc_filter_map_fd, kernel_filter_map_fd; +int update_filter_map_by_npu_smi() { + FILE *fp; + char line[MAX_PATH_LEN]; + int proc_filter_map_fd; int ret = 0; proc_filter_map_fd = bpf_obj_get(PROC_FILTER_MAP_PATH); if (proc_filter_map_fd < 0) { @@ -385,33 +397,7 @@ int update_filter_map(){ fprintf(stderr, "[OS_PROBE RANK_%d] Failed to get bpf prog proc_filter map: %s.\n", rank, strerror(errno)); return -1; } - kernel_filter_map_fd = bpf_obj_get(KERNEL_FILTER_MAP_PATH); - if (kernel_filter_map_fd < 0) { - // 打印error num - fprintf(stderr, "[OS_PROBE RANK_%d] Failed to get bpf prog kernel_filter map: %s.\n", rank, strerror(errno)); - return -1; - } - for (int dev_id = 0; dev_id < 8; ++dev_id) { - char send_key[16] = {0}; - char task_key[16] = {0}; - snprintf(send_key, sizeof(send_key), "dev%d_sq_send_wq", dev_id); - snprintf(task_key, sizeof(task_key), "dev%d_sq_task", dev_id); - - ret = bpf_map_update_elem(kernel_filter_map_fd, send_key, &dev_id, BPF_ANY); - if (ret != 0) { - perror("bpf_map_update_elem failed"); - } - ret = bpf_map_update_elem(kernel_filter_map_fd, task_key, &dev_id, BPF_ANY); - if (ret != 0) { - perror("bpf_map_update_elem failed"); - } - } - - FILE *fp; - char line[1024]; - // 获取进程号 - sleep(10); fp = popen("npu-smi info", "r"); if (fp == NULL) { perror("Failed to run npu-smi info"); @@ -441,8 +427,35 @@ int update_filter_map(){ } } pclose(fp); + return ret; +} - return 0; +int update_filter_map_by_kernel_thread() { + int kernel_filter_map_fd; + int ret = 0; + kernel_filter_map_fd = bpf_obj_get(KERNEL_FILTER_MAP_PATH); + if (kernel_filter_map_fd < 0) { + // 打印error num + fprintf(stderr, "[OS_PROBE RANK_%d] Failed to get bpf prog kernel_filter map: %s.\n", rank, strerror(errno)); + return -1; + } + for (int dev_id = 0; dev_id < 16; ++dev_id) { + char send_key[16] = {0}; + char task_key[16] = {0}; + snprintf(send_key, sizeof(send_key), "dev%d_sq_send_wq", dev_id); + snprintf(task_key, sizeof(task_key), "dev%d_sq_task", dev_id); + + ret = bpf_map_update_elem(kernel_filter_map_fd, send_key, &dev_id, BPF_ANY); + if (ret != 0) { + perror("bpf_map_update_elem failed"); + } + ret = bpf_map_update_elem(kernel_filter_map_fd, task_key, &dev_id, BPF_ANY); + if (ret != 0) { + perror("bpf_map_update_elem failed"); + } + } + + return ret; } int bpf_buffer_init_from_pin(struct bpf_buffer **buffer_ptr, const char *map_path, @@ -495,20 +508,25 @@ int bpf_buffer_init_from_pin(struct bpf_buffer **buffer_ptr, const char *map_pat return 0; } -int run_osprobe() { +void cleanup_osprobe() { FILE *fp; + fp = popen(RM_MAP_PATH, "r"); + if (fp != NULL) { + (void)pclose(fp); + fp = NULL; + } + unload_bpf_prog(&prog); + if (prog) { + free_bpf_prog(prog); + } +} + +int run_osprobe() { int ret = 0; - struct bpf_prog_s *prog = NULL; struct bpf_buffer *buffer = NULL; initialize_osprobe(); if (local_rank == 0) { - - fp = popen(RM_MAP_PATH, "r"); - if (fp != NULL) { - (void)pclose(fp); - fp = NULL; - } prog = alloc_bpf_prog(); if (prog == NULL) { goto err; @@ -524,12 +542,20 @@ int run_osprobe() { fprintf(stderr, "[OS_PROBE RANK_%d] load cpu probe failed.\n", rank); goto err; } - if (update_filter_map()) { - fprintf(stderr, "[OS_PROBE RANK_%d] Failed to update proc_filter map.\n", rank); + if (update_filter_map_by_kernel_thread()) { + fprintf(stderr, "[OS_PROBE RANK_%d] Failed to update proc_filter map by kernel thread.\n", rank); + goto err; + } + sleep(60); + if (update_filter_map_by_npu_smi()) { + fprintf(stderr, "[OS_PROBE RANK_%d] Failed to update proc_filter map by npu-smi info.\n", rank); goto err; } while (!g_stop) { sleep(1); + if (!checkAndUpdateTimer(3)) { + continue; + } for (int i = 0; i < prog->num; i++) { if (prog->buffers[i] && ((ret = bpf_buffer__poll(prog->buffers[i], THOUSAND)) < 0) @@ -559,6 +585,9 @@ int run_osprobe() { goto err; } while (!g_stop) { + if (!checkAndUpdateTimer(3)) { + continue; + } if (((ret = bpf_buffer__poll(buffer, THOUSAND)) < 0) && ret != -EINTR) { fprintf(stderr, "[OS_PROBE RANK_%d] perf poll prog failed:%s.\n", local_rank, strerror(errno)); @@ -569,14 +598,6 @@ int run_osprobe() { fprintf(stderr, "[OS_PROBE RANK_%d] sysTrace ebpf trace finished\n", local_rank); err: - fp = popen(RM_MAP_PATH, "r"); - if (fp != NULL) { - (void)pclose(fp); - fp = NULL; - } - unload_bpf_prog(&prog); - if (prog) { - free_bpf_prog(prog); - } + cleanup_osprobe(); return ret; } diff --git a/systrace/src/os/os_probe.h b/systrace/src/os/os_probe.h index 8fdbb1f..b002265 100644 --- a/systrace/src/os/os_probe.h +++ b/systrace/src/os/os_probe.h @@ -33,10 +33,12 @@ typedef struct { int rank; long long unsigned int start_time; long long unsigned int end_time; - long long unsigned int duration; // 若为多个事件聚合,则表示累计的执行时间 + long long unsigned int duration; event_type_e type; long long unsigned int delay; char comm[THREAD_COMM_LEN]; + char next_comm[THREAD_COMM_LEN]; + long unsigned int next_pid; } trace_event_data_t; #endif diff --git a/systrace/src/trace/systrace_manager.cc b/systrace/src/trace/systrace_manager.cc index 856bbb8..783d254 100644 --- a/systrace/src/trace/systrace_manager.cc +++ b/systrace/src/trace/systrace_manager.cc @@ -6,9 +6,16 @@ #include "../../include/common/constant.h" #include "../../include/common/shared_constants.h" #include "systrace_manager.h" +// #include "../../src/os/os_probe.h" int global_stage_id = 0; int global_stage_type = 0; + +extern "C" { + int run_osprobe(); + void cleanup_osprobe(); +} + namespace systrace { @@ -197,7 +204,11 @@ SysTrace &SysTrace::getInstance() return *instance_; } -SysTrace::~SysTrace() { stopEventPoller(); } +SysTrace::~SysTrace() +{ + stopOsProbePoller(); + stopEventPoller(); +} void SysTrace::initializeSystem() { @@ -208,6 +219,7 @@ void SysTrace::initializeSystem() MonitorServer::getInstance(); MSPTITracker::getInstance(); PyTorchTrace::getInstance(); + os_probe_ = std::thread(&run_osprobe); startEventPoller(); } @@ -222,6 +234,15 @@ void SysTrace::startEventPoller() STLOG(INFO) << "[SysTrace] Event poller started"; } +void SysTrace::stopOsProbePoller() +{ + cleanup_osprobe(); + if (os_probe_.joinable()) + { + os_probe_.join(); + } +} + void SysTrace::stopEventPoller() { should_run_ = false; diff --git a/systrace/src/trace/systrace_manager.h b/systrace/src/trace/systrace_manager.h index 85e43d5..f81fef6 100644 --- a/systrace/src/trace/systrace_manager.h +++ b/systrace/src/trace/systrace_manager.h @@ -66,6 +66,7 @@ class SysTrace void initializeSystem(); void startEventPoller(); void stopEventPoller(); + void stopOsProbePoller(); void eventPollerMain(); inline static SysTrace *instance_ = nullptr; @@ -74,6 +75,7 @@ class SysTrace std::atomic should_run_{true}; std::atomic loop_count_{0}; std::thread event_poller_; + std::thread os_probe_; }; } // namespace systrace \ No newline at end of file -- Gitee