add support for recursive mutex on windows; ensure h_mgr uses them (pthread doesnt guarantee default type is recursive)

This was SVN commit r10247.
This commit is contained in:
janwas 2011-09-10 22:51:51 +00:00
parent 579f1acb6f
commit 80df13f47b
3 changed files with 54 additions and 13 deletions

View File

@ -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))

View File

@ -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)

View File

@ -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*);