summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2014-02-16 19:41:56 +0100
committerMarti Maria <info@littlecms.com>2014-02-16 19:41:56 +0100
commitb1ef66aafe407c8165b174aa95a55a68903fd50c (patch)
treea6ed5e3937c76d5e3efebe6637ada2619e8536df /src
parenta6fd3eb3560a064b5dc901fa7babecd01fc6085f (diff)
downloadlcms2-b1ef66aafe407c8165b174aa95a55a68903fd50c.tar.gz
Added pthread dependency, and multithreading support
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in10
-rw-r--r--src/cmserr.c90
-rw-r--r--src/cmsplugin.c18
-rw-r--r--src/lcms2_internal.h155
4 files changed, 180 insertions, 93 deletions
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 <Windows.h>
-
-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 <pthread.h>
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 <Windows.h>
+
+
+// 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 <pthread.h>
+
+#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.