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

Reply via email to