From 80df13f47baf175521719bc8715ec01a8345f179 Mon Sep 17 00:00:00 2001 From: janwas Date: Sat, 10 Sep 2011 22:51:51 +0000 Subject: [PATCH] add support for recursive mutex on windows; ensure h_mgr uses them (pthread doesnt guarantee default type is recursive) This was SVN commit r10247. --- source/lib/res/h_mgr.cpp | 32 ++++++++++++++------ source/lib/sysdep/os/win/wposix/wpthread.cpp | 23 ++++++++++++++ source/lib/sysdep/os/win/wposix/wpthread.h | 12 ++++++-- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/source/lib/res/h_mgr.cpp b/source/lib/res/h_mgr.cpp index 3c655ee753..61314d6da4 100644 --- a/source/lib/res/h_mgr.cpp +++ b/source/lib/res/h_mgr.cpp @@ -503,22 +503,22 @@ fail: } -static pthread_mutex_t h_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t h_mutex; // (the same class is defined in vfs.cpp, but it is easier to // just duplicate it to avoid having to specify the mutex. // such a class exists in ps/ThreadUtil.h, but we can't // take a dependency on that module here.) -struct ScopedLock +struct H_ScopedLock { - ScopedLock() { pthread_mutex_lock(&h_mutex); } - ~ScopedLock() { pthread_mutex_unlock(&h_mutex); } + H_ScopedLock() { pthread_mutex_lock(&h_mutex); } + ~H_ScopedLock() { pthread_mutex_unlock(&h_mutex); } }; // any further params are passed to type's init routine Handle h_alloc(H_Type type, const PIVFS& vfs, const VfsPath& pathname, size_t flags, ...) { - ScopedLock s; + H_ScopedLock s; RETURN_STATUS_IF_ERR(type_validate(type)); @@ -582,7 +582,7 @@ static void h_free_hd(HDATA* hd) Status h_free(Handle& h, H_Type type) { - ScopedLock s; + H_ScopedLock s; // 0-initialized or an error code; don't complain because this // happens often and is harmless. @@ -636,7 +636,7 @@ VfsPath h_filename(const Handle h) // TODO: what if iterating through all handles is too slow? Status h_reload(const PIVFS& vfs, const VfsPath& pathname) { - ScopedLock s; + H_ScopedLock s; const u32 key = fnv_hash(pathname.string().c_str(), pathname.string().length()*sizeof(pathname.string()[0])); @@ -678,7 +678,7 @@ Status h_reload(const PIVFS& vfs, const VfsPath& pathname) Handle h_find(H_Type type, uintptr_t key) { - ScopedLock s; + H_ScopedLock s; return key_find(key, type); } @@ -692,7 +692,7 @@ Handle h_find(H_Type type, uintptr_t key) // at that point, all (cached) OpenAL resources must be freed. Status h_force_free(Handle h, H_Type type) { - ScopedLock s; + H_ScopedLock s; // require valid index; ignore tag; type checked below. HDATA* hd; @@ -743,6 +743,18 @@ static ModuleInitState initState; static Status Init() { + // lock must be recursive (e.g. h_alloc calls h_find) + pthread_mutexattr_t attr; + int err; + err = pthread_mutexattr_init(&attr); + ENSURE(err == 0); + err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + ENSURE(err == 0); + err = pthread_mutex_init(&h_mutex, &attr); + ENSURE(err == 0); + err = pthread_mutexattr_destroy(&attr); + ENSURE(err == 0); + RETURN_STATUS_IF_ERR(pool_create(&hpool, hdata_cap*sizeof(HDATA), sizeof(HDATA))); return INFO::OK; } @@ -755,7 +767,7 @@ static void Shutdown() // raise a double-free warning unless we ignore it. (#860, #915, #920) ignoreDoubleFree = true; - ScopedLock s; + H_ScopedLock s; // forcibly close all open handles for(HDATA* hd = (HDATA*)hpool.da.base; hd < (HDATA*)(hpool.da.base + hpool.da.pos); hd = (HDATA*)(uintptr_t(hd)+hpool.el_size)) diff --git a/source/lib/sysdep/os/win/wposix/wpthread.cpp b/source/lib/sysdep/os/win/wposix/wpthread.cpp index 2ce7c5a981..83742d5e61 100644 --- a/source/lib/sysdep/os/win/wposix/wpthread.cpp +++ b/source/lib/sysdep/os/win/wposix/wpthread.cpp @@ -255,6 +255,29 @@ again: // note: we use wutil_Allocate instead of new because the (no longer extant) // memory manager used a pthread_mutex. + +int pthread_mutexattr_init(pthread_mutexattr_t* UNUSED(attr)) +{ + return 0; +} + +int pthread_mutexattr_destroy(pthread_mutexattr_t* UNUSED(attr)) +{ + return 0; +} + +int pthread_mutexattr_gettype(const pthread_mutexattr_t* UNUSED(attr), int* type) +{ + *type = PTHREAD_MUTEX_RECURSIVE; + return 0; +} + +int pthread_mutexattr_settype(pthread_mutexattr_t* UNUSED(attr), int type) +{ + return (type == PTHREAD_MUTEX_RECURSIVE)? 0 : -ENOSYS; +} + + static CRITICAL_SECTION* CRITICAL_SECTION_from_pthread_mutex_t(pthread_mutex_t* m) { if(!m) diff --git a/source/lib/sysdep/os/win/wposix/wpthread.h b/source/lib/sysdep/os/win/wposix/wpthread.h index 69366aee88..3f2b1bb0a3 100644 --- a/source/lib/sysdep/os/win/wposix/wpthread.h +++ b/source/lib/sysdep/os/win/wposix/wpthread.h @@ -71,11 +71,17 @@ LIB_API int pthread_cancel(pthread_t thread); LIB_API int pthread_join(pthread_t thread, void** value_ptr); // mutex -typedef void* pthread_mutex_t; // pointer to critical section -typedef void pthread_mutexattr_t; -#define PTHREAD_MUTEX_INITIALIZER pthread_mutex_initializer() +typedef void* pthread_mutexattr_t; +LIB_API int pthread_mutexattr_init(pthread_mutexattr_t* attr); +LIB_API int pthread_mutexattr_destroy(pthread_mutexattr_t* attr); +enum { PTHREAD_MUTEX_RECURSIVE }; // the only one we support +LIB_API int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr, int* type); +LIB_API int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type); + +typedef void* pthread_mutex_t; // pointer to critical section LIB_API pthread_mutex_t pthread_mutex_initializer(); +#define PTHREAD_MUTEX_INITIALIZER pthread_mutex_initializer() LIB_API int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*); LIB_API int pthread_mutex_destroy(pthread_mutex_t*); LIB_API int pthread_mutex_lock(pthread_mutex_t*);