Skip to content

Commit b69e9eb

Browse files
committed
update multithread
1 parent d78a22e commit b69e9eb

File tree

6 files changed

+430
-990
lines changed

6 files changed

+430
-990
lines changed

.cursorignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
2+
artifact
3+
build
4+
cmake-build-debug
5+
workloads
6+
script

include/bpftimeruntime.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,11 @@ struct proc_info {
9898
struct mem_info mem_info;
9999
};
100100

101+
// 线程创建参数
102+
struct thread_create_args {
103+
void **thread_ptr;
104+
void *attr;
105+
void *start_routine;
106+
void *arg;
107+
};
101108
#endif

src/bpftimeruntime.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,11 @@
2828

2929
BpfTimeRuntime::BpfTimeRuntime(pid_t tid, std::string program_location)
3030
: tid(tid), updater(new BPFUpdater<uint64_t, uint64_t>(10)) {
31-
bpftime_initialize_global_shm(bpftime::shm_open_type::SHM_REMOVE_AND_CREATE);
31+
bpftime_initialize_global_shm(bpftime::shm_open_type::SHM_OPEN_ONLY);
3232
SPDLOG_INFO("GLOBAL memory initialized ");
33-
// load json program to shm
34-
bpftime_import_global_shm_from_json(program_location.c_str());
35-
SPDLOG_INFO("Program loaded to shm");
3633
}
3734

