From b1ef66aafe407c8165b174aa95a55a68903fd50c Mon Sep 17 00:00:00 2001 From: Marti Maria Date: Sun, 16 Feb 2014 19:41:56 +0100 Subject: Added pthread dependency, and multithreading support --- src/Makefile.in | 10 +++- src/cmserr.c | 90 ++---------------------------- src/cmsplugin.c | 18 ++++-- src/lcms2_internal.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/Makefile.in b/src/Makefile.in index 69887c2..998e409 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -58,7 +58,8 @@ host_triplet = @host@ subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -175,7 +176,7 @@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIB_JPEG = @LIB_JPEG@ LIB_MATH = @LIB_MATH@ -LIB_PTHREAD = @LIB_PTHREAD@ +LIB_THREAD = @LIB_THREAD@ LIB_TIFF = @LIB_TIFF@ LIB_ZLIB = @LIB_ZLIB@ LIPO = @LIPO@ @@ -199,6 +200,10 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -214,6 +219,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ diff --git a/src/cmserr.c b/src/cmserr.c index 8142423..29516db 100644 --- a/src/cmserr.c +++ b/src/cmserr.c @@ -532,66 +532,19 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig) //-------------------------------------------------------------------------------------------------- -#ifndef CMS_NO_PTHREADS - -#ifdef CMS_IS_WINDOWS_ - -// Windows funtions -#define WIN32_LEAN_AND_MEAN 1 -#include - -static -void* defMtxCreate(cmsContext id) -{ - cmsUNUSED_PARAMETER(id); - return (void*) CreateMutex( NULL, FALSE, NULL); -} - -static -void defMtxDestroy(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - CloseHandle((HANDLE) mtx); -} - -static -cmsBool defMtxLock(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - WaitForSingleObject((HANDLE) mtx, INFINITE); - return TRUE; -} - -static -void defMtxUnlock(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - ReleaseMutex((HANDLE) mtx); -} - -#else - -// Rest of the wide world -#include static void* defMtxCreate(cmsContext id) { - pthread_mutex_t* ptr_mutex = _cmsMalloc(id, sizeof(pthread_mutex_t)); - pthread_mutex_t init = PTHREAD_MUTEX_INITIALIZER; - - *ptr_mutex = init; - if (pthread_mutex_init(ptr_mutex, NULL) != 0) { - return NULL; - } - + _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); + _cmsInitMutexPrimitive(ptr_mutex); return (void*) ptr_mutex; } static void defMtxDestroy(cmsContext id, void* mtx) { - pthread_mutex_destroy((pthread_mutex_t *) mtx); + _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); _cmsFree(id, mtx); } @@ -599,50 +552,17 @@ static cmsBool defMtxLock(cmsContext id, void* mtx) { cmsUNUSED_PARAMETER(id); - return pthread_mutex_lock((pthread_mutex_t *) mtx) == 0; + return _cmsLockPrimitive((_cmsMutex *) mtx) == 0; } static void defMtxUnlock(cmsContext id, void* mtx) { cmsUNUSED_PARAMETER(id); - pthread_mutex_unlock((pthread_mutex_t *) mtx); -} - -#endif -#else - -// Multithreading locking is disabled -static -void* defMtxCreate(cmsContext id) -{ - return NULL; -} - -static -void defMtxDestroy(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - cmsUNUSED_PARAMETER(mtx); -} - -static -cmsBool defMtxLock(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - cmsUNUSED_PARAMETER(mtx); - - return TRUE; + _cmsUnlockPrimitive((_cmsMutex *) mtx); } -static -void defMtxUnlock(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - cmsUNUSED_PARAMETER(mtx); -} -#endif // Pointers to memory manager functions in Context0 _cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; diff --git a/src/cmsplugin.c b/src/cmsplugin.c index 89c6c08..83e8336 100644 --- a/src/cmsplugin.c +++ b/src/cmsplugin.c @@ -648,6 +648,7 @@ static struct _cmsContext_struct globalContext = { // The context pool (linked list head) +static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER; static struct _cmsContext_struct* _cmsContextPoolHead = NULL; // Internal, get associated pointer, with guessing. Never returns NULL. @@ -767,10 +768,11 @@ cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData) // Keep memory manager memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk)); - // Maintain the linked list - ctx ->Next = _cmsContextPoolHead; - _cmsContextPoolHead = ctx; - + // Maintain the linked list (with proper locking) + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + ctx ->Next = _cmsContextPoolHead; + _cmsContextPoolHead = ctx; + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); ctx ->chunks[UserPtr] = UserData; ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; @@ -828,8 +830,10 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); // Maintain the linked list - ctx ->Next = _cmsContextPoolHead; - _cmsContextPoolHead = ctx; + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + ctx ->Next = _cmsContextPoolHead; + _cmsContextPoolHead = ctx; + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); ctx ->chunks[UserPtr] = userData; ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; @@ -913,6 +917,7 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID) ctx -> MemPool = NULL; // Maintain list + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); if (_cmsContextPoolHead == ctx) { _cmsContextPoolHead = ctx->Next; @@ -930,6 +935,7 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID) } } } + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); // free the memory block itself _cmsFree(&fakeContext, ctx); diff --git a/src/lcms2_internal.h b/src/lcms2_internal.h index 31d7104..27b9352 100644 --- a/src/lcms2_internal.h +++ b/src/lcms2_internal.h @@ -164,6 +164,161 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) return _cmsQuickFloorWord(d); } + +// Pthread support -------------------------------------------------------------------- +#ifndef CMS_NO_PTHREADS + +// This is the threading support. Unfortunately, it has to be platform-dependent because +// windows does not support pthreads. + +#ifdef CMS_IS_WINDOWS_ + +#define WIN32_LEAN_AND_MEAN 1 +#include + + +// From: http://locklessinc.com/articles/pthreads_on_windows/ +// The pthreads API has an initialization macro that has no correspondence to anything in +// the windows API. By investigating the internal definition of the critical section type, +// one may work out how to initialize one without calling InitializeCriticalSection(). +// The trick here is that InitializeCriticalSection() is not allowed to fail. It tries +// to allocate a critical section debug object, but if no memory is available, it sets +// the pointer to a specific value. (One would expect that value to be NULL, but it is +// actually (void *)-1 for some reason.) Thus we can use this special value for that +// pointer, and the critical section code will work. + +// The other important part of the critical section type to initialize is the number +// of waiters. This controls whether or not the mutex is locked. Fortunately, this +// part of the critical section is unlikely to change. Apparently, many programs +// already test critical sections to see if they are locked using this value, so +// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical +// section, even when they changed the underlying algorithm to be more scalable. +// The final parts of the critical section object are unimportant, and can be set +// to zero for their defaults. This yields an initialization macro: + +typedef CRITICAL_SECTION _cmsMutex; + +#define CMS_MUTEX_INITIALIZER {((void*) (intptr_t) -1),-1,0,0,0,0} + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + EnterCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + LeaveCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + InitializeCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + DeleteCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + EnterCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + LeaveCriticalSection(m); + return 0; +} + +#else + +// Rest of the wide world +#include + +#define CMS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t _cmsMutex; + + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + return pthread_mutex_lock(m); +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + return pthread_mutex_unlock(m); +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + return pthread_mutex_init(m, NULL); +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + return pthread_mutex_destroy(m); +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + return pthread_mutex_lock(m); +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + return pthread_mutex_unlock(m); +} + +#endif +#else + +#define CMS_MUTEX_INITIALIZER 0 +typedef int _cmsMutex; + + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} +#endif + // Plug-In registration --------------------------------------------------------------- // Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once. -- cgit v1.2.1