From 905887586d29f599de346c233f72eea3ba29a4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=99=97=E5=8D=9A?= Date: Fri, 13 Sep 2024 15:23:21 +0800 Subject: [PATCH] modify mfutex --- .../eBPF_proc_image/bpf/mfutex.bpf.c | 364 ++++++++---------- .../eBPF_proc_image/include/proc_image.h | 28 +- .../eBPF_proc_image/proc_image.c | 71 ++-- 3 files changed, 213 insertions(+), 250 deletions(-) diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/mfutex.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/mfutex.bpf.c index ac7a2ea5f..1a773c563 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/mfutex.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/mfutex.bpf.c @@ -51,7 +51,7 @@ struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 10240); __type(key, struct record_lock_key); - __type(value, int); + __type(value, struct per_request); } record_lock SEC(".maps");//记录争用锁的全部进程 struct { @@ -70,9 +70,17 @@ struct { struct { __uint(type, BPF_MAP_TYPE_RINGBUF); - __uint(max_entries,256 * 10240); + __uint(max_entries,528 * 10240); } mfutex_rb SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10240); + __type(key, struct record_lock_key); + __type(value, struct per_request); +} futex_wait_queue SEC(".maps");//记录futex陷入内核 + + #define MUTEX_FLAG 1 #define RWLOCK_FLAG 2 #define SPIN_FLAG 3 @@ -87,50 +95,66 @@ static inline struct mfutex_ctrl *get_mfutex_ctrl(void) { } return mfutex_ctrl; } -bool push_to_rb(struct per_lock_event *per_lock) { - struct per_lock_event *e; - e = bpf_ringbuf_reserve(&mfutex_rb, sizeof(*e), 0); - if(!e) - return 0; - e->lock_ptr = per_lock->lock_ptr; - e->owner = per_lock->owner; - e->time = per_lock->time; - e->type = per_lock->type; - e->cnt = per_lock->cnt; - bpf_ringbuf_submit(e, 0); -} -// 用户态互斥锁 -/* - *1:通过__mutex->_lock查看是否已经上锁,如果是,则将该线程记录进record_lock数组中; - *2:通过__mutex->_owner_id 更新锁的持有者; - *3:通过__mutex->_type 标识锁的类型; + +/*1.尝试申请锁 + *1.1:将申请锁的进程加入等待队列,并标记相关信息; */ SEC("uprobe/pthread_mutex_lock") -int BPF_KPROBE(pthread_mutex_lock_enter, struct __pthread_mutex *__mutex)//存申请锁的地址 +int BPF_KPROBE(pthread_mutex_lock_enter, void *__mutex)//存申请锁的地址 { struct mfutex_ctrl *mfutex_ctrl = get_mfutex_ctrl(); if(!mfutex_ctrl) return 0; - pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - // if(mfutex_ctrl->target_pid == 0 && mfutex_ctrl->target_tgid == 0)//未指定目标进程或线程 - // return 0; - // if((mfutex_ctrl->target_pid != 0 && pid!=mfutex_ctrl->target_pid)|| - // (mfutex_ctrl->target_tgid != 0 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 - // return 0; - u64 lock_ptr = (u64)__mutex; + if(mfutex_ctrl->target_pid == -1 && mfutex_ctrl->target_tgid == -1)//未指定目标进程或线程 + return 0; + if((mfutex_ctrl->target_pid != -1 && pid!=mfutex_ctrl->target_pid)|| + (mfutex_ctrl->target_tgid != -1 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 + return 0; + u64 lock_ptr = (u64)__mutex; + int cnt; + /*1.将锁地址信息与进程pid记录在proc_lock map中*/ struct proc_flag proc_flag = {}; - //proc_flag 标注锁的类型 proc_flag.pid = pid; proc_flag.flag = MUTEX_FLAG; bpf_map_update_elem(&proc_lock, &proc_flag, &lock_ptr, BPF_ANY); - bpf_printk("A:lock_addr:0x%x\tpid:%d\n",lock_ptr,pid); + + /*2.对per_lock_info map中的信息进行读取更新或增加,包括cnt*/ + struct per_lock_event * per_lock_event = bpf_map_lookup_elem(&per_lock_info, &lock_ptr); + if(per_lock_event){ + per_lock_event->cnt++; + cnt = per_lock_event->cnt; + }else{ + struct per_lock_event new_per_lock = {}; + new_per_lock.lock_ptr = lock_ptr; + new_per_lock.type = MUTEX_FLAG; + new_per_lock.cnt = 1; + cnt = 1; + bpf_map_update_elem(&per_lock_info, &lock_ptr, &new_per_lock, BPF_ANY); + } + /*3.将 单个线程请求信息块 放入 请求等待队列record_lock 以及lock_record map */ + struct per_request per_request = {}; + per_request.pid = pid; + per_request.start_request_time = bpf_ktime_get_ns(); + struct record_lock_key key = {}; + key.lock_ptr = lock_ptr; + key.cnt = cnt; + bpf_map_update_elem(&record_lock, &key, &per_request, BPF_ANY); + bpf_printk("Push_info:pid:%d ,lock_ptr:%lu, cnt:%d\n",per_request.pid,key.lock_ptr,key.cnt); + //用于通过lock_ptr 和pid 找到cnt + struct lock_record_key key2 ={}; + key2.lock_ptr = lock_ptr; + key2.pid = pid; + bpf_map_update_elem(&lock_record, &key2, &cnt, BPF_ANY); return 0; } +/*2.申请锁成功 + *2.1:更新持有锁信息,将等待对列中对应的进程标记为持有; +*/ SEC("uretprobe/pthread_mutex_lock") int BPF_KRETPROBE(pthread_mutex_lock_exit,int ret) { @@ -139,87 +163,73 @@ int BPF_KRETPROBE(pthread_mutex_lock_exit,int ret) pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - // if(mfutex_ctrl->target_pid == 0 && mfutex_ctrl->target_tgid == 0)//未指定目标进程或线程 - // return 0; - // if((mfutex_ctrl->target_pid != 0 && pid!=mfutex_ctrl->target_pid)|| - // (mfutex_ctrl->target_tgid != 0 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 - // return 0; + if(ret) + return 0; + if(mfutex_ctrl->target_pid == -1 && mfutex_ctrl->target_tgid == -1)//未指定目标进程或线程 + return 0; + if((mfutex_ctrl->target_pid != -1 && pid!=mfutex_ctrl->target_pid)|| + (mfutex_ctrl->target_tgid != -1 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 + return 0; u64 *lock_ptr; u64 temp_lock_ptr; - //找锁 + u64 ts = bpf_ktime_get_ns(); + /*1.找到锁的地址*/ struct proc_flag proc_flag = {}; proc_flag.pid = pid; proc_flag.flag = MUTEX_FLAG; lock_ptr = bpf_map_lookup_elem(&proc_lock, &proc_flag); - if(!lock_ptr) - return 0; + if(!lock_ptr) return 0; temp_lock_ptr = *lock_ptr; - // bpf_map_delete_elem(&proc_lock, &proc_flag); - //对锁进行统计,申请成功,则记录,申请失败,则加入等待队列/阻塞队列; - if(ret==0){//无人占用锁, - struct per_lock_event *per_lock = bpf_map_lookup_elem(&per_lock_info, &temp_lock_ptr); - if(per_lock){//在map中找到 - per_lock->owner = pid; - per_lock->time = bpf_ktime_get_ns(); - per_lock->cnt = 1; - push_to_rb(per_lock); - }else{ - struct per_lock_event per_lock = {}; // 声明结构体变量 - per_lock.lock_ptr = temp_lock_ptr; - per_lock.type = MUTEX_FLAG; - per_lock.owner = pid; - per_lock.time = bpf_ktime_get_ns(); - per_lock.cnt = 1; - bpf_map_update_elem(&per_lock_info, &temp_lock_ptr, &per_lock, BPF_ANY); - push_to_rb(&per_lock); - } - bpf_printk("B:lock_addr:0x%x\tpid:%d\t%s\n",temp_lock_ptr,pid,ret==0?"SUCC":"FALSE"); - //记录等待该锁的全部进程; - struct record_lock_key key = {}; - key.lock_ptr = temp_lock_ptr; - key.cnt = 1; - bpf_map_update_elem(&record_lock, &key, &pid, BPF_ANY); - }else{//锁被持有,陷入阻塞或忙等待; - struct per_lock_event *per_lock = bpf_map_lookup_elem(&per_lock_info, &temp_lock_ptr); - if(!per_lock){ - return 0; - } - per_lock->cnt++; - //记录等待该锁的全部进程; - struct record_lock_key key= {}; - key.lock_ptr = temp_lock_ptr; - key.cnt = per_lock->cnt; - bpf_map_update_elem(&record_lock, &key, &pid, BPF_ANY); - struct lock_record_key key2 ={}; - key2.lock_ptr = temp_lock_ptr; - key2.pid = pid; - bpf_map_update_elem(&lock_record, &key2, &per_lock->cnt, BPF_ANY); - bpf_printk("B:lock_addr:0x%x\tpid:%d\t%s\n",temp_lock_ptr,pid,ret==0?"SUCC":"FALSE"); - bpf_printk("lock_addr:0x%x\towner:%d\towner_time:%llu\tcur_pid:%d\n", - temp_lock_ptr,per_lock->owner,per_lock->time,pid); - //数据存储 - push_to_rb(per_lock); - } - return 0; -} -// SEC("uprobe/__pthread_mutex_trylock") -// int BPF_KPROBE(__pthread_mutex_trylock_enter, void *__mutex) -// { -// record_lock_enter(ignore_tgid,1,1,__mutex,&mfutex_rb,&proc_lock,&lock_ctrl_map); - -// return 0; -// } + /*2.找到当前线程在record_lock map中的位置,即cnt*/ + int *cnt; + struct lock_record_key key1 = {}; + key1.lock_ptr = temp_lock_ptr; + key1.pid = pid; + cnt = bpf_map_lookup_elem(&lock_record, &key1);//找到cnt + if(!cnt) return 0; -// SEC("uretprobe/__pthread_mutex_trylock") -// int BPF_KRETPROBE(__pthread_mutex_trylock_exit,int ret) -// { -// record_lock_exit(ignore_tgid,2,1,ret,&mfutex_rb,&proc_lock,&locktype,&lock_ctrl_map); - -// return 0; -// } + /*3.通过 cnt和lock_ptr 在record_lock map中找到对应的线程信息块,并更新*/ + struct record_lock_key key2 = {}; + key2.lock_ptr = temp_lock_ptr; + key2.cnt = *cnt; + struct per_request *per_request = bpf_map_lookup_elem(&record_lock, &key2); + if(!per_request) return 0; + bpf_map_delete_elem(&record_lock, &key2); + key2.cnt = 1; + per_request->start_hold_time = ts;//标志着开始占有锁 + per_request->wait_delay = ts - per_request->start_request_time; + bpf_map_update_elem(&record_lock, &key2, per_request, BPF_ANY); + + /*4.更新per_lock_info map中的信息,并传送到ringbuf中*/ + struct per_lock_event *per_lock_event = bpf_map_lookup_elem(&per_lock_info, &temp_lock_ptr); + if(!per_lock_event) return 0; + per_lock_event->owner = pid; + per_lock_event->start_hold_time = ts; + bpf_map_update_elem(&per_lock_info, &temp_lock_ptr, per_lock_event, BPF_ANY); + + //数据传送到ringbuf; + struct per_lock_event *e; + e = bpf_ringbuf_reserve(&mfutex_rb, sizeof(*e), 0); + if(!e) + return 0; + e->lock_ptr = per_lock_event->lock_ptr; + e->owner = per_lock_event->owner; + e->last_owner = per_lock_event->last_owner; + e->start_hold_time = per_lock_event->start_hold_time; + e->type = per_lock_event->type; + e->cnt = per_lock_event->cnt; + e->last_hold_delay = per_lock_event->last_hold_delay; + bpf_printk("In Push_to_rb lock_ptr %llu,per_cnt:%d,owner:%d,last_owner:%d,last_hold_time:%lu\n",e->lock_ptr,e->cnt,e->owner, + e->last_owner,e->last_hold_delay); + bpf_ringbuf_submit(e, 0); + return 0; +} +/*尝试解锁 + *1.将等待对列中对应的解锁进程删除,并更新该进程持有锁的时间; +*/ SEC("uprobe/pthread_mutex_unlock") int BPF_KPROBE(pthread_mutex_unlock_enter, void *__mutex) { @@ -228,121 +238,69 @@ int BPF_KPROBE(pthread_mutex_unlock_enter, void *__mutex) pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - // if(mfutex_ctrl->target_pid == 0 && mfutex_ctrl->target_tgid == 0)//未指定目标进程或线程 - // return 0; - // if((mfutex_ctrl->target_pid != 0 && pid!=mfutex_ctrl->target_pid)|| - // (mfutex_ctrl->target_tgid != 0 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 - // return 0; + + if(mfutex_ctrl->target_pid == -1 && mfutex_ctrl->target_tgid == -1)//未指定目标进程或线程 + return 0; + if((mfutex_ctrl->target_pid != -1 && pid!=mfutex_ctrl->target_pid)|| + (mfutex_ctrl->target_tgid != -1 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 + return 0; u64 lock_ptr = (u64)__mutex; - struct proc_flag proc_flag = {}; - //proc_flag 标注锁的类型 - proc_flag.pid = pid; - proc_flag.flag = MUTEX_FLAG; - bpf_map_update_elem(&proc_unlock, &proc_flag, &lock_ptr, BPF_ANY); - bpf_printk("C:lock_addr:0x%x\tpid:%d\n",lock_ptr,pid); + u64 ts = bpf_ktime_get_ns(); + + /*1.通过 cnt和lock_ptr 在record_lock map中找到对应的线程信息块,并删除在队列中的记录*/ + struct record_lock_key key2 = {}; + key2.lock_ptr = lock_ptr; + key2.cnt = 1; + struct per_request *per_request = bpf_map_lookup_elem(&record_lock, &key2); + if(!per_request) return 0; + bpf_map_delete_elem(&record_lock, &key2); + + /*2.将该线程持有锁的信息同步在per_lock map 中*/ + struct per_lock_event *per_lock_event = bpf_map_lookup_elem(&per_lock_info, &lock_ptr); + if(!per_lock_event) return 0; + per_lock_event->last_owner = pid; + // per_lock_event->last_start_hold_time = ts; + per_lock_event->last_hold_delay = ts - per_request->start_hold_time;//持有锁的时间 + bpf_map_update_elem(&per_lock_info, &lock_ptr, per_lock_event, BPF_ANY); return 0; } -SEC("uretprobe/pthread_mutex_unlock") -int BPF_KRETPROBE(pthread_mutex_unlock_exit,int ret) -{ - struct mfutex_ctrl *mfutex_ctrl = get_mfutex_ctrl(); - if(!mfutex_ctrl) return 0; +// SEC("uprobe/__pthread_mutex_trylock") +// int BPF_KPROBE(__pthread_mutex_trylock_enter, void *__mutex) +// { +// record_lock_enter(ignore_tgid,1,1,__mutex,&mfutex_rb,&proc_lock,&lock_ctrl_map); +// return 0; +// } - pid_t pid = bpf_get_current_pid_tgid(); - int tgid = bpf_get_current_pid_tgid() >> 32; - // if(mfutex_ctrl->target_pid == 0 && mfutex_ctrl->target_tgid == 0)//未指定目标进程或线程 - // return 0; - // if((mfutex_ctrl->target_pid != 0 && pid!=mfutex_ctrl->target_pid)|| - // (mfutex_ctrl->target_tgid != 0 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 - // return 0; +// SEC("uretprobe/__pthread_mutex_trylock") +// int BPF_KRETPROBE(__pthread_mutex_trylock_exit,int ret) +// { +// record_lock_exit(ignore_tgid,2,1,ret,&mfutex_rb,&proc_lock,&locktype,&lock_ctrl_map); +// return 0; +// } - u64 *lock_ptr; - u64 temp_lock_ptr; - //找锁 - struct proc_flag proc_flag = {}; - proc_flag.pid = pid; - proc_flag.flag = MUTEX_FLAG; - lock_ptr = bpf_map_lookup_elem(&proc_unlock, &proc_flag); - if(!lock_ptr) - return 0; - temp_lock_ptr = *lock_ptr; - bpf_map_delete_elem(&proc_unlock, &proc_flag); - /*返回值为0,表示解锁成功; - *执行以下操作: - *1:将释放锁的进程从record_lock map中删除; - *2:找到下一个要上锁的线程: 通过遍历被唤醒线程队列和等待锁的队列(record_lock),找到最先被唤醒的线程,就是下一个持有锁的线程; - *3:更新event,将新持有锁的线程信息同步到event数组; - */ - if(ret == 0){ - //1:将释放锁的进程从record_lock map中删除; - struct record_lock_key key = {}; - key.lock_ptr = temp_lock_ptr; - key.cnt = 1; - bpf_map_delete_elem(&record_lock, &key); - bpf_printk("D:lock_addr:0x%x\tpid:%d\t%s\n",temp_lock_ptr,pid,ret==0?"SUCC":"FALSE"); - /*2,3步骤需要到新线程被唤醒时操作;*/ - } +SEC("uprobe/futex") +int trace_futex(struct pt_regs *ctx) { + struct event ev = {}; + ev.pid = bpf_get_current_pid_tgid() >> 32; // 获取进程PID + ev.ts = bpf_ktime_get_ns(); // 获取时间戳 + ev.uaddr = PT_REGS_PARM1(ctx); // 获取futex地址 + ev.futex_op = PT_REGS_PARM2(ctx); // 获取futex操作 + + // 将数据发送到用户态 + bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &ev, sizeof(ev)); return 0; } -//新线程被唤醒时,如果该线程在等待队列(record_lock)中,则说明该线程持有锁; -SEC("tp_btf/sched_wakeup") -int BPF_PROG(sched_wakeup, struct task_struct *p) +/*获取到要加入等待队列的线程,拿到时间*/ +SEC("kprobe/futex_wait") +int BPF_KPROBE(trace_futex_wait, + u32 __user *uaddr, unsigned int flags, + u32 val, ktime_t *abs_time, u32 bitset) { - struct mfutex_ctrl *mfutex_ctrl = get_mfutex_ctrl(); - if(!mfutex_ctrl) return 0; - - pid_t pid = bpf_get_current_pid_tgid(); - int tgid = bpf_get_current_pid_tgid() >> 32; - // if(mfutex_ctrl->target_pid == 0 && mfutex_ctrl->target_tgid == 0)//未指定目标进程或线程 - // return 0; - // if((mfutex_ctrl->target_pid != 0 && pid!=mfutex_ctrl->target_pid)|| - // (mfutex_ctrl->target_tgid != 0 && tgid != mfutex_ctrl->target_tgid))//当前进程或线程非目标进程或线程 - // return 0; - - u64 *lock_ptr; - u64 temp_lock_ptr; - - /*1.在record_lock map中找到当前进程,并将cnt设为1,即持有锁*/ - //1.1找锁 - struct proc_flag proc_flag; - proc_flag.pid = pid; - proc_flag.flag = MUTEX_FLAG; - lock_ptr = bpf_map_lookup_elem(&proc_lock, &proc_flag); - if(!lock_ptr) - return 0; - temp_lock_ptr = *lock_ptr; - bpf_map_delete_elem(&proc_lock, &proc_flag); - - //1.2找cnt - int *cnt; - struct lock_record_key key1 = {} ; - key1.lock_ptr = temp_lock_ptr; - key1.pid = pid; - cnt = bpf_map_lookup_elem(&lock_record, &key1);//找到cnt - if(!cnt) return 0; - //1.3 在record_lock map中找到对应的pid并修改其cnt - struct record_lock_key key2 = {}; - key2.lock_ptr = temp_lock_ptr; - key2.cnt = *cnt; - bpf_map_delete_elem(&record_lock, &key2); - key2.cnt = 1;//修改cnt,表示为锁持有者; - bpf_map_update_elem(&record_lock, &key2, &lock_ptr, BPF_ANY); - //1.4 修改per_lock_info map中的数值,然后更新event - struct per_lock_event *per_lock = bpf_map_lookup_elem(&per_lock_info, &temp_lock_ptr); - if(!per_lock) return 0; - per_lock->owner = pid; - per_lock->time = bpf_ktime_get_ns(); - per_lock->cnt--; - - bpf_printk("lock_addr:0x%x\towner:%d\towner_time:%llu\tcur_pid:%d\n", - temp_lock_ptr,per_lock->owner,per_lock->time,pid); - //1.5 数据上传至ringbuffer - push_to_rb(per_lock); - return 0; -} \ No newline at end of file + +} diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h index 94abd28e5..101146dbe 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h @@ -122,21 +122,6 @@ struct lock_event{ }; //mfutex -struct __pthread_mutex -{ - unsigned int __lock; - unsigned int __owner_id; - unsigned int __cnt; - int __shpid; - int __type; - int __flags; - union - { - unsigned int __reserved[2]; - void *__pointer_aligned; - }; -}; - struct mfutex_ctrl{ bool lock_func; bool enable_myproc; @@ -144,10 +129,18 @@ struct mfutex_ctrl{ pid_t target_tgid; }; +struct per_request{//每条锁请求信息 + int pid; + u64 start_request_time; + u64 start_hold_time; + u64 wait_delay; +}; + struct lock_record_key{ u64 lock_ptr;//哪个锁 int pid;//进程号 }; + struct record_lock_key{ u64 lock_ptr;//哪个锁 int cnt;//第几次申请该锁 @@ -155,9 +148,8 @@ struct record_lock_key{ struct per_lock_event{ u64 lock_ptr; int type;//1:互斥锁;2:读写锁读锁;3:读写锁写锁;4:自旋锁 - - int owner;//目前谁持有锁; - u64 time;//持有锁的时间; + int owner,last_owner;//目前谁持有锁; + u64 start_hold_time,last_hold_delay;//持有锁的时间; int cnt;//等待锁+持有锁的数量; }; diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c index a1178b4aa..b185d67b2 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c @@ -118,6 +118,7 @@ char *lock_status[] = {"", "mutex_req", "mutex_lock", "mutex_unlock", "rdlock_req", "rdlock_lock", "rdlock_unlock", "wrlock_req", "wrlock_lock", "wrlock_unlock", "spinlock_req", "spinlock_lock", "spinlock_unlock"}; +char *mfutex_type[] = {"","MUTEX","RW_LOCK","SPIN_LOCK","RCU_LOCK","FUTEX_LOCK"}; char *keytime_type[] = {"", "exec_enter", "exec_exit", "exit", @@ -533,36 +534,48 @@ static int print_mfutex(void *ctx, void *data,unsigned long data_sz) time_t now = time(NULL);// 获取当前时间 struct tm *localTime = localtime(&now);// 将时间转换为本地时间结构 printf("%02d:%02d:%02d ",localTime->tm_hour, localTime->tm_min, localTime->tm_sec); - int err,record_lock_fd =bpf_map__fd(mfutex_skel->maps.record_lock); + printf("%-12s 0x%x %-10d %-16llu %-11llu %-11lu | ",mfutex_type[e->type],e->lock_ptr,e->owner,e->start_hold_time,e->last_owner,e->last_hold_delay); - printf("0x%-16x %-10d %-11llu | \n",e->lock_ptr,e->owner,e->time); - // pid_t lookup_key = -1 ,next_key; - // int lock_cur_tgid = 0; + int err,record_lock_fd =bpf_map__fd(mfutex_skel->maps.record_lock); - // if(e->tgid != -1) lock_cur_tgid = 2; - // else lock_cur_tgid = 1; - - // if(prev_image != LOCK_IMAGE || env.lock_prev_tgid != lock_cur_tgid){ - // printf("USERLOCK ------------------------------------------------------------------------------------------------\n"); - // printf("%-15s ","TIME"); - // if(e->tgid != -1){ - // printf("%-6s ","TGID"); - // env.lock_prev_tgid = 2; - // } else { - // env.lock_prev_tgid = 1; + struct record_lock_key lookup_key = {-1,-1}, next_key; + while(!bpf_map_get_next_key(record_lock_fd, &lookup_key, &next_key)){ + // printf("next_key:%x target_ptr:%x\n",next_key,e->lock_ptr); + if(next_key.lock_ptr != e->lock_ptr) { + lookup_key = next_key; + continue;//不是目标锁,跳过 + } + struct per_request per_request = {}; + err = bpf_map_lookup_elem(record_lock_fd,&next_key,&per_request); + if (err < 0) { + // printf(stderr, "failed to lookup info: %d\n", err); + lookup_key = next_key; + continue;//不是目标锁,跳过 + } + float wait_delay = (e->start_hold_time-per_request.start_request_time)/1000000000.0; + if(wait_delay<=0||wait_delay>=10000) + printf("%d(NULL) | ",per_request.pid); + else printf("%d(%ds) | ",per_request.pid,((e->start_hold_time-per_request.start_request_time)/1000000000)); + lookup_key = next_key; + } + printf("\n"); + + // struct record_lock_key key; + // key.lock_ptr = e->lock_ptr; + // key.cnt = 1; + // while(key.cnt<=e->cnt){ + // struct per_request per_request; + // err = bpf_map_lookup_elem(record_lock_fd,&key,&per_request); + // if (err < 0) { + // // fprintf(stderr, "failed to lookup info: %d\n", err); + // printf("(%llu|%d) ",key.lock_ptr,key.cnt); + // key.cnt++; + // continue;//没找到,就去找下一个 // } - // printf("%-6s %-15s %s\n","PID","LockAddr","LockStatus"); - // prev_image = LOCK_IMAGE; - // } - - // printf("%-15lld ",e->time); - // if(e->tgid != -1) printf("%-6d ",e->tgid); - // printf("%-6d %-15lld ",e->pid,e->lock_ptr); - // if(e->lock_status==2 || e->lock_status==5 || e->lock_status==8 || e->lock_status==11){ - // printf("%s-%d\n",lock_status[e->lock_status],e->ret); - // }else{ - // printf("%s\n",lock_status[e->lock_status]); + // printf("%d(%lu)| ",per_request.pid,per_request.wait_delay); + // key.cnt++; // } + // printf("\n"); return 0; } @@ -758,7 +771,7 @@ static int mfutex_attach(struct mfutex_bpf *skel) // ATTACH_URETPROBE_CHECKED(skel,__pthread_mutex_trylock,__pthread_mutex_trylock_exit); ATTACH_UPROBE_CHECKED(skel,pthread_mutex_unlock,pthread_mutex_unlock_enter); - ATTACH_URETPROBE_CHECKED(skel,pthread_mutex_unlock,pthread_mutex_unlock_exit); + // ATTACH_URETPROBE_CHECKED(skel,pthread_mutex_unlock,pthread_mutex_unlock_exit); err = mfutex_bpf__attach(skel); @@ -1007,7 +1020,7 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to create mfutex ring buffer\n"); goto cleanup; } - printf("%-16s %-16s %-10s %-11s\n","TIME","LOCK_Addr","Holder","HoldTime"); + printf("%-8s %-12s %-10s %-10s %-16s %-11s %-11s | %10s\n","TIME","LOCK_TYPE","LOCK_Addr","Holder","HoldTime","Last_Holder","Last_Delay","Wait_Proc"); } if(env.enable_keytime){ @@ -1152,7 +1165,7 @@ int main(int argc, char **argv) } if(env.enable_mfutex){ - err = ring_buffer__poll(mfutex_rb, 10); + err = ring_buffer__poll(mfutex_rb, 2000); /* Ctrl-C will cause -EINTR */ if (err == -EINTR) { err = 0;