Index: /trunk/psLib/src/sys/psMutex.h
===================================================================
--- /trunk/psLib/src/sys/psMutex.h	(revision 19119)
+++ /trunk/psLib/src/sys/psMutex.h	(revision 19120)
@@ -3,9 +3,55 @@
 
 #include <pthread.h>
+#include <assert.h>
 
 typedef pthread_mutex_t psMutex;        /// Mutual Exclusion using pthreads
+//#define PS_MUTEX_CAREFUL                // Use error-checking mutexes, trace messages, check the results
+
+#ifdef PS_MUTEX_CAREFUL
 
 /// Initialize a mutex
 #define psMutexInit(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to initialise mutex"); \
+    psTrace("psLib.sys.mutex", 3, "Initialising mutex on %s...", #PTR); \
+    /* Gotta go the long way, since we can't use PTHREAD_MUTEX_INITIALIZER after we declare the variable */ \
+    pthread_mutexattr_t attr; /* Mutex attributes */ \
+    pthread_mutexattr_init(&attr); \
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); \
+    pthread_mutex_init(&(PTR)->lock, &attr); \
+    pthread_mutexattr_destroy(&attr); \
+}
+
+/// Lock a mutex
+#define psMutexLock(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to lock mutex"); \
+    psTrace("psLib.sys.mutex", 1, "Thread %p waiting for mutex lock on %s...", (void*)pthread_self(), #PTR); \
+    int pml = pthread_mutex_lock(&(PTR)->lock); \
+    psTrace("psLib.sys.mutex", 1, "Thread %p locked mutex on %s", (void*)pthread_self(), #PTR); \
+    if (pml == EINVAL) { \
+        psAbort("Cannot lock mutex on %s: not initialised", #PTR); \
+    } \
+    if (pml == EDEADLK) { \
+        psAbort("Deadlocked mutex on %s", #PTR); \
+    } \
+}
+
+/// Unlock a mutex
+#define psMutexUnlock(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to unlock mutex"); \
+    psTrace("psLib.sys.mutex", 1, "Thread %p unlocking mutex on %s", (void*)pthread_self(), #PTR); \
+    int pmu = pthread_mutex_unlock(&(PTR)->lock); \
+    if (pmu == EINVAL) { \
+        psAbort("Cannot unlock mutex on %s: not initialised", #PTR); \
+    } \
+    if (pmu == EPERM) { \
+        psAbort("Unlocking stolen mutex on %s", #PTR); \
+    } \
+}
+
+#else  // PS_MUTEX_CAREFUL
+
+/// Initialize a mutex
+#define psMutexInit(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to initialise mutex"); \
     /* Gotta go the long way, since we can't use PTHREAD_MUTEX_INITIALIZER after we declare the variable */ \
     pthread_mutexattr_t attr; /* Mutex attributes */ \
@@ -17,19 +63,27 @@
 
 /// Lock a mutex
-#define psMutexLock(PTR) \
-if (pthread_mutex_lock(&(PTR)->lock) == EINVAL) { \
-    psAbort("Cannot lock mutex on %s: not initialised", #PTR); \
+#define psMutexLock(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to lock mutex"); \
+    if (pthread_mutex_lock(&(PTR)->lock) == EINVAL) { \
+        psAbort("Cannot lock mutex on %s: not initialised", #PTR); \
+    } \
 }
 
 /// Unlock a mutex
-#define psMutexUnlock(PTR) \
-if (pthread_mutex_unlock(&(PTR)->lock) == EINVAL) { \
-    psAbort("Cannot unlock mutex on %s: not initialised", #PTR); \
+#define psMutexUnlock(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to unlock mutex"); \
+    if (pthread_mutex_unlock(&(PTR)->lock) == EINVAL) { \
+        psAbort("Cannot unlock mutex on %s: not initialised", #PTR); \
+    } \
 }
 
+#endif // PS_MUTEX_CAREFUL
+
 /// Destroy a mutex
-#define psMutexDestroy(PTR) \
-if (pthread_mutex_destroy(&(PTR)->lock) == EBUSY) { \
-    psAbort("Cannot destroy mutex on %s: is busy", #PTR); \
+#define psMutexDestroy(PTR) { \
+    psAssert(PTR, "Require non-NULL pointer to destroy mutex"); \
+    if (pthread_mutex_destroy(&(PTR)->lock) == EBUSY) { \
+        psAbort("Cannot destroy mutex on %s: is busy", #PTR); \
+    } \
 }
 
