29#ifndef DT_SYSTEM_DTPTHREAD_H
30#define DT_SYSTEM_DTPTHREAD_H
32#include "external/ThreadSafetyAnalysis.h"
69typedef struct CAPABILITY(
"mutex") dt_pthread_mutex_t
71 pthread_mutex_t
mutex;
106 if(mutexattr)
return pthread_mutex_init(&
mutex->mutex, mutexattr);
108 pthread_mutexattr_t recursive;
109 int res = pthread_mutexattr_init(&recursive);
111 res = pthread_mutexattr_settype(&recursive, PTHREAD_MUTEX_RECURSIVE);
112 if(!
res)
res = pthread_mutex_init(&
mutex->mutex, &recursive);
113 pthread_mutexattr_destroy(&recursive);
119 return pthread_mutex_lock(&
mutex->mutex);
124 return pthread_mutex_trylock(&
mutex->mutex);
129 return pthread_mutex_unlock(&
mutex->mutex);
134 return pthread_mutex_destroy(&
mutex->mutex);
151 return pthread_cond_wait(cond, &
mutex->mutex);
171typedef struct CAPABILITY(
"rwlock") dt_pthread_rwlock_t
173 pthread_rwlock_t
lock;
181 long last_holder_tid;
182 gboolean last_holder_was_writer;
187 int active_reader_count;
188 double oldest_active_reader_since;
189 long oldest_active_reader_tid;
195 lock->writer_depth = 0;
197 lock->last_holder_tid = 0;
199 lock->active_reader_count = 0;
200 lock->oldest_active_reader_since = 0.0;
201 lock->oldest_active_reader_tid = 0;
202 return pthread_rwlock_init(&
lock->lock, attr);
214 return pthread_rwlock_destroy(&
lock->lock);
219 if(pthread_equal(
rwlock->writer, pthread_self()) &&
rwlock->writer_depth > 1)
224 const gboolean writer_was_self = pthread_equal(
rwlock->writer, pthread_self());
225 if(
rwlock->name && !writer_was_self)
229 if(__sync_fetch_and_sub(&
rwlock->active_reader_count, 1) == 1)
231 rwlock->oldest_active_reader_since = 0.0;
232 rwlock->oldest_active_reader_tid = 0;
235 const int res = pthread_rwlock_unlock(&
rwlock->lock);
239 __sync_bool_compare_and_swap(&(
rwlock->writer), pthread_self(), 0);
254 unsigned long prev_holder, gboolean prev_was_writer);
256 unsigned long prev_holder, gboolean prev_was_writer,
257 int active_readers,
unsigned long oldest_reader_tid,
258 double oldest_reader_age_ms);
263 clock_gettime(CLOCK_MONOTONIC, &ts);
264 return ts.tv_sec + ts.tv_nsec / 1e9;
269 if(pthread_equal(
rwlock->writer, pthread_self()) &&
rwlock->writer_depth >= 1)
277 const long _prev_holder =
rwlock->last_holder_tid;
278 const gboolean _prev_was_writer =
rwlock->last_holder_was_writer;
279 const int res = pthread_rwlock_rdlock(&
rwlock->lock);
283 (
unsigned long)_prev_holder, _prev_was_writer);
286 rwlock->last_holder_tid = (long)pthread_self();
288 if(__sync_fetch_and_add(&
rwlock->active_reader_count, 1) == 0)
291 rwlock->oldest_active_reader_tid = (long)pthread_self();
296 return pthread_rwlock_rdlock(&
rwlock->lock);
301 if(pthread_equal(
rwlock->writer, pthread_self()) &&
rwlock->writer_depth >= 1)
309 const long _prev_holder =
rwlock->last_holder_tid;
310 const gboolean _prev_was_writer =
rwlock->last_holder_was_writer;
311 const int _readers_now =
rwlock->active_reader_count;
312 const long _oldest_reader_tid =
rwlock->oldest_active_reader_tid;
313 const double _oldest_reader_age_ms
314 = _readers_now > 0 ? (_start -
rwlock->oldest_active_reader_since) * 1000.0 : 0.0;
315 const int res = pthread_rwlock_wrlock(&
rwlock->lock);
319 (
unsigned long)_prev_holder, _prev_was_writer, _readers_now,
320 (
unsigned long)_oldest_reader_tid, _oldest_reader_age_ms);
323 __sync_lock_test_and_set(&(
rwlock->writer), pthread_self());
325 rwlock->last_holder_tid = (long)pthread_self();
330 const int res = pthread_rwlock_wrlock(&
rwlock->lock);
333 __sync_lock_test_and_set(&(
rwlock->writer), pthread_self());
344 if(pthread_equal(
rwlock->writer, pthread_self()) &&
rwlock->writer_depth >= 1)
return EBUSY;
345 return pthread_rwlock_tryrdlock(&
rwlock->lock);
350 if(pthread_equal(
rwlock->writer, pthread_self()) &&
rwlock->writer_depth >= 1)
return EBUSY;
351 const int res = pthread_rwlock_trywrlock(&
rwlock->lock);
354 __sync_lock_test_and_set(&(
rwlock->writer), pthread_self());
360#define dt_pthread_rwlock_rdlock_with_caller(A,B,C) dt_pthread_rwlock_rdlock(A)
361#define dt_pthread_rwlock_wrlock_with_caller(A,B,C) dt_pthread_rwlock_wrlock(A)
362#define dt_pthread_rwlock_tryrdlock_with_caller(A,B,C) dt_pthread_rwlock_tryrdlock(A)
363#define dt_pthread_rwlock_trywrlock_with_caller(A,B,C) dt_pthread_rwlock_trywrlock(A)
369 return pthread_mutex_lock(&
mutex->mutex);
374 return pthread_mutex_trylock(&
mutex->mutex);
379 return pthread_mutex_unlock(&
mutex->mutex);
382int dt_pthread_create(pthread_t *thread,
void *(*start_routine)(
void *),
void *arg,
const gboolean realtime);
static int rwlock NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_BAD_lock(dt_pthread_mutex_t *mutex)
int dt_pthread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg, const gboolean realtime)
struct CAPABILITY("mutex") dt_pthread_mutex_t
void _dt_pthread_rwlock_diag_log_rdlock(const char *name, unsigned long tid, double wait_ms, unsigned long prev_holder, gboolean prev_was_writer)
static int dt_pthread_rwlock_wrlock(dt_pthread_rwlock_t *rwlock) ACQUIRE(rwlock) NO_THREAD_SAFETY_ANALYSIS
return pthread_rwlock_tryrdlock & rwlock
static int dt_pthread_rwlock_trywrlock(dt_pthread_rwlock_t *rwlock) TRY_ACQUIRE(0
static int dt_pthread_mutex_BAD_trylock(dt_pthread_mutex_t *mutex)
static double _dt_pthread_rwlock_diag_now(void)
static int dt_pthread_mutex_BAD_unlock(dt_pthread_mutex_t *mutex)
static void dt_pthread_rwlock_set_name(dt_pthread_rwlock_t *lock, const char *name)
static int dt_pthread_rwlock_unlock(dt_pthread_rwlock_t *rwlock) RELEASE_GENERIC(rwlock) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_rwlock_rdlock(dt_pthread_rwlock_t *rwlock) ACQUIRE_SHARED(rwlock) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Initialise a mutex. With mutexattr NULL – which is how 54 of the 56 call sites in this tree spell it ...
void _dt_pthread_rwlock_diag_log_wrlock(const char *name, unsigned long tid, double wait_ms, unsigned long prev_holder, gboolean prev_was_writer, int active_readers, unsigned long oldest_reader_tid, double oldest_reader_age_ms)
static int dt_pthread_rwlock_destroy(dt_pthread_rwlock_t *lock)
static int dt_pthread_rwlock_tryrdlock(dt_pthread_rwlock_t *rwlock) TRY_ACQUIRE_SHARED(0
static int dt_pthread_mutex_trylock(dt_pthread_mutex_t *mutex) TRY_ACQUIRE(0
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
void dt_pthread_setname(const char *name)
static int dt_pthread_rwlock_init(dt_pthread_rwlock_t *lock, const pthread_rwlockattr_t *attr)
static int dt_pthread_cond_wait(pthread_cond_t *cond, dt_pthread_mutex_t *mutex)
Wait on cond, releasing mutex for the duration.
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS