Made unix mutexes recursive.

This commit is contained in:
Ryan C. Gordon 2005-09-20 04:01:36 +00:00
parent a1208dae33
commit c28540fe89
2 changed files with 41 additions and 7 deletions

View File

@ -2,6 +2,8 @@
* CHANGELOG. * CHANGELOG.
*/ */
09192005 - Make unix mutexes recursive above pthread layer...fixes deadlock on
MacOS X, for now.
09182005 - API BREAKAGE: PHYSFS_enumerateFilesCallback() now passes the 09182005 - API BREAKAGE: PHYSFS_enumerateFilesCallback() now passes the
original directory name back to the app in the callback. This original directory name back to the app in the callback. This
API was only in 1.1.0, and wasn't promised to be stable at this API was only in 1.1.0, and wasn't promised to be stable at this

View File

@ -466,6 +466,13 @@ void __PHYSFS_platformReleaseMutex(void *mutex) {}
#else #else
typedef struct
{
pthread_mutex_t mutex;
pthread_t owner;
PHYSFS_uint32 count;
} PthreadMutex;
/* Just in case; this is a panic value. */ /* Just in case; this is a panic value. */
#if ((!defined SIZEOF_INT) || (SIZEOF_INT <= 0)) #if ((!defined SIZEOF_INT) || (SIZEOF_INT <= 0))
# define SIZEOF_INT 4 # define SIZEOF_INT 4
@ -490,36 +497,61 @@ PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
void *__PHYSFS_platformCreateMutex(void) void *__PHYSFS_platformCreateMutex(void)
{ {
int rc; int rc;
pthread_mutex_t *m; PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
m = (pthread_mutex_t *) allocator.Malloc(sizeof (pthread_mutex_t));
BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL); BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
rc = pthread_mutex_init(m, NULL); rc = pthread_mutex_init(&m->mutex, NULL);
if (rc != 0) if (rc != 0)
{ {
allocator.Free(m); allocator.Free(m);
BAIL_MACRO(strerror(rc), NULL); BAIL_MACRO(strerror(rc), NULL);
} /* if */ } /* if */
m->count = 0;
m->owner = (pthread_t) 0xDEADBEEF;
return((void *) m); return((void *) m);
} /* __PHYSFS_platformCreateMutex */ } /* __PHYSFS_platformCreateMutex */
void __PHYSFS_platformDestroyMutex(void *mutex) void __PHYSFS_platformDestroyMutex(void *mutex)
{ {
pthread_mutex_destroy((pthread_mutex_t *) mutex); PthreadMutex *m = (PthreadMutex *) mutex;
allocator.Free(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 */ } /* __PHYSFS_platformDestroyMutex */
int __PHYSFS_platformGrabMutex(void *mutex) int __PHYSFS_platformGrabMutex(void *mutex)
{ {
return(pthread_mutex_lock((pthread_mutex_t *) mutex) == 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 */ } /* __PHYSFS_platformGrabMutex */
void __PHYSFS_platformReleaseMutex(void *mutex) void __PHYSFS_platformReleaseMutex(void *mutex)
{ {
pthread_mutex_unlock((pthread_mutex_t *) mutex); 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 */ } /* __PHYSFS_platformReleaseMutex */
#endif /* !PHYSFS_NO_PTHREADS_SUPPORT */ #endif /* !PHYSFS_NO_PTHREADS_SUPPORT */