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 -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org