C 有没有办法找到当前pthread持有的pthread_互斥体列表?

C 有没有办法找到当前pthread持有的pthread_互斥体列表?,c,linux,multithreading,pthreads,mutex,C,Linux,Multithreading,Pthreads,Mutex,我尝试在pthread_互斥体上创建一个包装器,它维护当前线程持有的所有互斥体的列表。然而,我也使用了某些库代码,对于这些代码,我不可能使用这个包装器。是否有任何方法可以获取通用pthread_互斥体的此列表? FWIW,我正在使用Linux主机。您可以(例如,通过LD\u PRELOAD和插入pthread\u mutex\u lock()、pthread\u mutex\u trylock()和pthread\u mutex\u unlock()函数,这些函数都是您自己调用的底层函数,但也要

我尝试在pthread_互斥体上创建一个包装器,它维护当前线程持有的所有互斥体的列表。然而,我也使用了某些库代码,对于这些代码,我不可能使用这个包装器。是否有任何方法可以获取通用pthread_互斥体的此列表? FWIW,我正在使用Linux主机。

您可以(例如,通过
LD\u PRELOAD
插入
pthread\u mutex\u lock()
pthread\u mutex\u trylock()
pthread\u mutex\u unlock()
函数,这些函数都是您自己调用的底层函数,但也要维护一个每个线程的数组/锁存互斥地址链。(您可以使用GCC提供的存储类关键字(相当于C11
\u Thread\u local
)来声明每个线程的变量。)


下面是一个经过验证的工作示例

Makefile,要构建插入库和示例程序:

#SPDX许可证标识符:CC0-1.0
CC:=gcc
CFLAGS:=-Wall-Wextra-O2
LDFLAGS:=-pthread-ldl
bin:=libhold.so示例
.骗子:一切顺利
全部:清洁$(垃圾箱)
清洁:
rm-f*.o$(箱子)
run:libhold.so示例
env LD_PRELOAD=./libhold.so./example
%.o:%.c
$(CC)$(CFLAGS)-c$^
libhold.so:libhold.c
$(CC)$(CFLAGS)-fPIC$^-shared-Wl,-soname,$@-ldl-o$@
示例:example.o hold.o
$(CC)$(CFLAGS)$^$(LDFLAGS)-o$@
请注意,Makefiles中的缩进必须使用制表符,因此如果复制粘贴上述内容,则需要修复缩进,例如,通过运行
sed-e的|^*|\t |“-i Makefile

libhold.c,插入库(libhold.so)的实现:

//SPDX许可证标识符:CC0-1.0
#定义GNU源
#包括
#包括
#包括
#包括
#包括
静态int(*original_lock)(pthread_mutex_t*)=NULL;
静态int(*original_trylock)(pthread_mutex_t*)=NULL;
静态int(*original_unlock)(pthread_mutex_t*)=NULL;
静态int HOLD_err=0;
静态uu螺纹尺寸u t保持u max=0;
静态uu螺纹尺寸u t保持u num=0;
静态线程pthread\u mutex\u t**hold\u ptr=NULL;
int libhold_errno(无效)
{
返回uuu原子加载u n(&hold u err,uuu原子顺序u CST);
}
容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量容量
{
返回持有数量;
}
pthread_mutex_t*libhold_mutex(大小\u t i)
{
返回(i=保持最大值){
const int saved_errno=errno;
const size_t temp_max=(hold_num | 127)+121;
无效*温度ptr;
temp_ptr=realloc(保持的_ptr,temp_max*sizeof保持的_ptr[0]);
如果(!temp_ptr){
__原子存储(保留错误、ENOMEM、原子顺序CST);
errno=已保存\u errno;
返回0;
}
保持最大值=温度最大值;
保持时间=临时时间;
}
HOLD_ptr[HOLD_num++]=m;
返回0;
}
int pthread\u mutex\u trylock(pthread\u mutex\u t*m)
{
int(*trylock)(pthread_mutex_t*);
__原子负荷(原始负荷、原始负荷、原子负荷、连续负荷);
如果(!trylock){
trylock=dlsym(RTLD_NEXT,“pthread_mutex_trylock”);
如果(!trylock){
__原子存储(&hold_err,ENOSYS,__原子顺序_CST);
回归分析;
}
__原子存储(原始、原始、原子顺序CST);
}
int-retval=trylock(m);
如果(返回)
返回返回;
如果(保持数量>=保持最大值){
const int saved_errno=errno;
const size_t temp_max=(hold_num | 127)+121;
无效*温度ptr;
temp_ptr=realloc(保持的_ptr,temp_max*sizeof保持的_ptr[0]);
如果(!temp_ptr){
__原子存储(保留错误、ENOMEM、原子顺序CST);
errno=已保存\u errno;
返回0;
}
保持最大值=温度最大值;
保持时间=临时时间;
}
HOLD_ptr[HOLD_num++]=m;
返回0;
}
int pthread_mutex_unlock(pthread_mutex_t*m)
{
int(*解锁)(pthread_mutex_t*);
__原子加载(原始解锁和解锁,原子顺序CST);
如果(!解锁){
unlock=dlsym(RTLD_NEXT,“pthread_mutex_unlock”);
如果(!解锁){
__原子存储(&hold_err,ENOSYS,__原子顺序_CST);
回归分析;
}
__原子存储(原始解锁和解锁,原子顺序CST);
}
int retval=解锁(m);
如果(返回)
返回返回;
尺寸i=0;
而(我<持有数量){
如果(保持_ptr[i]==m){
持有数量--;
如果(i
hold.c,实现获取互斥体跟踪信息所需的接口(互斥体跟踪是否可用,当前线程持有多少互斥体,以及这些互斥体的地址):

//SPDX许可证标识符:CC0-1.0
#定义_POSIX_C_源200809L
#定义GNU源
#包括
#包括
#包括
#包括
静态int libhold\u errno\u默认值(无效)
{
回归分析;
}
静态大小\u t libhold\u计数\u默认值(无效)
{
返回0;
}
静态pthread_mutex_t*libhold_mutex_默认值(size_t i)
{
(void)i;/*消除有关未使用参数的警告;不生成代码*/
返回NULL;
}
静态int(*hold_errno_func)(void)=NULL;
静态尺寸(*保持不变
// SPDX-License-Identifier: CC0-1.0
#define  _POSIX_C_SOURCE  200809L
#define  _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include "held.h"

#ifndef  LOCKS
#define  LOCKS  5
#endif

void print_held(FILE *out)
{
    if (!out)
        out = stdout;

    int err = held_errno();
    if (err == ENOSYS) {
        fprintf(out, "Mutex tracking is not available.\n");
        return;
    } else
    if (err) {
        fprintf(out, "Error in mutex tracking: %s.\n", strerror(err));
        return;
    }

    size_t n = held_count();
    if (n > 0) {
        fprintf(out, "%zu %s held by current thread:\n", n, (n > 1) ? "mutexes" : "mutex");
        for (size_t i = 0; i < n; i++) {
            fprintf(out, "\t%p\n", held_mutex(i));
        }
    } else {
        fprintf(out, "No mutexes held by current thread.\n");
    }
}

int main(void)
{
    pthread_mutex_t  lock[LOCKS];
    size_t           i;

    for (i = 0; i < LOCKS; i++)
        pthread_mutex_init(lock + i, NULL);

    for (i = 0; i < LOCKS; i++)
        pthread_mutex_lock(lock + i);

    print_held(stdout);

    for (i = 0; i < LOCKS; i++)
        pthread_mutex_unlock(lock + i);

    print_held(stdout);

    return EXIT_SUCCESS;
}