|
|
@ -737,74 +737,143 @@ endian_flip128(void __maybe_unused *dest_p, const void __maybe_unused *src_p) |
|
|
|
|
|
|
|
|
|
|
|
extern void _quit(int status); |
|
|
|
extern void _quit(int status); |
|
|
|
|
|
|
|
|
|
|
|
#define mutex_lock(_lock) _mutex_lock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
/*
|
|
|
|
#define mutex_unlock_noyield(_lock) _mutex_unlock_noyield(_lock, __FILE__, __func__, __LINE__) |
|
|
|
* Set this to non-zero to enable lock tracking |
|
|
|
#define wr_lock(_lock) _wr_lock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
* Use the API lockstats command to see the locking status on stderr |
|
|
|
#define rd_lock(_lock) _rd_lock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
* i.e. in your log file if you 2> log.log - but not on the screen |
|
|
|
#define rw_unlock(_lock) _rw_unlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
* API lockstats is privilidged but will always exist and will return |
|
|
|
#define mutex_init(_lock) _mutex_init(_lock, __FILE__, __func__, __LINE__) |
|
|
|
* success if LOCK_TRACKING is enabled and warning if disabled |
|
|
|
#define rwlock_init(_lock) _rwlock_init(_lock, __FILE__, __func__, __LINE__) |
|
|
|
* In production code, this should never be enabled since it will slow down all locking |
|
|
|
|
|
|
|
* So, e.g. use it to track down a deadlock - after a reproducable deadlock occurs |
|
|
|
|
|
|
|
* ... Of course if the API code itself deadlocks, it wont help :) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
#define LOCK_TRACKING 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if LOCK_TRACKING |
|
|
|
|
|
|
|
enum cglock_typ { |
|
|
|
|
|
|
|
CGLOCK_MUTEX, |
|
|
|
|
|
|
|
CGLOCK_RW, |
|
|
|
|
|
|
|
CGLOCK_UNKNOWN |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern uint64_t api_getlock(void *lock, const char *file, const char *func, const int line); |
|
|
|
|
|
|
|
extern void api_gotlock(uint64_t id, void *lock, const char *file, const char *func, const int line); |
|
|
|
|
|
|
|
extern uint64_t api_trylock(void *lock, const char *file, const char *func, const int line); |
|
|
|
|
|
|
|
extern void api_didlock(uint64_t id, int ret, void *lock, const char *file, const char *func, const int line); |
|
|
|
|
|
|
|
extern void api_gunlock(void *lock, const char *file, const char *func, const int line); |
|
|
|
|
|
|
|
extern void api_initlock(void *lock, enum cglock_typ typ, const char *file, const char *func, const int line); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define GETLOCK(_lock, _file, _func, _line) uint64_t _id1 = api_getlock((void *)(_lock), _file, _func, _line) |
|
|
|
|
|
|
|
#define GOTLOCK(_lock, _file, _func, _line) api_gotlock(_id1, (void *)(_lock), _file, _func, _line) |
|
|
|
|
|
|
|
#define TRYLOCK(_lock, _file, _func, _line) uint64_t _id2 = api_trylock((void *)(_lock), _file, _func, _line) |
|
|
|
|
|
|
|
#define DIDLOCK(_ret, _lock, _file, _func, _line) api_didlock(_id2, _ret, (void *)(_lock), _file, _func, _line) |
|
|
|
|
|
|
|
#define GUNLOCK(_lock, _file, _func, _line) api_gunlock((void *)(_lock), _file, _func, _line) |
|
|
|
|
|
|
|
#define INITLOCK(_lock, _typ, _file, _func, _line) api_initlock((void *)(_lock), _typ, _file, _func, _line) |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
#define GETLOCK(_lock, _file, _func, _line) |
|
|
|
|
|
|
|
#define GOTLOCK(_lock, _file, _func, _line) |
|
|
|
|
|
|
|
#define TRYLOCK(_lock, _file, _func, _line) |
|
|
|
|
|
|
|
#define DIDLOCK(_ret, _lock, _file, _func, _line) |
|
|
|
|
|
|
|
#define GUNLOCK(_lock, _file, _func, _line) |
|
|
|
|
|
|
|
#define INITLOCK(_typ, _lock, _file, _func, _line) |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define mutex_lock(_lock) _mutex_lock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define mutex_unlock_noyield(_lock) _mutex_unlock_noyield(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define mutex_unlock(_lock) _mutex_unlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define mutex_trylock(_lock) _mutex_trylock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define wr_lock(_lock) _wr_lock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define rd_lock(_lock) _rd_lock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define rw_unlock(_lock) _rw_unlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define rd_unlock_noyield(_lock) _rd_unlock_noyield(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define wr_unlock_noyield(_lock) _wr_unlock_noyield(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define rd_unlock(_lock) _rd_unlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define wr_unlock(_lock) _wr_unlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define mutex_init(_lock) _mutex_init(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define rwlock_init(_lock) _rwlock_init(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cglock_init(_lock) _cglock_init(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_rlock(_lock) _cg_rlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_ilock(_lock) _cg_ilock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_ulock(_lock) _cg_ulock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_wlock(_lock) _cg_wlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_dwlock(_lock) _cg_dwlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_dwilock(_lock) _cg_dwilock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_dlock(_lock) _cg_dlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_runlock(_lock) _cg_runlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_ruwlock(_lock) _cg_ruwlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
#define cg_wunlock(_lock) _cg_wunlock(_lock, __FILE__, __func__, __LINE__) |
|
|
|
|
|
|
|
|
|
|
|
static inline void _mutex_lock(pthread_mutex_t *lock, const char *file, const char *func, const int line) |
|
|
|
static inline void _mutex_lock(pthread_mutex_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
GETLOCK(lock, file, func, line); |
|
|
|
if (unlikely(pthread_mutex_lock(lock))) |
|
|
|
if (unlikely(pthread_mutex_lock(lock))) |
|
|
|
quitfrom(1, file, func, line, "WTF MUTEX ERROR ON LOCK! errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "WTF MUTEX ERROR ON LOCK! errno=%d", errno); |
|
|
|
|
|
|
|
GOTLOCK(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void _mutex_unlock_noyield(pthread_mutex_t *lock, const char *file, const char *func, const int line) |
|
|
|
static inline void _mutex_unlock_noyield(pthread_mutex_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely(pthread_mutex_unlock(lock))) |
|
|
|
if (unlikely(pthread_mutex_unlock(lock))) |
|
|
|
quitfrom(1, file, func, line, "WTF MUTEX ERROR ON UNLOCK! errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "WTF MUTEX ERROR ON UNLOCK! errno=%d", errno); |
|
|
|
|
|
|
|
GUNLOCK(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void mutex_unlock(pthread_mutex_t *lock) |
|
|
|
static inline void _mutex_unlock(pthread_mutex_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutex_unlock_noyield(lock); |
|
|
|
_mutex_unlock_noyield(lock, file, func, line); |
|
|
|
sched_yield(); |
|
|
|
sched_yield(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline int mutex_trylock(pthread_mutex_t *lock) |
|
|
|
static inline int _mutex_trylock(pthread_mutex_t *lock, __maybe_unused const char *file, __maybe_unused const char *func, __maybe_unused const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return pthread_mutex_trylock(lock); |
|
|
|
TRYLOCK(lock, file, func, line); |
|
|
|
|
|
|
|
int ret = pthread_mutex_trylock(lock); |
|
|
|
|
|
|
|
DIDLOCK(ret, lock, file, func, line); |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void _wr_lock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
static inline void _wr_lock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
GETLOCK(lock, file, func, line); |
|
|
|
if (unlikely(pthread_rwlock_wrlock(lock))) |
|
|
|
if (unlikely(pthread_rwlock_wrlock(lock))) |
|
|
|
quitfrom(1, file, func, line, "WTF WRLOCK ERROR ON LOCK! errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "WTF WRLOCK ERROR ON LOCK! errno=%d", errno); |
|
|
|
|
|
|
|
GOTLOCK(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void _rd_lock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
static inline void _rd_lock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
GETLOCK(lock, file, func, line); |
|
|
|
if (unlikely(pthread_rwlock_rdlock(lock))) |
|
|
|
if (unlikely(pthread_rwlock_rdlock(lock))) |
|
|
|
quitfrom(1, file, func, line, "WTF RDLOCK ERROR ON LOCK! errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "WTF RDLOCK ERROR ON LOCK! errno=%d", errno); |
|
|
|
|
|
|
|
GOTLOCK(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void _rw_unlock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
static inline void _rw_unlock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely(pthread_rwlock_unlock(lock))) |
|
|
|
if (unlikely(pthread_rwlock_unlock(lock))) |
|
|
|
quitfrom(1, file, func, line, "WTF RWLOCK ERROR ON UNLOCK! errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "WTF RWLOCK ERROR ON UNLOCK! errno=%d", errno); |
|
|
|
|
|
|
|
GUNLOCK(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void rd_unlock_noyield(pthread_rwlock_t *lock) |
|
|
|
static inline void _rd_unlock_noyield(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rw_unlock(lock); |
|
|
|
_rw_unlock(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void wr_unlock_noyield(pthread_rwlock_t *lock) |
|
|
|
static inline void _wr_unlock_noyield(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rw_unlock(lock); |
|
|
|
_rw_unlock(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void rd_unlock(pthread_rwlock_t *lock) |
|
|
|
static inline void _rd_unlock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rw_unlock(lock); |
|
|
|
_rw_unlock(lock, file, func, line); |
|
|
|
sched_yield(); |
|
|
|
sched_yield(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void wr_unlock(pthread_rwlock_t *lock) |
|
|
|
static inline void _wr_unlock(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rw_unlock(lock); |
|
|
|
_rw_unlock(lock, file, func, line); |
|
|
|
sched_yield(); |
|
|
|
sched_yield(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -812,86 +881,88 @@ static inline void _mutex_init(pthread_mutex_t *lock, const char *file, const ch |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely(pthread_mutex_init(lock, NULL))) |
|
|
|
if (unlikely(pthread_mutex_init(lock, NULL))) |
|
|
|
quitfrom(1, file, func, line, "Failed to pthread_mutex_init errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "Failed to pthread_mutex_init errno=%d", errno); |
|
|
|
|
|
|
|
INITLOCK(lock, CGLOCK_MUTEX, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void _rwlock_init(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
static inline void _rwlock_init(pthread_rwlock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely(pthread_rwlock_init(lock, NULL))) |
|
|
|
if (unlikely(pthread_rwlock_init(lock, NULL))) |
|
|
|
quitfrom(1, file, func, line, "Failed to pthread_rwlock_init errno=%d", errno); |
|
|
|
quitfrom(1, file, func, line, "Failed to pthread_rwlock_init errno=%d", errno); |
|
|
|
|
|
|
|
INITLOCK(lock, CGLOCK_RW, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void cglock_init(cglock_t *lock) |
|
|
|
static inline void _cglock_init(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutex_init(&lock->mutex); |
|
|
|
_mutex_init(&lock->mutex, file, func, line); |
|
|
|
rwlock_init(&lock->rwlock); |
|
|
|
_rwlock_init(&lock->rwlock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Read lock variant of cglock. Cannot be promoted. */ |
|
|
|
/* Read lock variant of cglock. Cannot be promoted. */ |
|
|
|
static inline void cg_rlock(cglock_t *lock) |
|
|
|
static inline void _cg_rlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutex_lock(&lock->mutex); |
|
|
|
_mutex_lock(&lock->mutex, file, func, line); |
|
|
|
rd_lock(&lock->rwlock); |
|
|
|
_rd_lock(&lock->rwlock, file, func, line); |
|
|
|
mutex_unlock_noyield(&lock->mutex); |
|
|
|
_mutex_unlock_noyield(&lock->mutex, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Intermediate variant of cglock - behaves as a read lock but can be promoted
|
|
|
|
/* Intermediate variant of cglock - behaves as a read lock but can be promoted
|
|
|
|
* to a write lock or demoted to read lock. */ |
|
|
|
* to a write lock or demoted to read lock. */ |
|
|
|
static inline void cg_ilock(cglock_t *lock) |
|
|
|
static inline void _cg_ilock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutex_lock(&lock->mutex); |
|
|
|
_mutex_lock(&lock->mutex, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Upgrade intermediate variant to a write lock */ |
|
|
|
/* Upgrade intermediate variant to a write lock */ |
|
|
|
static inline void cg_ulock(cglock_t *lock) |
|
|
|
static inline void _cg_ulock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
wr_lock(&lock->rwlock); |
|
|
|
_wr_lock(&lock->rwlock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Write lock variant of cglock */ |
|
|
|
/* Write lock variant of cglock */ |
|
|
|
static inline void cg_wlock(cglock_t *lock) |
|
|
|
static inline void _cg_wlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutex_lock(&lock->mutex); |
|
|
|
_mutex_lock(&lock->mutex, file, func, line); |
|
|
|
wr_lock(&lock->rwlock); |
|
|
|
_wr_lock(&lock->rwlock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Downgrade write variant to a read lock */ |
|
|
|
/* Downgrade write variant to a read lock */ |
|
|
|
static inline void cg_dwlock(cglock_t *lock) |
|
|
|
static inline void _cg_dwlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
wr_unlock_noyield(&lock->rwlock); |
|
|
|
_wr_unlock_noyield(&lock->rwlock, file, func, line); |
|
|
|
rd_lock(&lock->rwlock); |
|
|
|
_rd_lock(&lock->rwlock, file, func, line); |
|
|
|
mutex_unlock_noyield(&lock->mutex); |
|
|
|
_mutex_unlock_noyield(&lock->mutex, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Demote a write variant to an intermediate variant */ |
|
|
|
/* Demote a write variant to an intermediate variant */ |
|
|
|
static inline void cg_dwilock(cglock_t *lock) |
|
|
|
static inline void _cg_dwilock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
wr_unlock(&lock->rwlock); |
|
|
|
_wr_unlock(&lock->rwlock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Downgrade intermediate variant to a read lock */ |
|
|
|
/* Downgrade intermediate variant to a read lock */ |
|
|
|
static inline void cg_dlock(cglock_t *lock) |
|
|
|
static inline void _cg_dlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rd_lock(&lock->rwlock); |
|
|
|
_rd_lock(&lock->rwlock, file, func, line); |
|
|
|
mutex_unlock_noyield(&lock->mutex); |
|
|
|
_mutex_unlock_noyield(&lock->mutex, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void cg_runlock(cglock_t *lock) |
|
|
|
static inline void _cg_runlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rd_unlock(&lock->rwlock); |
|
|
|
_rd_unlock(&lock->rwlock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* This drops the read lock and grabs a write lock. It does NOT protect data
|
|
|
|
/* This drops the read lock and grabs a write lock. It does NOT protect data
|
|
|
|
* between the two locks! */ |
|
|
|
* between the two locks! */ |
|
|
|
static inline void cg_ruwlock(cglock_t *lock) |
|
|
|
static inline void _cg_ruwlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
rd_unlock_noyield(&lock->rwlock); |
|
|
|
_rd_unlock_noyield(&lock->rwlock, file, func, line); |
|
|
|
cg_wlock(lock); |
|
|
|
_cg_wlock(lock, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void cg_wunlock(cglock_t *lock) |
|
|
|
static inline void _cg_wunlock(cglock_t *lock, const char *file, const char *func, const int line) |
|
|
|
{ |
|
|
|
{ |
|
|
|
wr_unlock_noyield(&lock->rwlock); |
|
|
|
_wr_unlock_noyield(&lock->rwlock, file, func, line); |
|
|
|
mutex_unlock(&lock->mutex); |
|
|
|
_mutex_unlock(&lock->mutex, file, func, line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct pool; |
|
|
|
struct pool; |
|
|
@ -942,6 +1013,10 @@ extern bool opt_bfl_noncerange; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
extern int swork_id; |
|
|
|
extern int swork_id; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if LOCK_TRACKING |
|
|
|
|
|
|
|
extern pthread_mutex_t lockstat_lock; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
extern pthread_rwlock_t netacc_lock; |
|
|
|
extern pthread_rwlock_t netacc_lock; |
|
|
|
|
|
|
|
|
|
|
|
extern const uint32_t sha256_init_state[]; |
|
|
|
extern const uint32_t sha256_init_state[]; |
|
|
@ -1329,6 +1404,8 @@ struct work { |
|
|
|
int subid; |
|
|
|
int subid; |
|
|
|
// Allow devices to flag work for their own purposes
|
|
|
|
// Allow devices to flag work for their own purposes
|
|
|
|
bool devflag; |
|
|
|
bool devflag; |
|
|
|
|
|
|
|
// Allow devices to timestamp work for their own purposes
|
|
|
|
|
|
|
|
struct timeval tv_stamp; |
|
|
|
|
|
|
|
|
|
|
|
struct timeval tv_getwork; |
|
|
|
struct timeval tv_getwork; |
|
|
|
struct timeval tv_getwork_reply; |
|
|
|
struct timeval tv_getwork_reply; |
|
|
|