38-
BpfTimeRuntime::~BpfTimeRuntime() { bpftime_remove_global_shm(); }
35+
BpfTimeRuntime::~BpfTimeRuntime() { }
3936
int BpfTimeRuntime::read(CXLController *controller, BPFTimeRuntimeElem *elem) {
4037
mem_stats stats;
4138
proc_info proc_info1;

src/cxlmemsim.bpf.c

Lines changed: 115 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -12,220 +12,53 @@
1212

1313
#include "../include/bpftimeruntime.h"
1414

15+
16+
// 线程参数映射
17+
struct {
18+
__uint(type, BPF_MAP_TYPE_HASH);
19+
__uint(max_entries, 10240);
20+
__type(key, u64); // pid_tgid
21+
__type(value, struct thread_create_args);
22+
} thread_create_args_map SEC(".maps");
23+
1524
struct {
16-
__uint(type, BPF_MAP_TYPE_HASH);
17-
__uint(max_entries, 100000);
18-
__type(key, u64);
19-
__type(value, struct alloc_info);
25+
__uint(type, BPF_MAP_TYPE_HASH);
26+
__uint(max_entries, 100000);
27+
__type(key, u64);
28+
__type(value, struct alloc_info);
2029
} allocs_map SEC(".maps");
2130

2231
struct {
23-
__uint(type, BPF_MAP_TYPE_HASH);
24-
__uint(max_entries, 10240);
25-
__type(key, u32);
26-
__type(value, struct mem_stats);
32+
__uint(type, BPF_MAP_TYPE_HASH);
33+
__uint(max_entries, 10240);
34+
__type(key, u32);
35+
__type(value, struct mem_stats);
2736
} stats_map SEC(".maps");
2837

2938
// 存储线程信息的 map
3039
struct {
31-
__uint(type, BPF_MAP_TYPE_HASH);
32-
__uint(max_entries, 102400);
33-
__type(key, u32); // tid as key
34-
__type(value, struct proc_info);
40+
__uint(type, BPF_MAP_TYPE_HASH);
41+
__uint(max_entries, 102400);
42+
__type(key, u32); // tid as key
43+
__type(value, struct proc_info);
3544
} thread_map SEC(".maps");
3645

3746
struct {
38-
__uint(type, BPF_MAP_TYPE_HASH);
39-
__uint(max_entries, 10240);
40-
__type(key, u32);
41-
__type(value, struct proc_info);
47+
__uint(type, BPF_MAP_TYPE_HASH);
48+
__uint(max_entries, 10240);
49+
__type(key, u32);
50+
__type(value, struct proc_info);
4251
} process_map SEC(".maps");
4352

4453
// 用于处理多线程同步的自旋锁映射
4554
struct {
46-
__uint(type, BPF_MAP_TYPE_HASH);
47-
__uint(max_entries, 10240);
48-
__type(key, u32);
49-
__type(value, u32);
55+
__uint(type, BPF_MAP_TYPE_HASH);
56+
__uint(max_entries, 10240);
57+
__type(key, u32);
58+
__type(value, u32);
5059
} locks SEC(".maps");
5160
// 钩住OpenMP并行区域创建函数
52-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:GOMP_parallel")
53-
int uprobe_omp_parallel(struct pt_regs *ctx) {
54-
u64 pid_tgid = bpf_get_current_pid_tgid();
55-
u32 pid = pid_tgid >> 32;
56-
void *fn = (void *)PT_REGS_PARM1(ctx); // 并行区域函数指针
57-
void *data = (void *)PT_REGS_PARM2(ctx); // 用户数据指针
58-
unsigned num_threads = (unsigned)PT_REGS_PARM3(ctx); // 线程数量
59-
60-
// 更新进程信息中的线程计数
61-
struct proc_info *proc_info = bpf_map_lookup_elem(&process_map, &pid);
62-
if (proc_info) {
63-
proc_info->thread_count += num_threads;
64-
bpf_map_update_elem(&process_map, &pid, proc_info, BPF_ANY);
65-
}
66-
67-
return 0;
68-
}
69-
70-
// 钩住GOMP_single_start函数 - 用于single构造
71-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:GOMP_single_start")
72-
int uprobe_omp_single_start(struct pt_regs *ctx) {
73-
u64 pid_tgid = bpf_get_current_pid_tgid();
74-
u32 pid = pid_tgid >> 32;
75-
u32 tid = (u32)pid_tgid;
76-
// 返回值表示该线程是否执行single区域
77-
return 0;
78-
}
79-
80-
// 钩住GOMP_single_start的返回值
81-
SEC("uretprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:GOMP_single_start")
82-
int uretprobe_omp_single_start(struct pt_regs *ctx) {
83-
u64 pid_tgid = bpf_get_current_pid_tgid();
84-
u32 pid = pid_tgid >> 32;
85-
u32 tid = (u32)pid_tgid;
86-
bool is_selected = (bool)PT_REGS_RC(ctx);
87-
88-
89-
return 0;
90-
}
91-
92-
// OpenMP临界区钩子
93-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:GOMP_critical_start")
94-
int uprobe_omp_critical_start(struct pt_regs *ctx) {
95-
u64 pid_tgid = bpf_get_current_pid_tgid();
96-
u32 pid = pid_tgid >> 32;
97-
u32 tid = (u32)pid_tgid;
98-
99-
100-
// 记录线程进入临界区
101-
u32 locked = 1;
102-
bpf_map_update_elem(&locks, &tid, &locked, BPF_ANY);
103-
104-
struct proc_info *item = bpf_map_lookup_elem(&thread_map, &tid);
105-
if (item) {
106-
item->is_locked = 1;
107-
bpf_map_update_elem(&thread_map, &tid, item, BPF_ANY);
108-
}
109-
110-
return 0;
111-
}
112-
113-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:GOMP_critical_end")
114-
int uprobe_omp_critical_end(struct pt_regs *ctx) {
115-
u64 pid_tgid = bpf_get_current_pid_tgid();
116-
u32 pid = pid_tgid >> 32;
117-
u32 tid = (u32)pid_tgid;
118-
119-
120-
// 记录线程离开临界区
121-
u32 locked = 0;
122-
bpf_map_update_elem(&locks, &tid, &locked, BPF_ANY);
123-
124-
struct proc_info *item = bpf_map_lookup_elem(&thread_map, &tid);
125-
if (item) {
126-
item->is_locked = 0;
127-
bpf_map_update_elem(&thread_map, &tid, item, BPF_ANY);
128-
}
129-
130-
return 0;
131-
}
132-
133-
// OpenMP屏障同步点
134-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:GOMP_barrier")
135-
int uprobe_omp_barrier(struct pt_regs *ctx) {
136-
u64 pid_tgid = bpf_get_current_pid_tgid();
137-
u32 pid = pid_tgid >> 32;
138-
u32 tid = (u32)pid_tgid;
139-
140-
141-
return 0;
142-
}
143-
144-
// 线程同步:获取OpenMP锁
145-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:omp_set_lock")
146-
int uprobe_omp_set_lock(struct pt_regs *ctx) {
147-
u64 pid_tgid = bpf_get_current_pid_tgid();
148-
u32 pid = pid_tgid >> 32;
149-
u32 tid = (u32)pid_tgid;
150-
void *lock = (void *)PT_REGS_PARM1(ctx);
151-
152-
153-
// 记录线程获取锁
154-
u32 locked = 1;
155-
bpf_map_update_elem(&locks, &tid, &locked, BPF_ANY);
156-
157-
return 0;
158-
}
159-
160-
// 线程同步:释放OpenMP锁
161-
SEC("uprobe//usr/lib/x86_64-linux-gnu/libgomp.so.1:omp_unset_lock")
162-
int uprobe_omp_unset_lock(struct pt_regs *ctx) {
163-
u64 pid_tgid = bpf_get_current_pid_tgid();
164-
u32 pid = pid_tgid >> 32;
165-
u32 tid = (u32)pid_tgid;
166-
void *lock = (void *)PT_REGS_PARM1(ctx);
167-
168-
169-
// 记录线程释放锁
170-
u32 locked = 0;
171-
bpf_map_update_elem(&locks, &tid, &locked, BPF_ANY);
172-
173-
return 0;
174-
}
175-
// C++标准库线程创建函数的钩子
176-
SEC("uprobe//usr/lib/gcc/x86_64-linux-gnu/14/libstdc++.so:_ZNSt6thread15_M_start_threadESt10unique_ptrINS_6_StateESt14default_deleteIS1_EEPFvvE")
177-
int uprobe_cxx_thread_start(struct pt_regs *ctx) {
178-
u64 pid_tgid = bpf_get_current_pid_tgid();
179-
u32 pid = pid_tgid >> 32;
180-
u32 tid = (u32)pid_tgid;
181-
182-
// 获取函数参数(注意:在BPF中我们不能直接访问complex C++对象的内部)
183-
// 我们只能获取到原始指针
184-
void *thread_state_ptr = (void *)PT_REGS_PARM1(ctx); // unique_ptr参数
185-
void *thread_func_ptr = (void *)PT_REGS_PARM2(ctx); // 函数指针参数
186-
187-
188-
// 记录线程创建事件到临时映射,供返回探针使用
189-
struct {
190-
u32 parent_pid;
191-
u64 create_time;
192-
} thread_info = {
193-
.parent_pid = pid,
194-
.create_time = bpf_ktime_get_ns(),
195-
};
196-
197-
bpf_map_update_elem(&allocs_map, &pid_tgid, &thread_info, BPF_ANY);
198-
199-
return 0;
200-
}
20161

202-
// C++标准库线程创建函数的返回钩子
203-
SEC("uretprobe//usr/lib/gcc/x86_64-linux-gnu/14/libstdc++.so:_ZNSt6thread15_M_start_threadESt10unique_ptrINS_6_StateESt14default_deleteIS1_EEPFvvE")
204-
int uretprobe_cxx_thread_start(struct pt_regs *ctx) {
205-
u64 pid_tgid = bpf_get_current_pid_tgid();
206-
u32 pid = pid_tgid >> 32;
207-
208-
// 获取之前保存的信息
209-
void *thread_info_ptr = bpf_map_lookup_elem(&allocs_map, &pid_tgid);
210-
if (!thread_info_ptr) {
211-
return 0;
212-
}
213-
214-
// 注意:C++线程创建函数不直接返回线程ID
215-
// 需要在后续步骤中捕获(比如通过pthread_create的返回值)
216-
217-
// 在这里,我们可以增加进程的线程计数
218-
struct proc_info *proc_info = bpf_map_lookup_elem(&process_map, &pid);
219-
if (proc_info) {
220-
proc_info->thread_count++;
221-
bpf_map_update_elem(&process_map, &pid, proc_info, BPF_ANY);
222-
}
223-
224-
// 清理临时信息
225-
bpf_map_delete_elem(&allocs_map, &pid_tgid);
226-
227-
return 0;
228-
}
22962
// mmap的uprobe钩子
23063
SEC("uprobe//usr/lib/x86_64-linux-gnu/libc.so.6:mmap")
23164
int uprobe_mmap(struct pt_regs *ctx) {
@@ -926,4 +759,90 @@ int uretprobe_pthread_mutex_trylock(struct pt_regs *ctx) {
926759

927760
return 0;
928761
}
762+
763+
SEC("uprobe//lib/x86_64-linux-gnu/libc.so.6:pthread_create")
764+
int pthread_create_probe(struct pt_regs *ctx)
765+
{
766+
u64 pid_tgid = bpf_get_current_pid_tgid();
767+
u32 pid = pid_tgid >> 32;
768+
769+
// 获取新线程的 ID(通过第一个参数)
770+
unsigned long *thread_ptr;
771+
bpf_probe_read(&thread_ptr, sizeof(thread_ptr),
772+
(void *)&PT_REGS_PARM1(ctx));
773+
774+
775+
if (thread_ptr) {
776+
// 创建新的线程信息
777+
struct thread_create_args thread_info = {
778+
.thread_ptr = thread_ptr,
779+
.attr = NULL,
780+
.start_routine = NULL,
781+
.arg = NULL,
782+
};
783+
bpf_printk("pthread_create_probe: pid: %d thread_ptr: %lx\n", pid,
784+
(unsigned long)thread_ptr);
785+
// 更新线程计数
786+
struct proc_info *parent_info =
787+
bpf_map_lookup_elem(&process_map, &pid);
788+
if (parent_info) {
789+
// __sync_fetch_and_add(&parent_info->thread_count, 1);
790+
parent_info->thread_count += 1;
791+
}
792+
793+
// 注意:我们需要在 return probe 中获取实际的线程 ID
794+
// 这里先保存父进程信息
795+
bpf_map_update_elem(&thread_create_args_map, &pid_tgid,
796+
&thread_info, BPF_ANY);
797+
}
798+
799+
return 0;
800+
}
801+
SEC("uretprobe//lib/x86_64-linux-gnu/libc.so.6:pthread_create")
802+
int pthread_create_return_probe(struct pt_regs *ctx)
803+
{
804+
u64 pid_tgid = bpf_get_current_pid_tgid();
805+
u32 pid = pid_tgid >> 32;
806+
807+
// 获取 pthread_create 的返回值
808+
int ret = PT_REGS_RC(ctx);
809+
810+
// 如果 pthread_create 成功(返回0)
811+
if (ret == 0) {
812+
struct thread_create_args *args =
813+
bpf_map_lookup_elem(&thread_create_args_map, &pid_tgid);
814+
if (args) {
815+
// 获取线程指针
816+
void **thread_ptrs = args->thread_ptr;
817+
818+
// 读取新创建的线程ID
819+
if (thread_ptrs) {
820+
u64 thread_id = 0;
821+
// 正确读取 pthread_t 类型的值
822+
bpf_probe_read(&thread_id, sizeof(thread_id), thread_ptrs);
823+
824+
if (thread_id != 0) {
825+
// 使用实际的线程ID更新信息
826+
struct proc_info updated_info;
827+
updated_info.parent_pid = pid;
828+
updated_info.current_pid = pid;
829+
updated_info.current_tid = thread_id;
830+
updated_info.create_time = bpf_ktime_get_ns();
831+
832+
// 使用 %lu 或 %lx 格式打印无符号长整型
833+
bpf_printk("pthread_create_return_probe: pid: %d thread_id: %lu (0x%lx)\n",
834+
pid, thread_id, thread_id);
835+
836+
// 将线程信息添加到进程映射中
837+
bpf_map_update_elem(&thread_map, &thread_id, &updated_info, BPF_ANY);
838+
}
839+
}
840+
841+
// 清理参数映射
842+
bpf_map_delete_elem(&thread_create_args_map, &pid_tgid);
843+
}
844+
}
845+
846+
return 0;
847+
}
929848
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)