mergerfs/vendored/libfuse/include/mutex_debug.hpp

160 lines
3.6 KiB
C++
Raw Permalink Normal View History

#pragma once
#include "fmt/core.h"
2026-02-20 22:27:55 -06:00
#include <ctime>
#include <cstdlib>
#include <pthread.h>
2025-06-06 19:10:19 -05:00
#ifndef PTHREAD_MUTEX_ADAPTIVE_NP
# define PTHREAD_MUTEX_ADAPTIVE_NP PTHREAD_MUTEX_NORMAL
#endif
2026-02-20 22:27:55 -06:00
#define mutex_init(M) _mutex_init((M),__FILE__,__func__,__LINE__)
#define mutex_destroy(M) _mutex_destroy((M),__FILE__,__func__,__LINE__)
#define mutex_lock(M) _mutex_lock((M),__FILE__,__func__,__LINE__)
#define mutex_unlock(M) _mutex_unlock((M),__FILE__,__func__,__LINE__)
static
inline
void
_print_error_and_abort(const char *func1_,
const int errno_,
const char *file_,
const char *func2_,
const int linenum_)
{
fmt::println(stderr,
"ERROR: {} returned {} ({}) - ({}:{}:{})",
func1_,
errno_,
strerror(errno_),
file_,
func2_,
linenum_);
2026-02-20 22:27:55 -06:00
std::abort();
}
static
inline
void
2026-02-20 22:27:55 -06:00
_mutex_init(pthread_mutex_t &mutex_,
const char *file_,
const char *func_,
const int linenum_)
{
int rv;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ADAPTIVE_NP);
2026-02-20 22:27:55 -06:00
rv = pthread_mutex_init(&mutex_,&attr);
if(rv != 0)
_print_error_and_abort(__func__,rv,file_,func_,linenum_);
pthread_mutexattr_destroy(&attr);
}
static
inline
void
2026-02-20 22:27:55 -06:00
_mutex_destroy(pthread_mutex_t &mutex_,
const char *file_,
const char *func_,
const int linenum_)
{
int rv;
2026-02-20 22:27:55 -06:00
rv = pthread_mutex_destroy(&mutex_);
if(rv != 0)
_print_error_and_abort(__func__,rv,file_,func_,linenum_);
}
static
inline
void
2026-02-20 22:27:55 -06:00
_mutex_lock(pthread_mutex_t &mutex_,
const char *file_,
const char *func_,
const int linenum_)
{
int rv;
int cnt = 0;
timespec timeout;
while(true)
{
clock_gettime(CLOCK_REALTIME,&timeout);
timeout.tv_nsec += 1000000 * 1; // 1ms
if(timeout.tv_nsec >= 1000000000)
{
timeout.tv_sec += 1;
timeout.tv_nsec -= 1000000000;
}
2026-02-20 22:27:55 -06:00
rv = pthread_mutex_timedlock(&mutex_,&timeout);
switch(rv)
{
case 0:
return;
case ETIMEDOUT:
2025-06-06 19:10:19 -05:00
cnt++;
fmt::println(stderr,
"NOTICE: pthread_mutex_timedlock expired - count={}; ({}:{}:{})",
cnt,
file_,
func_,
linenum_);
continue;
default:
_print_error_and_abort(__func__,rv,file_,func_,linenum_);
return;
}
}
}
static
inline
void
2026-02-20 22:27:55 -06:00
_mutex_unlock(pthread_mutex_t &mutex_,
const char *file_,
const char *func_,
const int linenum_)
{
int rv;
2026-02-20 22:27:55 -06:00
rv = pthread_mutex_unlock(&mutex_);
if(rv != 0)
_print_error_and_abort(__func__,rv,file_,func_,linenum_);
}
class ScopedMutexLock
{
private:
pthread_mutex_t &_mutex;
const char *_file;
const char *_func;
int _line;
public:
ScopedMutexLock(pthread_mutex_t &mutex_,
const char *file_,
const char *func_,
int line_)
: _mutex(mutex_), _file(file_), _func(func_), _line(line_)
{
_mutex_lock(_mutex,_file,_func,_line);
}
~ScopedMutexLock()
{
_mutex_unlock(_mutex,_file,_func,_line);
}
ScopedMutexLock(const ScopedMutexLock&) = delete;
ScopedMutexLock& operator=(const ScopedMutexLock&) = delete;
};