changeset 294:dd9809a93425

Improve mutex debugging facilities.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 11 Oct 2012 16:04:02 +0300
parents bc2e8ce003d7
children 04c7e7cefddc
files dmlib.c dmlib.h dmmutex.h
diffstat 3 files changed, 176 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/dmlib.c	Thu Oct 11 16:01:14 2012 +0300
+++ b/dmlib.c	Thu Oct 11 16:04:02 2012 +0300
@@ -197,3 +197,134 @@
         default:                   return "Unknown error";
     }
 }
+
+
+#ifdef DM_MUTEX_DEBUG
+
+static DMMutexLock * dmGetMutexThreadIDLock(DMMutex *mutex)
+{
+    Uint32 id = SDL_ThreadID();
+    int i;
+    for (i = 0; i < 8; i++)
+    {
+        DMMutexLock *lock = &(mutex->locks[i]);
+        if (lock->used && lock->id == id)
+            return lock;
+    }
+    return NULL;
+}
+
+static void dmPrintMutexLocks(DMMutex *mutex, const char *state, const char *file, const int line)
+{
+    int i;
+
+    fprintf(stderr,
+    "----------------------\n"
+    "%s --> %p @ %s:%d\n"
+    "Current thread: %d\n"
+    "Mutex         : %p (created @ %s:%d)\n",
+    state, mutex, file, line,
+    SDL_ThreadID(), mutex, mutex->cr_file, mutex->cr_line);
+
+    for (i = 0; i < 8; i++)
+    {
+        DMMutexLock *lock = &(mutex->locks[i]);
+        if (lock->used)
+        {
+            fprintf(stderr,
+            "Lock #%d: thread=%d, state=%d\n",
+            i, lock->id, lock->state);
+        }
+    }    
+}
+
+int dmDOMutexLock(DMMutex *mutex, const char *file, const int line)
+{
+    if (mutex != NULL)
+    {
+        dmPrintMutexLocks(mutex, "LOCKING", file, line);
+        
+        DMMutexLock *lock = dmGetMutexThreadIDLock(mutex);
+        if (lock != NULL)
+        {
+            int res;
+            if (lock->state == 0)
+                res = SDL_mutexP(mutex->m);
+            else
+                res = 1;
+            lock->state++;
+            fprintf(stderr, "LOCKING %p @ thread=%d done [1].\n", mutex, SDL_ThreadID());
+            return res;
+        }
+        else
+        {
+            int i;
+            for (i = 0; i < 8; i++)
+            {
+                DMMutexLock *lock = &(mutex->locks[i]);
+                if (!lock->used)
+                {
+                    int res;
+                    lock->used = TRUE;
+                    lock->id = SDL_ThreadID();
+                    lock->state++;
+                    res = SDL_mutexP(mutex->m);
+                    fprintf(stderr, "LOCKING %p @ thread=%d done [2].\n", mutex, SDL_ThreadID());
+                    return res;
+                }
+            }
+            return -2;
+        }
+    }
+    return -1;
+}
+
+
+int dmDOMutexUnlock(DMMutex *mutex, const char *file, const int line)
+{
+    if (mutex != NULL)
+    {
+        dmPrintMutexLocks(mutex, "UN-LOCKING", file, line);
+
+        DMMutexLock *lock = dmGetMutexThreadIDLock(mutex);
+        if (lock != NULL)
+        {
+            int res;
+            lock->state--;
+            if (lock->state == 0)
+                res = SDL_mutexV(mutex->m);
+            else
+                res = lock->state;
+            return res;
+        }
+        else
+        {
+            return -2;
+        }
+    }
+    return -1;
+}
+
+
+DMMutex * dmDOCreateMutex(const char *file, const int line)
+{
+    DMMutex *mutex = dmMalloc0(sizeof(DMMutex));
+    if (mutex == NULL)
+        return NULL;
+    mutex->cr_file = dm_strdup(file);
+    mutex->cr_line = line;
+    mutex->m = SDL_CreateMutex();
+    return mutex;
+}
+
+
+void dmDestroyMutex(DMMutex *mutex)
+{
+    if (mutex != NULL)
+    {
+        SDL_DestroyMutex(mutex->m);
+        dmFree(mutex);
+    }
+}
+
+#endif
--- a/dmlib.h	Thu Oct 11 16:01:14 2012 +0300
+++ b/dmlib.h	Thu Oct 11 16:04:02 2012 +0300
@@ -71,14 +71,6 @@
 #define DMRES_RES_FILE  "res.txt"   // Resource data file
 
 
-// Mutexes
-#define DMMutex SDL_mutex
-#define dmCreateMutex() SDL_CreateMutex()
-#define dmDestroyMutex(x) SDL_DestroyMutex(x)
-#define dmMutexLock(x) SDL_mutexP(x)
-#define dmMutexUnlock(x) SDL_mutexV(x)
-
-
 /* Define a boolean type
  */
 #if !defined(FALSE) && !defined(TRUE) && !defined(BOOL)
@@ -381,6 +373,42 @@
 char *     dm_strdup_printf(const char *, ...);
 
 
+/* Mutexes
+ */
+#ifdef DM_MUTEX_DEBUG
+
+typedef struct
+{
+    BOOL used;
+    Uint32 id;
+    int state;
+} DMMutexLock;
+
+typedef struct
+{
+    char *cr_file;
+    int cr_line;
+    SDL_mutex *m;
+    DMMutexLock locks[8];
+} DMMutex;
+
+#define dmMutexLock(x) dmDOMutexLock(x, __FILE__, (int) __LINE__)
+#define dmMutexUnlock(x) dmDOMutexUnlock(x, __FILE__, (int) __LINE__)
+#define dmCreateMutex(x) dmDOCreateMutex(__FILE__, (int) __LINE__)
+
+int        dmDOMutexLock(DMMutex *mutex, const char *file, const int line);
+int        dmDOMutexUnlock(DMMutex *mutex, const char *file, const int line);
+DMMutex *  dmDOCreateMutex(const char *file, const int line);
+void       dmDestroyMutex(DMMutex *mutex);
+
+#else
+#define DMMutex SDL_mutex
+#define dmCreateMutex() SDL_CreateMutex()
+#define dmDestroyMutex(x) SDL_DestroyMutex(x)
+#define dmMutexLock(x) SDL_mutexP(x)
+#define dmMutexUnlock(x) SDL_mutexV(x)
+#endif
+
 /* Endianess swapping macros
  */
 #define DM_SWAP_16_LE_BE(value)    ((Uint16) (   \
--- a/dmmutex.h	Thu Oct 11 16:01:14 2012 +0300
+++ b/dmmutex.h	Thu Oct 11 16:04:02 2012 +0300
@@ -5,24 +5,29 @@
  * (C) Copyright 2012 Tecnic Software productions (TNSP)
  */
 
-int SDL_mutexP(DMMutex *p)
+Uint32 SDL_ThreadID()
+{
+    return 0;
+}
+
+int SDL_mutexP(SDL_mutex *p)
 {
     (void) p;
     return 0;
 }
 
-int SDL_mutexV(DMMutex *p)
+int SDL_mutexV(SDL_mutex *p)
 {
     (void) p;
     return 0;
 }
 
-DMMutex * SDL_CreateMutex()
+SDL_mutex * SDL_CreateMutex()
 {
     return NULL;
 }
 
-void SDL_DestroyMutex(DMMutex *p)
+void SDL_DestroyMutex(SDL_mutex *p)
 {
     (void) p;
 }