#include <pthread_np.h>
#endif
+#if ENABLE_TRACE
int tvh_thread_debug;
static int tvhwatch_done;
static pthread_t thrwatch_tid;
static pthread_mutex_t thrwatch_mutex = PTHREAD_MUTEX_INITIALIZER;
static TAILQ_HEAD(, tvh_mutex) thrwatch_mutexes = TAILQ_HEAD_INITIALIZER(thrwatch_mutexes);
static int64_t tvh_thread_crash_time;
+#endif
/*
* thread routines
char name[17];
};
+#if ENABLE_TRACE
static void
thread_get_name(pthread_t tid, char *buf, int len)
{
// ???
#endif
}
+#endif
static void *
thread_wrapper(void *p)
return pthread_mutex_destroy(&mutex->mutex);
}
+#if ENABLE_TRACE
static void tvh_mutex_add_to_list(tvh_mutex_t *mutex, const char *filename, int lineno)
{
pthread_mutex_lock(&thrwatch_mutex);
TAILQ_INSERT_HEAD(&thrwatch_mutexes, mutex, link);
pthread_mutex_unlock(&thrwatch_mutex);
}
+#endif
+#if ENABLE_TRACE
static void tvh_mutex_check_interval(tvh_mutex_t *mutex)
{
if (tvh_thread_debug > 10000) {
printf("mutex %p at %s:%d took %lldms\n", mutex, mutex->filename, mutex->lineno, diff / (MONOCLOCK_RESOLUTION / 1000));
}
}
+#endif
+#if ENABLE_TRACE
static void tvh_mutex_remove_from_list(tvh_mutex_t *mutex)
{
pthread_mutex_lock(&thrwatch_mutex);
mutex->lineno = 0;
pthread_mutex_unlock(&thrwatch_mutex);
}
+#endif
+#if ENABLE_TRACE
static void tvh_mutex_remove_from_list_keep_info(tvh_mutex_t *mutex)
{
pthread_mutex_lock(&thrwatch_mutex);
tvh_mutex_check_interval(mutex);
pthread_mutex_unlock(&thrwatch_mutex);
}
+#endif
+#if ENABLE_TRACE
int tvh__mutex_lock(tvh_mutex_t *mutex, const char *filename, int lineno)
{
int r = pthread_mutex_lock(&mutex->mutex);
tvh_mutex_add_to_list(mutex, filename, lineno);
return r;
}
+#endif
+#if ENABLE_TRACE
int tvh__mutex_trylock(tvh_mutex_t *mutex, const char *filename, int lineno)
{
int r = pthread_mutex_trylock(&mutex->mutex);
tvh_mutex_add_to_list(mutex, filename, lineno);
return r;
}
+#endif
+#if ENABLE_TRACE
int tvh__mutex_unlock(tvh_mutex_t *mutex)
{
int r;
tvh_mutex_remove_from_list(mutex);
return r;
}
+#endif
int
tvh_mutex_timedlock
{
int r;
+#if ENABLE_TRACE
tvh_mutex_remove_from_list_keep_info(mutex);
+#endif
r = pthread_cond_wait(&cond->cond, &mutex->mutex);
+#if ENABLE_TRACE
tvh_mutex_add_to_list(mutex, NULL, -1);
+#endif
return r;
}
{
int r;
+#if ENABLE_TRACE
tvh_mutex_remove_from_list_keep_info(mutex);
+#endif
#if defined(PLATFORM_DARWIN)
/* Use a relative timedwait implementation */
r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
#endif
+#if ENABLE_TRACE
tvh_mutex_add_to_list(mutex, NULL, -1);
+#endif
return r;
}
{
int r;
+#if ENABLE_TRACE
tvh_mutex_remove_from_list_keep_info(mutex);
+#endif
r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, ts);
+#if ENABLE_TRACE
tvh_mutex_add_to_list(mutex, NULL, -1);
+#endif
return r;
}
abort();
}
+#if ENABLE_TRACE
static void tvh_thread_mutex_deadlock(tvh_mutex_t *mutex)
{
int fd = hts_settings_open_file(HTS_SETTINGS_OPEN_WRITE | HTS_SETTINGS_OPEN_DIRECT, "mutex-deadlock.txt");
fclose(f);
abort();
}
+#endif
+#if ENABLE_TRACE
static void *tvh_thread_watch_thread(void *aux)
{
int64_t now;
}
return NULL;
}
+#endif
void tvh_thread_init(int debug_level)
{
+#if ENABLE_TRACE
tvh_thread_debug = debug_level;
tvh_thread_crash_time = getfastmonoclock() + sec2mono(15);
if (debug_level > 0) {
tvhwatch_done = 0;
tvh_thread_create(&thrwatch_tid, NULL, tvh_thread_watch_thread, NULL, "thrwatch");
}
+#endif
}
void tvh_thread_done(void)
{
+#if ENABLE_TRACE
if (tvh_thread_debug > 0) {
tvhwatch_done = 1;
pthread_join(thrwatch_tid, NULL);
}
+#endif
}
#include <pthread.h>
#include "queue.h"
+#include "build.h"
typedef struct {
pthread_cond_t cond;
typedef struct tvh_mutex {
pthread_mutex_t mutex;
+#if ENABLE_TRACE
pthread_t thread;
const char *filename;
int lineno;
int64_t tstamp;
TAILQ_ENTRY(tvh_mutex) link;
+#endif
} tvh_mutex_t;
/*
*
*/
+#if ENABLE_TRACE
extern int tvh_thread_debug;
+#endif
void tvh_thread_init(int debug_level);
void tvh_thread_done(void);
int tvh_mutex_init(tvh_mutex_t *mutex, const pthread_mutexattr_t *attr);
int tvh_mutex_destroy(tvh_mutex_t *mutex);
+#if ENABLE_TRACE
int tvh__mutex_lock(tvh_mutex_t *mutex, const char *filename, int lineno);
#define tvh_mutex_lock(_mutex) \
({ \
return pthread_mutex_unlock(&mutex->mutex);
return tvh__mutex_unlock(mutex);
}
+#else
+static inline int tvh_mutex_lock(tvh_mutex_t *mutex)
+{
+ return pthread_mutex_lock(&mutex->mutex);
+}
+static inline int tvh_mutex_trylock(tvh_mutex_t *mutex)
+{
+ return pthread_mutex_trylock(&mutex->mutex);
+}
+static inline int tvh_mutex_unlock(tvh_mutex_t *mutex)
+{
+ return pthread_mutex_unlock(&mutex->mutex);
+}
+#endif
int tvh_mutex_timedlock(tvh_mutex_t *mutex, int64_t usec);
int tvh_cond_init(tvh_cond_t *cond, int monotonic);