From 39406cbacc6de66e879ad789a7a0f2243a82cc3e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 30 Mar 2002 16:44:09 +0000 Subject: [PATCH] First shot at thread-safety. --- physfs.c | 254 ++++++++++++++++++++++++++++++++-------------- physfs_internal.h | 40 ++++++++ platform/unix.c | 35 +++++++ 3 files changed, 255 insertions(+), 74 deletions(-) diff --git a/physfs.c b/physfs.c index 6f655e9..75aa158 100644 --- a/physfs.c +++ b/physfs.c @@ -85,7 +85,6 @@ static const DirFunctions *dirFunctions[] = /* General PhysicsFS state ... */ - static int initialized = 0; static ErrMsg *errorMessages = NULL; static DirInfo *searchPath = NULL; @@ -96,6 +95,9 @@ static char *baseDir = NULL; static char *userDir = NULL; static int allowSymLinks = 0; +/* mutexes ... */ +static void *errorLock = NULL; /* protects error message list. */ +static void *stateLock = NULL; /* protects other PhysFS static state. */ /* functions ... */ @@ -105,6 +107,7 @@ static ErrMsg *findErrorForCurrentThread(void) ErrMsg *i; int tid; + __PHYSFS_platformGrabMutex(errorLock); if (errorMessages != NULL) { tid = __PHYSFS_platformGetThreadID(); @@ -112,9 +115,13 @@ static ErrMsg *findErrorForCurrentThread(void) for (i = errorMessages; i != NULL; i = i->next) { if (i->tid == tid) + { + __PHYSFS_platformReleaseMutex(errorLock); return(i); + } /* if */ } /* for */ } /* if */ + __PHYSFS_platformReleaseMutex(errorLock); return(NULL); /* no error available. */ } /* findErrorForCurrentThread */ @@ -137,8 +144,11 @@ void __PHYSFS_setError(const char *str) memset((void *) err, '\0', sizeof (ErrMsg)); err->tid = __PHYSFS_platformGetThreadID(); + + __PHYSFS_platformGrabMutex(errorLock); err->next = errorMessages; errorMessages = err; + __PHYSFS_platformReleaseMutex(errorLock); } /* if */ err->errorAvailable = 1; @@ -147,19 +157,6 @@ void __PHYSFS_setError(const char *str) } /* __PHYSFS_setError */ -static void freeErrorMessages(void) -{ - ErrMsg *i; - ErrMsg *next; - - for (i = errorMessages; i != NULL; i = next) - { - next = i->next; - free(i); - } /* for */ -} /* freeErrorMessages */ - - const char *PHYSFS_getLastError(void) { ErrMsg *err = findErrorForCurrentThread(); @@ -172,6 +169,20 @@ const char *PHYSFS_getLastError(void) } /* PHYSFS_getLastError */ +/* MAKE SURE that errorLock is held before calling this! */ +static void freeErrorMessages(void) +{ + ErrMsg *i; + ErrMsg *next; + + for (i = errorMessages; i != NULL; i = next) + { + next = i->next; + free(i); + } /* for */ +} /* freeErrorMessages */ + + void PHYSFS_getLinkedVersion(PHYSFS_Version *ver) { if (ver != NULL) @@ -212,16 +223,17 @@ static DirInfo *buildDirInfo(const char *newDir, int forWriting) di = (DirInfo *) malloc(sizeof (DirInfo)); if (di == NULL) + { dirHandle->funcs->dirClose(dirHandle); - BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0); + BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0); + } /* if */ di->dirName = (char *) malloc(strlen(newDir) + 1); if (di->dirName == NULL) { free(di); dirHandle->funcs->dirClose(dirHandle); - __PHYSFS_setError(ERR_OUT_OF_MEMORY); - return(0); + BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); } /* if */ di->next = NULL; @@ -231,6 +243,7 @@ static DirInfo *buildDirInfo(const char *newDir, int forWriting) } /* buildDirInfo */ +/* MAKE SURE you've got the stateLock held before calling this! */ static int freeDirInfo(DirInfo *di, FileHandleList *openList) { FileHandleList *i; @@ -243,7 +256,7 @@ static int freeDirInfo(DirInfo *di, FileHandleList *openList) const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle; BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0); } /* for */ - + di->dirHandle->funcs->dirClose(di->dirHandle); free(di->dirName); free(di); @@ -356,6 +369,30 @@ static char *calculateBaseDir(const char *argv0) } /* calculateBaseDir */ +static int initializeMutexes(void) +{ + errorLock = __PHYSFS_platformCreateMutex(); + if (errorLock == NULL) + goto initializeMutexes_failed; + + stateLock = __PHYSFS_platformCreateMutex(); + if (stateLock == NULL) + goto initializeMutexes_failed; + + return(1); /* success. */ + +initializeMutexes_failed: + if (errorLock != NULL) + __PHYSFS_platformDestroyMutex(errorLock); + + if (stateLock != NULL) + __PHYSFS_platformDestroyMutex(stateLock); + + errorLock = stateLock = NULL; + return(0); /* failed. */ +} /* initializeMutexes */ + + int PHYSFS_init(const char *argv0) { char *ptr; @@ -364,6 +401,8 @@ int PHYSFS_init(const char *argv0) BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0); BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0); + BAIL_IF_MACRO(!initializeMutexes(), NULL, 0); + baseDir = calculateBaseDir(argv0); BAIL_IF_MACRO(baseDir == NULL, NULL, 0); ptr = __PHYSFS_platformRealPath(baseDir); @@ -393,6 +432,7 @@ int PHYSFS_init(const char *argv0) } /* PHYSFS_init */ +/* MAKE SURE you hold stateLock before calling this! */ static int closeFileHandleList(FileHandleList **list) { FileHandleList *i; @@ -417,6 +457,7 @@ static int closeFileHandleList(FileHandleList **list) } /* closeFileHandleList */ +/* MAKE SURE you hold the stateLock before calling this! */ static void freeSearchPath(void) { DirInfo *i; @@ -461,6 +502,11 @@ int PHYSFS_deinit(void) allowSymLinks = 0; initialized = 0; + + __PHYSFS_platformDestroyMutex(errorLock); + __PHYSFS_platformDestroyMutex(stateLock); + + errorLock = stateLock = NULL; return(1); } /* PHYSFS_deinit */ @@ -507,49 +553,59 @@ const char *PHYSFS_getUserDir(void) const char *PHYSFS_getWriteDir(void) { - if (writeDir == NULL) - return(NULL); + const char *retval = NULL; - return(writeDir->dirName); + __PHYSFS_platformGrabMutex(stateLock); + if (writeDir != NULL) + retval = writeDir->dirName; + __PHYSFS_platformReleaseMutex(stateLock); + + return(retval); } /* PHYSFS_getWriteDir */ int PHYSFS_setWriteDir(const char *newDir) { + int retval = 1; + + __PHYSFS_platformGrabMutex(stateLock); + if (writeDir != NULL) { - BAIL_IF_MACRO(!freeDirInfo(writeDir, openWriteList), NULL, 0); + BAIL_IF_MACRO_MUTEX(!freeDirInfo(writeDir, openWriteList), NULL, + stateLock, 0); writeDir = NULL; } /* if */ if (newDir != NULL) { writeDir = buildDirInfo(newDir, 1); - return(writeDir != NULL); + retval = (writeDir != NULL); } /* if */ - return(1); + __PHYSFS_platformReleaseMutex(stateLock); + + return(retval); } /* PHYSFS_setWriteDir */ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath) { DirInfo *di; - DirInfo *i = searchPath; DirInfo *prev = NULL; + DirInfo *i; - while (i != NULL) + __PHYSFS_platformGrabMutex(stateLock); + + for (i = searchPath; i != NULL; i = i->next) { - if (strcmp(newDir, i->dirName) == 0) /* already in search path. */ - return(1); - + /* already in search path? */ + BAIL_IF_MACRO_MUTEX(strcmp(newDir, i->dirName)==0, NULL, stateLock, 1); prev = i; - i = i->next; - } /* while */ + } /* for */ di = buildDirInfo(newDir, 0); - - BAIL_IF_MACRO(di == NULL, NULL, 0); + BAIL_IF_MACRO_MUTEX(di == NULL, NULL, stateLock, 0); if (appendToPath) { @@ -565,6 +621,7 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath) searchPath = di; } /* else */ + __PHYSFS_platformReleaseMutex(stateLock); return(1); } /* PHYSFS_addToSearchPath */ @@ -577,25 +634,26 @@ int PHYSFS_removeFromSearchPath(const char *oldDir) BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0); + __PHYSFS_platformGrabMutex(stateLock); for (i = searchPath; i != NULL; i = i->next) { if (strcmp(i->dirName, oldDir) == 0) { next = i->next; - BAIL_IF_MACRO(!freeDirInfo(i, openReadList), NULL, 0); + BAIL_IF_MACRO_MUTEX(!freeDirInfo(i, openReadList), NULL, + stateLock, 0); if (prev == NULL) searchPath = next; else prev->next = next; - return(1); + BAIL_MACRO_MUTEX(NULL, stateLock, 1); } /* if */ prev = i; } /* for */ - __PHYSFS_setError(ERR_NOT_IN_SEARCH_PATH); - return(0); + BAIL_MACRO_MUTEX(ERR_NOT_IN_SEARCH_PATH, stateLock, 0); } /* PHYSFS_removeFromSearchPath */ @@ -606,11 +664,13 @@ char **PHYSFS_getSearchPath(void) DirInfo *i; char **retval; + __PHYSFS_platformGrabMutex(stateLock); + for (i = searchPath; i != NULL; i = i->next) count++; retval = (char **) malloc(sizeof (char *) * count); - BAIL_IF_MACRO(!retval, ERR_OUT_OF_MEMORY, NULL); + BAIL_IF_MACRO_MUTEX(!retval, ERR_OUT_OF_MEMORY, stateLock, NULL); count--; retval[count] = NULL; @@ -626,13 +686,13 @@ char **PHYSFS_getSearchPath(void) } /* while */ free(retval); - __PHYSFS_setError(ERR_OUT_OF_MEMORY); - return(NULL); + BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL); } /* if */ strcpy(retval[x], i->dirName); } /* for */ + __PHYSFS_platformReleaseMutex(stateLock); return(retval); } /* PHYSFS_getSearchPath */ @@ -646,6 +706,8 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName, const char *dirsep = PHYSFS_getDirSeparator(); char *str; + BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); + /* set write dir... */ str = malloc(strlen(userdir) + (strlen(organization) * 2) + (strlen(appName) * 2) + (strlen(dirsep) * 3) + 2); @@ -740,7 +802,7 @@ char * __PHYSFS_convertToDependent(const char *prepend, const char *dirName, const char *append) { - const char *dirsep = PHYSFS_getDirSeparator(); + const char *dirsep = __PHYSFS_platformDirSeparator; size_t sepsize = strlen(dirsep); char *str; char *i1; @@ -852,7 +914,7 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname) } /* __PHYSFS_verifySecurity */ -int PHYSFS_mkdir(const char *dirName) +int PHYSFS_mkdir(const char *dname) { DirHandle *h; char *str; @@ -860,19 +922,18 @@ int PHYSFS_mkdir(const char *dirName) char *end; int retval = 0; - BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0); + BAIL_IF_MACRO(dname == NULL, ERR_INVALID_ARGUMENT, 0); + while (*dname == '/') + dname++; + __PHYSFS_platformGrabMutex(stateLock); + BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0); h = writeDir->dirHandle; - - while (*dirName == '/') - dirName++; - - BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0); - BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0); - - start = str = malloc(strlen(dirName) + 1); - BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0); - strcpy(str, dirName); + BAIL_IF_MACRO_MUTEX(!h->funcs->mkdir, ERR_NOT_SUPPORTED, stateLock, 0); + BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, dname), NULL, stateLock, 0); + start = str = malloc(strlen(dname) + 1); + BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0); + strcpy(str, dname); while (1) { @@ -891,6 +952,8 @@ int PHYSFS_mkdir(const char *dirName) start = end + 1; } /* while */ + __PHYSFS_platformReleaseMutex(stateLock); + free(str); return(retval); } /* PHYSFS_mkdir */ @@ -898,16 +961,23 @@ int PHYSFS_mkdir(const char *dirName) int PHYSFS_delete(const char *fname) { + int retval; DirHandle *h; - BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0); - h = writeDir->dirHandle; - BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0); + BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0); while (*fname == '/') fname++; - BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0); - return(h->funcs->remove(h, fname)); + __PHYSFS_platformGrabMutex(stateLock); + + BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0); + h = writeDir->dirHandle; + BAIL_IF_MACRO_MUTEX(!h->funcs->remove, ERR_NOT_SUPPORTED, stateLock, 0); + BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL, stateLock, 0); + retval = h->funcs->remove(h, fname); + + __PHYSFS_platformReleaseMutex(stateLock); + return(retval); } /* PHYSFS_delete */ @@ -918,15 +988,20 @@ const char *PHYSFS_getRealDir(const char *filename) while (*filename == '/') filename++; + __PHYSFS_platformGrabMutex(stateLock); for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; if (__PHYSFS_verifySecurity(h, filename)) { if (h->funcs->exists(h, filename)) + { + __PHYSFS_platformReleaseMutex(stateLock); return(i->dirName); + } /* if */ } /* if */ } /* for */ + __PHYSFS_platformReleaseMutex(stateLock); return(NULL); } /* PHYSFS_getRealDir */ @@ -1029,9 +1104,11 @@ char **PHYSFS_enumerateFiles(const char *path) LinkedStringList *finalList = NULL; int omitSymLinks = !allowSymLinks; + BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL); while (*path == '/') path++; + __PHYSFS_platformGrabMutex(stateLock); for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; @@ -1041,6 +1118,7 @@ char **PHYSFS_enumerateFiles(const char *path) interpolateStringLists(&finalList, rc); } /* if */ } /* for */ + __PHYSFS_platformReleaseMutex(stateLock); retval = convertStringListToPhysFSList(finalList); return(retval); @@ -1049,6 +1127,7 @@ char **PHYSFS_enumerateFiles(const char *path) int PHYSFS_exists(const char *fname) { + BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0); while (*fname == '/') fname++; @@ -1060,21 +1139,28 @@ int PHYSFS_isDirectory(const char *fname) { DirInfo *i; + BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0); while (*fname == '/') fname++; if (*fname == '\0') return(1); + __PHYSFS_platformGrabMutex(stateLock); for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; if (__PHYSFS_verifySecurity(h, fname)) { if (h->funcs->exists(h, fname)) - return(h->funcs->isDirectory(h, fname)); + { + int retval = h->funcs->isDirectory(h, fname); + __PHYSFS_platformReleaseMutex(stateLock); + return(retval); + } /* if */ } /* if */ } /* for */ + __PHYSFS_platformReleaseMutex(stateLock); return(0); } /* PHYSFS_isDirectory */ @@ -1087,19 +1173,28 @@ int PHYSFS_isSymbolicLink(const char *fname) if (!allowSymLinks) return(0); + BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0); while (*fname == '/') fname++; + __PHYSFS_platformGrabMutex(stateLock); for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; if (__PHYSFS_verifySecurity(h, fname)) { if (h->funcs->exists(h, fname)) - return(h->funcs->isSymLink(h, fname)); + { + int retval = h->funcs->isSymLink(h, fname); + __PHYSFS_platformReleaseMutex(stateLock); + return(retval); + } /* if */ } /* if */ } /* for */ +/* !!! FIXME: setError ERR_FILE_NOT_FOUND? */ + __PHYSFS_platformReleaseMutex(stateLock); + return(0); } /* PHYSFS_isSymbolicLink */ @@ -1108,19 +1203,24 @@ static PHYSFS_file *doOpenWrite(const char *fname, int appending) { PHYSFS_file *retval = NULL; FileHandle *rc = NULL; - DirHandle *h = (writeDir == NULL) ? NULL : writeDir->dirHandle; - const DirFunctions *f = (h == NULL) ? NULL : h->funcs; + DirHandle *h; + const DirFunctions *f; FileHandleList *list; + BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL); while (*fname == '/') fname++; - BAIL_IF_MACRO(!h, ERR_NO_WRITE_DIR, NULL); - BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, NULL); + __PHYSFS_platformGrabMutex(stateLock); + h = (writeDir == NULL) ? NULL : writeDir->dirHandle; + BAIL_IF_MACRO_MUTEX(!h, ERR_NO_WRITE_DIR, stateLock, NULL); + BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL, + stateLock, NULL); list = (FileHandleList *) malloc(sizeof (FileHandleList)); - BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL); + BAIL_IF_MACRO_MUTEX(!list, ERR_OUT_OF_MEMORY, stateLock, NULL); + f = h->funcs; rc = (appending) ? f->openAppend(h, fname) : f->openWrite(h, fname); if (rc == NULL) free(list); @@ -1132,6 +1232,7 @@ static PHYSFS_file *doOpenWrite(const char *fname, int appending) retval = &(list->handle); } /* else */ + __PHYSFS_platformReleaseMutex(stateLock); return(retval); } /* doOpenWrite */ @@ -1150,13 +1251,16 @@ PHYSFS_file *PHYSFS_openAppend(const char *filename) PHYSFS_file *PHYSFS_openRead(const char *fname) { + PHYSFS_file *retval; FileHandle *rc = NULL; FileHandleList *list; DirInfo *i; + BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL); while (*fname == '/') fname++; + __PHYSFS_platformGrabMutex(stateLock); for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; @@ -1168,16 +1272,17 @@ PHYSFS_file *PHYSFS_openRead(const char *fname) } /* if */ } /* for */ - if (rc == NULL) - return(NULL); + BAIL_IF_MACRO_MUTEX(rc == NULL, NULL, stateLock, NULL); list = (FileHandleList *) malloc(sizeof (FileHandleList)); BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL); list->handle.opaque = (void *) rc; list->next = openReadList; openReadList = list; + retval = &(list->handle); - return(&(list->handle)); + __PHYSFS_platformReleaseMutex(stateLock); + return(retval); } /* PHYSFS_openRead */ @@ -1215,19 +1320,20 @@ int PHYSFS_close(PHYSFS_file *handle) { int rc; + __PHYSFS_platformGrabMutex(stateLock); + /* -1 == close failure. 0 == not found. 1 == success. */ rc = closeHandleInOpenList(&openReadList, handle); - BAIL_IF_MACRO(rc == -1, NULL, 0); + BAIL_IF_MACRO_MUTEX(rc == -1, NULL, stateLock, 0); if (!rc) { rc = closeHandleInOpenList(&openWriteList, handle); - BAIL_IF_MACRO(rc == -1, NULL, 0); + BAIL_IF_MACRO_MUTEX(rc == -1, NULL, stateLock, 0); } /* if */ - if (!rc) - __PHYSFS_setError(ERR_NOT_A_HANDLE); - - return(rc); + __PHYSFS_platformReleaseMutex(stateLock); + BAIL_IF_MACRO(!rc, ERR_NOT_A_HANDLE, 0); + return(1); } /* PHYSFS_close */ diff --git a/physfs_internal.h b/physfs_internal.h index 335e5af..c62852d 100644 --- a/physfs_internal.h +++ b/physfs_internal.h @@ -304,6 +304,8 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname); /* These get used all over for lessening code clutter. */ #define BAIL_MACRO(e, r) { __PHYSFS_setError(e); return r; } #define BAIL_IF_MACRO(c, e, r) if (c) { __PHYSFS_setError(e); return r; } +#define BAIL_MACRO_MUTEX(e, m, r) { __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; } +#define BAIL_IF_MACRO_MUTEX(c, e, m, r) if (c) { __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; } @@ -633,6 +635,44 @@ int __PHYSFS_platformMkDir(const char *path); int __PHYSFS_platformDelete(const char *path); +/* + * Create a platform-specific mutex. This can be whatever datatype your + * platform uses for mutexes, but it is cast to a (void *) for abstractness. + * + * Return (NULL) if you couldn't create one. Systems without threads can + * return any arbitrary non-NULL value. + */ +void *__PHYSFS_platformCreateMutex(void); + +/* + * Destroy a platform-specific mutex, and clean up any resources associated + * with it. (mutex) is a value previously returned by + * __PHYSFS_platformCreateMutex(). This can be a no-op on single-threaded + * platforms. + */ +void __PHYSFS_platformDestroyMutex(void *mutex); + +/* + * Grab possession of a platform-specific mutex. Mutexes should be recursive; + * that is, the same thread should be able to call this function multiple + * times in a row without causing a deadlock. This function should block + * until a thread can gain possession of the mutex. + * + * Return non-zero if the mutex was grabbed, zero if there was an + * unrecoverable problem grabbing it (this should not be a matter of + * timing out! We're talking major system errors; block until the mutex + * is available otherwise.) + */ +int __PHYSFS_platformGrabMutex(void *mutex); + +/* + * Relinquish possession of the mutex when this method has been called + * once for each time that platformGrabMutex was called. Once possession has + * been released, the next thread in line to grab the mutex (if any) may + * proceed. + */ +void __PHYSFS_platformReleaseMutex(void *mutex); + #ifdef __cplusplus } #endif diff --git a/platform/unix.c b/platform/unix.c index 3980b1d..e61c393 100644 --- a/platform/unix.c +++ b/platform/unix.c @@ -660,5 +660,40 @@ int __PHYSFS_platformDelete(const char *path) return(1); } /* __PHYSFS_platformDelete */ + +void *__PHYSFS_platformCreateMutex(void) +{ + int rc; + pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t)); + BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL); + rc = pthread_mutex_init(m, NULL); + if (rc != 0) + { + free(m); + BAIL_MACRO(strerror(rc), NULL); + } /* if */ + + return((void *) m); +} /* __PHYSFS_platformCreateMutex */ + + +void __PHYSFS_platformDestroyMutex(void *mutex) +{ + pthread_mutex_destroy((pthread_mutex_t *) mutex); + free(mutex); +} /* __PHYSFS_platformDestroyMutex */ + + +int __PHYSFS_platformGrabMutex(void *mutex) +{ + return(pthread_mutex_lock((pthread_mutex_t *) mutex) == 0); +} /* __PHYSFS_platformGrabMutex */ + + +void __PHYSFS_platformReleaseMutex(void *mutex) +{ + pthread_mutex_unlock((pthread_mutex_t *) mutex); +} /* __PHYSFS_platformReleaseMutex */ + /* end of unix.c ... */