diff dmlib.c @ 294:dd9809a93425

Improve mutex debugging facilities.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 11 Oct 2012 16:04:02 +0300
parents 32250b436bca
children 3c5ebe88e52f
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