Changeset: 2bd1f838ef0f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2bd1f838ef0f
Modified Files:
gdk/gdk_logger.c
gdk/gdk_system.c
gdk/gdk_system.h
Branch: default
Log Message:
In debug builds, maintain a per-thread list of locks that are currently held.
The list can be viewed in the debugger by calling dump_threads() which
prints information (including these locks) for each thread in the system.
diffs (truncated from 374 to 300 lines):
diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c
--- a/gdk/gdk_logger.c
+++ b/gdk/gdk_logger.c
@@ -97,17 +97,8 @@ typedef enum {LOG_OK, LOG_EOF, LOG_ERR}
static gdk_return bm_commit(logger *lg);
static gdk_return tr_grow(trans *tr);
-static inline void
-log_lock(logger *lg)
-{
- MT_lock_set(&lg->lock);
-}
-
-static inline void
-log_unlock(logger *lg)
-{
- MT_lock_unset(&lg->lock);
-}
+#define log_lock(lg) MT_lock_set(&(lg)->lock)
+#define log_unlock(lg) MT_lock_unset(&(lg)->lock)
static inline bte
find_type(logger *lg, int tpe)
diff --git a/gdk/gdk_system.c b/gdk/gdk_system.c
--- a/gdk/gdk_system.c
+++ b/gdk/gdk_system.c
@@ -191,6 +191,9 @@ static struct winthread {
MT_Lock *lockwait; /* lock we're waiting for */
MT_Sema *semawait; /* semaphore we're waiting for */
MT_Cond *condwait; /* condition variable we're waiting for */
+#ifdef LOCK_OWNER
+ MT_Lock *mylocks; /* locks we're holding */
+#endif
struct winthread *joinwait; /* process we are joining with */
const char *working; /* what we're currently doing */
char algorithm[512]; /* the algorithm used in the last operation */
@@ -211,21 +214,33 @@ static DWORD threadslot = TLS_OUT_OF_IND
void
dump_threads(void)
{
- TRC_DEBUG_IF(THRD) {
- EnterCriticalSection(&winthread_cs);
- for (struct winthread *w = winthreads; w; w = w->next) {
- TRC_DEBUG_ENDIF(THRD, "%s, waiting for %s, working on
%.200s\n",
- w->threadname,
- w->lockwait ? w->lockwait->name :
- w->semawait ? w->semawait->name :
- w->condwait ? w->condwait->name :
- w->joinwait ? w->joinwait->threadname :
- "nothing",
- ATOMIC_GET(&w->exited) ? "exiting" :
- w->working ? w->working : "nothing");
+ char buf[1024];
+ EnterCriticalSection(&winthread_cs);
+ for (struct winthread *w = winthreads; w; w = w->next) {
+ int pos = snprintf(buf, sizeof(buf),
+ "%s, waiting for %s, working on %.200s",
+ w->threadname,
+ w->lockwait ? w->lockwait->name :
+ w->semawait ? w->semawait->name :
+ w->condwait ? w->condwait->name :
+ w->joinwait ? w->joinwait->threadname :
+ "nothing",
+ ATOMIC_GET(&w->exited) ? "exiting" :
+ w->working ? w->working : "nothing");
+#ifdef LOCK_OWNER
+ const char *sep = ", locked: ";
+ for (MT_Lock *l = w->mylocks; l && pos < (int) sizeof(buf); l =
l->nxt) {
+ pos += snprintf(buf + pos, sizeof(buf) - pos,
+ "%s%s(%s)", sep, l->name, l->locker);
+ sep = ", ";
}
- LeaveCriticalSection(&winthread_cs);
+#endif
+ TRC_DEBUG_IF(THRD)
+ TRC_DEBUG_ENDIF(THRD, "%s%s\n", buf, pos >= (int)
sizeof(buf) ? "..." : "");
+ else
+ fprintf(stderr, "%s%s\n", buf, pos >= (int) sizeof(buf)
? "..." : "");
}
+ LeaveCriticalSection(&winthread_cs);
}
bool
@@ -345,6 +360,42 @@ MT_thread_setcondwait(MT_Cond *cond)
w->condwait = cond;
}
+#ifdef LOCK_OWNER
+void
+MT_thread_add_mylock(MT_Lock *lock)
+{
+ if (threadslot == TLS_OUT_OF_INDEXES)
+ return;
+ struct winthread *w = TlsGetValue(threadslot);
+
+ if (w) {
+ lock->nxt = w->mylocks;
+ w->mylocks = lock;
+ }
+}
+
+void
+MT_thread_del_mylock(MT_Lock *lock)
+{
+ if (threadslot == TLS_OUT_OF_INDEXES)
+ return;
+ struct winthread *w = TlsGetValue(threadslot);
+
+ if (w) {
+ if (w->mylocks == lock) {
+ w->mylocks = lock->nxt;
+ } else {
+ for (MT_Lock *l = w->mylocks; l; l = l->nxt) {
+ if (l->nxt == lock) {
+ l->nxt = lock->nxt;
+ break;
+ }
+ }
+ }
+ }
+}
+#endif
+
void
MT_thread_setworking(const char *work)
{
@@ -609,6 +660,9 @@ static struct posthread {
MT_Lock *lockwait; /* lock we're waiting for */
MT_Sema *semawait; /* semaphore we're waiting for */
MT_Cond *condwait; /* condition variable we're waiting for */
+#ifdef LOCK_OWNER
+ MT_Lock *mylocks; /* locks we're holding */
+#endif
struct posthread *joinwait; /* process we are joining with */
const char *working; /* what we're currently doing */
char algorithm[512]; /* the algorithm used in the last operation */
@@ -634,21 +688,33 @@ static bool thread_initialized = false;
void
dump_threads(void)
{
- TRC_DEBUG_IF(THRD) {
- pthread_mutex_lock(&posthread_lock);
- for (struct posthread *p = posthreads; p; p = p->next) {
- TRC_DEBUG_ENDIF(THRD, "%s, waiting for %s, working on
%.200s\n",
- p->threadname,
- p->lockwait ? p->lockwait->name :
- p->semawait ? p->semawait->name :
- p->condwait ? p->condwait->name :
- p->joinwait ? p->joinwait->threadname :
- "nothing",
- ATOMIC_GET(&p->exited) ? "exiting" :
- p->working ? p->working : "nothing");
+ char buf[1024];
+ pthread_mutex_lock(&posthread_lock);
+ for (struct posthread *p = posthreads; p; p = p->next) {
+ int pos = snprintf(buf, sizeof(buf),
+ "%s: waiting for %s, working on %.200s",
+ p->threadname,
+ p->lockwait ? p->lockwait->name :
+ p->semawait ? p->semawait->name :
+ p->condwait ? p->condwait->name :
+ p->joinwait ? p->joinwait->threadname :
+ "nothing",
+ ATOMIC_GET(&p->exited) ? "exiting" :
+ p->working ? p->working : "nothing");
+#ifdef LOCK_OWNER
+ const char *sep = ", locked: ";
+ for (MT_Lock *l = p->mylocks; l && pos < (int) sizeof(buf); l =
l->nxt) {
+ pos += snprintf(buf + pos, sizeof(buf) - pos,
+ "%s%s(%s)", sep, l->name, l->locker);
+ sep = ", ";
}
- pthread_mutex_unlock(&posthread_lock);
+#endif
+ TRC_DEBUG_IF(THRD)
+ TRC_DEBUG_ENDIF(THRD, "%s%s\n", buf, pos >= (int)
sizeof(buf) ? "..." : "");
+ else
+ fprintf(stderr, "%s%s\n", buf, pos >= (int) sizeof(buf)
? "..." : "");
}
+ pthread_mutex_unlock(&posthread_lock);
}
bool
@@ -767,6 +833,42 @@ MT_thread_setcondwait(MT_Cond *cond)
p->condwait = cond;
}
+#ifdef LOCK_OWNER
+void
+MT_thread_add_mylock(MT_Lock *lock)
+{
+ if (!thread_initialized)
+ return;
+ struct posthread *p = pthread_getspecific(threadkey);
+
+ if (p) {
+ lock->nxt = p->mylocks;
+ p->mylocks = lock;
+ }
+}
+
+void
+MT_thread_del_mylock(MT_Lock *lock)
+{
+ if (!thread_initialized)
+ return;
+ struct posthread *p = pthread_getspecific(threadkey);
+
+ if (p) {
+ if (p->mylocks == lock) {
+ p->mylocks = lock->nxt;
+ } else {
+ for (MT_Lock *l = p->mylocks; l; l = l->nxt) {
+ if (l->nxt == lock) {
+ l->nxt = lock->nxt;
+ break;
+ }
+ }
+ }
+ }
+}
+#endif
+
void
MT_thread_setworking(const char *work)
{
diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h
--- a/gdk/gdk_system.h
+++ b/gdk/gdk_system.h
@@ -205,6 +205,16 @@ gdk_export void MT_thread_set_qry_ctx(Qr
/* define this to keep lock statistics (can be expensive) */
/* #define LOCK_STATS 1 */
+/* define this to keep track of which locks a thread has acquired */
+#ifndef NDEBUG /* normally only in debug builds */
+#define LOCK_OWNER 1
+#endif
+
+#ifndef LOCK_OWNER
+#define MT_thread_add_mylock(l) ((void) 0)
+#define MT_thread_del_mylock(l) ((void) 0)
+#endif
+
#ifdef LOCK_STATS
#include "gdk_tracer.h"
@@ -215,13 +225,15 @@ gdk_export void MT_thread_set_qry_ctx(Qr
} while (0)
#define _DBG_LOCK_LOCKER(l) \
- do { \
- (l)->locker = __func__; \
- (l)->thread = MT_thread_getname(); \
- } while (0)
+ ( \
+ (l)->locker = __func__, \
+ (l)->thread = MT_thread_getname(), \
+ MT_thread_add_mylock(l) \
+ )
#define _DBG_LOCK_UNLOCKER(l) \
do { \
+ MT_thread_del_mylock(l); \
(l)->locker = __func__; \
(l)->thread = NULL; \
TRC_DEBUG(TEM, "Unlocking %s\n", (l)->name); \
@@ -286,14 +298,31 @@ gdk_export void MT_thread_set_qry_ctx(Qr
#else
+#ifdef LOCK_OWNER
+#define _DBG_LOCK_LOCKER(l) \
+ ( \
+ (l)->locker = __func__, \
+ (l)->thread = MT_thread_getname(), \
+ MT_thread_add_mylock(l) \
+ )
+
+#define _DBG_LOCK_UNLOCKER(l) \
+ do { \
+ MT_thread_del_mylock(l); \
+ (l)->locker = __func__; \
+ (l)->thread = NULL; \
+ } while (0)
+#else
+#define _DBG_LOCK_LOCKER(l) ((void) 0)
+#define _DBG_LOCK_UNLOCKER(l) ((void) 0)
+#endif
+
#define _DBG_LOCK_COUNT_0(l) ((void) 0)
#define _DBG_LOCK_CONTENTION(l) ((void) 0)
#define _DBG_LOCK_SLEEP(l) ((void) 0)
#define _DBG_LOCK_COUNT_2(l) ((void) 0)
#define _DBG_LOCK_INIT(l) ((void) 0)
#define _DBG_LOCK_DESTROY(l) ((void) 0)
-#define _DBG_LOCK_LOCKER(l) ((void) 0)
-#define _DBG_LOCK_UNLOCKER(l) ((void) 0)
#endif
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]