Index: /pjproject/trunk/pjlib/include/pj/config.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/config.h	(revision 2842)
+++ /pjproject/trunk/pjlib/include/pj/config.h	(revision 2843)
@@ -327,4 +327,16 @@
 #    define PJ_DEBUG		    0
 #  endif
+#endif
+
+/**
+ * Enable this macro to activate logging to mutex/semaphore related events.
+ * This is useful to troubleshoot concurrency problems such as deadlocks.
+ * In addition, you should also add PJ_LOG_HAS_THREAD_ID flag to the
+ * log decoration to assist the troubleshooting.
+ *
+ * Default: 0
+ */
+#ifndef PJ_DEBUG_MUTEX
+#   define PJ_DEBUG_MUTEX	    0
 #endif
 
Index: /pjproject/trunk/pjlib/include/pj/os.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/os.h	(revision 2842)
+++ /pjproject/trunk/pjlib/include/pj/os.h	(revision 2843)
@@ -676,9 +676,5 @@
  * @return	    Non-zero if yes.
  */
-#if defined(PJ_DEBUG) && PJ_DEBUG != 0
-   PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);
-#else
-#  define pj_mutex_is_locked(mutex)	    1
-#endif
+PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);
 
 /**
Index: /pjproject/trunk/pjlib/src/pj/os_core_win32.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_core_win32.c	(revision 2842)
+++ /pjproject/trunk/pjlib/src/pj/os_core_win32.c	(revision 2843)
@@ -39,4 +39,15 @@
 #endif
 
+/* Activate mutex related logging if PJ_DEBUG_MUTEX is set, otherwise
+ * use default level 6 logging.
+ */
+#if defined(PJ_DEBUG_MUTEX) && PJ_DEBUG_MUTEX
+#   undef PJ_DEBUG
+#   define PJ_DEBUG	    1
+#   define LOG_MUTEX(expr)  PJ_LOG(5,expr)
+#else
+#   define LOG_MUTEX(expr)  PJ_LOG(6,expr)
+#endif
+
 #define THIS_FILE	"os_core_win32.c"
 
@@ -905,5 +916,5 @@
     PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
 
-    PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting", 
+    LOG_MUTEX((mutex->obj_name, "Mutex: thread %s is waiting", 
 				pj_thread_this()->obj_name));
 
@@ -918,5 +929,5 @@
 
 #endif
-    PJ_LOG(6,(mutex->obj_name, 
+    LOG_MUTEX((mutex->obj_name, 
 	      (status==PJ_SUCCESS ? "Mutex acquired by thread %s" : "FAILED by %s"),
 	      pj_thread_this()->obj_name));
@@ -949,5 +960,5 @@
 #endif
 
-    PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s", 
+    LOG_MUTEX((mutex->obj_name, "Mutex released by thread %s", 
 				pj_thread_this()->obj_name));
 
@@ -972,5 +983,5 @@
     PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
 
-    PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is trying", 
+    LOG_MUTEX((mutex->obj_name, "Mutex: thread %s is trying", 
 				pj_thread_this()->obj_name));
 
@@ -982,5 +993,5 @@
 #endif
     if (status==PJ_SUCCESS) {
-	PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s", 
+	LOG_MUTEX((mutex->obj_name, "Mutex acquired by thread %s", 
 				  pj_thread_this()->obj_name));
 
@@ -990,5 +1001,5 @@
 #endif
     } else {
-	PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s's trylock() failed", 
+	LOG_MUTEX((mutex->obj_name, "Mutex: thread %s's trylock() failed", 
 				    pj_thread_this()->obj_name));
     }
@@ -1005,5 +1016,5 @@
     PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
 
-    PJ_LOG(6,(mutex->obj_name, "Mutex destroyed"));
+    LOG_MUTEX((mutex->obj_name, "Mutex destroyed"));
 
 #if PJ_WIN32_WINNT >= 0x0400
@@ -1016,13 +1027,16 @@
 }
 
+/*
+ * pj_mutex_is_locked()
+ */
+PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex)
+{
 #if PJ_DEBUG
-/*
- * pj_mutex_is_locked()
- */
-PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex)
-{
     return mutex->owner == pj_thread_this();
-}
-#endif
+#else
+    pj_assert(!"PJ_DEBUG is not set!");
+    return 1;
+#endif
+}
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1083,5 +1097,5 @@
     }
 
-    PJ_LOG(6, (sem->obj_name, "Semaphore created"));
+    LOG_MUTEX((sem->obj_name, "Semaphore created"));
 
     *sem_ptr = sem;
@@ -1096,13 +1110,13 @@
     PJ_ASSERT_RETURN(sem, PJ_EINVAL);
 
-    PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s is waiting", 
+    LOG_MUTEX((sem->obj_name, "Semaphore: thread %s is waiting", 
 			      pj_thread_this()->obj_name));
 
     result = WaitForSingleObject(sem->hSemaphore, timeout);
     if (result == WAIT_OBJECT_0) {
-	PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", 
+	LOG_MUTEX((sem->obj_name, "Semaphore acquired by thread %s", 
 				  pj_thread_this()->obj_name));
     } else {
-	PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s FAILED to acquire", 
+	LOG_MUTEX((sem->obj_name, "Semaphore: thread %s FAILED to acquire", 
 				  pj_thread_this()->obj_name));
     }
@@ -1146,5 +1160,5 @@
     PJ_ASSERT_RETURN(sem, PJ_EINVAL);
 
-    PJ_LOG(6, (sem->obj_name, "Semaphore released by thread %s",
+    LOG_MUTEX((sem->obj_name, "Semaphore released by thread %s",
 			      pj_thread_this()->obj_name));
 
@@ -1163,5 +1177,5 @@
     PJ_ASSERT_RETURN(sem, PJ_EINVAL);
 
-    PJ_LOG(6, (sem->obj_name, "Semaphore destroyed by thread %s",
+    LOG_MUTEX((sem->obj_name, "Semaphore destroyed by thread %s",
 			      pj_thread_this()->obj_name));
 
