diff --git a/configure.in b/configure.in index c93a450f..89c87304 100644 --- a/configure.in +++ b/configure.in @@ -291,6 +291,29 @@ esac AC_MSG_RESULT([$want_inline]) AC_SUBST(INLINE_FLAGS) +# Check for atomic integer operations +ATOMIC_OPS="" +AC_ARG_ENABLE(atomics,AC_HELP_STRING([--enable-atomics],[Enable atomic integer operations (default: yes)]),want_atomics=$enableval,want_atomics=yes) +if [[ "x$want_atomics" != "xno" ]]; then +AC_MSG_CHECKING([whether to use atomic integer operations]) +AC_LANG_SAVE +AC_LANG_C +SAVE_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Wall -Werror" +AC_TRY_LINK([],[ +int i = 0; +int j = __sync_add_and_fetch(&i,1); +return __sync_fetch_and_sub(&j,1); +], +ATOMIC_OPS="-DATOMIC_OPS", +want_atomics="no (missing -march ?)" +) +CFLAGS="$SAVE_CFLAGS" +AC_LANG_RESTORE +AC_MSG_RESULT([$want_atomics]) +fi +AC_SUBST(ATOMIC_OPS) + FDSIZE_HACK="" AC_ARG_WITH(fdsize,AC_HELP_STRING([--with-fdsize=NNNN],[set FD_SIZE to NNNN (default 8192)]),[ac_cv_use_fdsize=$withval],[ac_cv_use_fdsize=8192]) if [[ "x$ac_cv_use_fdsize" != "xno" ]]; then diff --git a/engine/Makefile.in b/engine/Makefile.in index e448a234..27939f6c 100644 --- a/engine/Makefile.in +++ b/engine/Makefile.in @@ -100,6 +100,9 @@ Mutex.o: @srcdir@/Mutex.cpp $(MKDEPS) $(CINC) Thread.o: @srcdir@/Thread.cpp $(MKDEPS) $(CINC) $(COMPILE) @THREAD_KILL@ @HAVE_PRCTL@ -c $< +TelEngine.o: @srcdir@/TelEngine.cpp $(MKDEPS) $(CINC) + $(COMPILE) @ATOMIC_OPS@ -c $< + Client.o: @srcdir@/Client.cpp $(MKDEPS) $(CLINC) $(COMPILE) -c $< diff --git a/engine/TelEngine.cpp b/engine/TelEngine.cpp index 449d2d1a..e3d275d9 100644 --- a/engine/TelEngine.cpp +++ b/engine/TelEngine.cpp @@ -627,12 +627,16 @@ void GenObject::destruct() } +#ifndef ATOMIC_OPS static MutexPool s_refMutex(REFOBJECT_MUTEX_COUNT,false,"RefObject"); +#endif RefObject::RefObject() : m_refcount(1), m_mutex(0) { +#ifndef ATOMIC_OPS m_mutex = s_refMutex.mutex(this); +#endif } RefObject::~RefObject() @@ -653,21 +657,45 @@ void RefObject::destruct() bool RefObject::ref() { +#ifdef ATOMIC_OPS +#ifdef _WINDOWS + if (InterlockedIncrement((LONG*)&m_refcount) > 1) + return true; + InterlockedDecrement((LONG*)&m_refcount); +#else + if (__sync_add_and_fetch(&m_refcount,1) > 1) + return true; + __sync_sub_and_fetch(&m_refcount,1); +#endif +#else Lock lock(m_mutex); if (m_refcount > 0) { ++m_refcount; return true; } +#endif return false; } bool RefObject::deref() { +#ifdef ATOMIC_OPS +#ifdef _WINDOWS + int i = InterlockedDecrement((LONG*)&m_refcount) + 1; + if (i <= 0) + InterlockedIncrement((LONG*)&m_refcount); +#else + int i = __sync_fetch_and_sub(&m_refcount,1); + if (i <= 0) + __sync_fetch_and_add(&m_refcount,1); +#endif +#else m_mutex->lock(); int i = m_refcount; if (i > 0) --m_refcount; m_mutex->unlock(); +#endif if (i == 1) zeroRefs(); else if (i <= 0) @@ -683,18 +711,40 @@ void RefObject::zeroRefs() bool RefObject::resurrect() { +#ifdef ATOMIC_OPS +#ifdef _WINDOWS + if (InterlockedIncrement((LONG*)&m_refcount) == 1) + return true; + InterlockedDecrement((LONG*)&m_refcount); + return false; +#else + if (__sync_add_and_fetch(&m_refcount,1) == 1) + return true; + __sync_sub_and_fetch(&m_refcount,1); + return false; +#endif +#else m_mutex->lock(); bool ret = (0 == m_refcount); if (ret) m_refcount = 1; m_mutex->unlock(); return ret; +#endif } void RefObject::destroyed() { } +bool RefObject::efficientIncDec() +{ +#ifdef ATOMIC_OPS + return true; +#else + return false; +#endif +} void RefPointerBase::assign(RefObject* oldptr, RefObject* newptr, void* pointer) { diff --git a/windows/Libyate.vcproj b/windows/Libyate.vcproj index 2b5cf830..846eb551 100644 --- a/windows/Libyate.vcproj +++ b/windows/Libyate.vcproj @@ -49,7 +49,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".,..,..\engine\regex,..\engine\tables" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBYATE_EXPORTS;__STDC__;_CRT_SECURE_NO_DEPRECATE;HAVE_DNS_NAPTR_DATA" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBYATE_EXPORTS;__STDC__;_CRT_SECURE_NO_DEPRECATE;ATOMIC_OPS;HAVE_DNS_NAPTR_DATA" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -147,7 +147,7 @@ Optimization="2" InlineFunctionExpansion="1" AdditionalIncludeDirectories=".,..,..\engine\regex,..\engine\tables" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBYATE_EXPORTS;__STDC__;_CRT_SECURE_NO_DEPRECATE;HAVE_DNS_NAPTR_DATA" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBYATE_EXPORTS;__STDC__;_CRT_SECURE_NO_DEPRECATE;ATOMIC_OPS;HAVE_DNS_NAPTR_DATA" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" diff --git a/yateclass.h b/yateclass.h index 76be3607..bb5e3b4f 100644 --- a/yateclass.h +++ b/yateclass.h @@ -812,6 +812,13 @@ public: */ virtual void destruct(); + /** + * Check if reference counter manipulations are efficient on this platform. + * If platform does not support atomic operations a mutex pool is used. + * @return True if refcount uses atomic integer operations + */ + static bool efficientIncDec(); + protected: /** * This method is called when the reference count reaches zero after