From 515f40908328b96ef0298b7a057bdcb70ed06b21 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 3 Apr 2007 05:01:13 +0000 Subject: [PATCH] Reverted change r857:858...recursive mutex APIs sort of suck for portability. --- platform/unix.c | 64 +++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/platform/unix.c b/platform/unix.c index 858f3be6..2b47cc99 100644 --- a/platform/unix.c +++ b/platform/unix.c @@ -289,7 +289,6 @@ int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a) } /* __PHYSFS_platformSetDefaultAllocator */ - #if (defined PHYSFS_NO_PTHREADS_SUPPORT) PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) { return(0x0001); } @@ -300,6 +299,13 @@ void __PHYSFS_platformReleaseMutex(void *mutex) {} #else +typedef struct +{ + pthread_mutex_t mutex; + pthread_t owner; + PHYSFS_uint32 count; +} PthreadMutex; + /* Just in case; this is a panic value. */ #if ((!defined SIZEOF_INT) || (SIZEOF_INT <= 0)) # define SIZEOF_INT 4 @@ -323,56 +329,62 @@ PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) void *__PHYSFS_platformCreateMutex(void) { - pthread_mutex_t *m = NULL; - pthread_mutexattr_t attr; int rc; - - rc = pthread_mutexattr_init(&attr); - if (rc == 0) - { - rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - if (rc == 0) - { - m = (pthread_mutex_t *) allocator.Malloc(sizeof (pthread_mutex_t)); - if (m == NULL) - rc = ENOMEM; - else - rc = pthread_mutex_init(m, &attr); - } /* if */ - pthread_mutexattr_destroy(&attr); - } /* if */ - + PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex)); + BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL); + rc = pthread_mutex_init(&m->mutex, NULL); if (rc != 0) { allocator.Free(m); BAIL_MACRO(strerror(rc), NULL); } /* if */ + m->count = 0; + m->owner = (pthread_t) 0xDEADBEEF; return((void *) m); } /* __PHYSFS_platformCreateMutex */ void __PHYSFS_platformDestroyMutex(void *mutex) { - pthread_mutex_t *m = (pthread_mutex_t *) mutex; - pthread_mutex_destroy(m); + PthreadMutex *m = (PthreadMutex *) mutex; + + /* Destroying a locked mutex is a bug, but we'll try to be helpful. */ + if ((m->owner == pthread_self()) && (m->count > 0)) + pthread_mutex_unlock(&m->mutex); + + pthread_mutex_destroy(&m->mutex); allocator.Free(m); } /* __PHYSFS_platformDestroyMutex */ int __PHYSFS_platformGrabMutex(void *mutex) { - pthread_mutex_t *m = (pthread_mutex_t *) mutex; - if (pthread_mutex_lock(m) != 0) - return(0); + PthreadMutex *m = (PthreadMutex *) mutex; + pthread_t tid = pthread_self(); + if (m->owner != tid) + { + if (pthread_mutex_lock(&m->mutex) != 0) + return(0); + m->owner = tid; + } /* if */ + + m->count++; return(1); } /* __PHYSFS_platformGrabMutex */ void __PHYSFS_platformReleaseMutex(void *mutex) { - pthread_mutex_t *m = (pthread_mutex_t *) mutex; - pthread_mutex_unlock(m); + PthreadMutex *m = (PthreadMutex *) mutex; + if (m->owner == pthread_self()) + { + if (--m->count == 0) + { + m->owner = (pthread_t) 0xDEADBEEF; + pthread_mutex_unlock(&m->mutex); + } /* if */ + } /* if */ } /* __PHYSFS_platformReleaseMutex */ #endif /* !PHYSFS_NO_PTHREADS_SUPPORT */