From: Alex Rousskov Date: Wed, 25 May 2011 03:14:15 +0000 (-0600) Subject: Detect support for __sync_add_and_fetch() and friends, X-Git-Tag: take07~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=65b81b2712ba00ea3b47ecd0d4b730a63681550f;p=thirdparty%2Fsquid.git Detect support for __sync_add_and_fetch() and friends, setting HAVE_ATOMIC_OPS accordingly. Disable shared memory caching by default if atomic operations are not supported. Prohibit shared memory caching if atomic operations are not supported. Needs more testing. --- diff --git a/configure.ac b/configure.ac index f3abae3362..66cda2ed54 100644 --- a/configure.ac +++ b/configure.ac @@ -361,6 +361,28 @@ SQUID_DEFINE_BOOL(_USE_INLINE_,$enable_inline, # to be used by sub-commands export enable_inline +dnl +dnl Check for atomic operations support in the compiler +dnl +AC_MSG_CHECKING([for atomic operations support]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + int n = 0; +]],[[ + __sync_add_and_fetch(&n, 1); // n becomes 1 + __sync_fetch_and_add(&n, 1); // n becomes 2 + __sync_bool_compare_and_swap(&n, 2, 201); // n becomes 201 + __sync_fetch_and_and(&n, 200); // n becomes 200 + return (n == 200) ? 0 : -1; +]])], +[ + AC_DEFINE(HAVE_ATOMIC_OPS,1, + [Define to 1 if you have __sync_add_and_fetch() and such]) + AC_MSG_RESULT(yes) +],[ + AC_MSG_RESULT(no) +]) + + AC_ARG_ENABLE(debug-cbdata, AS_HELP_STRING([--enable-debug-cbdata], [Provide some debug information in cbdata]), [ diff --git a/src/MemStore.cc b/src/MemStore.cc index 7944840bdd..5496c089f0 100644 --- a/src/MemStore.cc +++ b/src/MemStore.cc @@ -361,7 +361,12 @@ void MemStoreRr::run(const RunnerRegistry &) { // decide whether to use a shared memory cache if the user did not specify if (!Config.memShared.configured()) { - Config.memShared.configure(UsingSmp() && Config.memMaxSize > 0); + Config.memShared.configure(AtomicOperationsSupported && + UsingSmp() && Config.memMaxSize > 0); + } else + if (Config.memShared && !AtomicOperationsSupported) { + // bail if the user wants shared memory cache but we cannot support it + fatal("memory_cache_shared is on, but no support for atomic operations detected"); } if (!Config.memShared) diff --git a/src/cf.data.pre b/src/cf.data.pre index 7f0a73035d..4da9db7839 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -2558,8 +2558,10 @@ DEFAULT: none DOC_START Controls whether the memory cache is shared among SMP workers. - By default, the memory cache is shared only if there are multiple - worker processes with positive cache_mem setting. + By default, the memory cache is shared if and only if all of the + following conditions are satisfied: SMP mode is enabled using multiple + worker processes, cache_mem is positive, and Squid was built with a + compiler that supports GCC-style atomic operations. DOC_END NAME: memory_cache_mode diff --git a/src/ipc/AtomicWord.h b/src/ipc/AtomicWord.h index 9d9080f502..815fcbb2f0 100644 --- a/src/ipc/AtomicWord.h +++ b/src/ipc/AtomicWord.h @@ -6,6 +6,9 @@ #ifndef SQUID_IPC_ATOMIC_WORD_H #define SQUID_IPC_ATOMIC_WORD_H +#if HAVE_ATOMIC_OPS +/// Supplies atomic operations for an integral Value in memory shared by kids. +/// Used to implement non-blocking shared locks, queues, tables, and pools. template class AtomicWordT { public: @@ -34,6 +37,45 @@ private: Value value; }; +enum { AtomicOperationsSupported = 1 }; + +#else +/// A wrapper to provide AtomicWordT API (and asserting implementation) +/// where we do not support atomic operations. This avoids ifdefs in core code. +template +class AtomicWordT { +public: + AtomicWordT() {} // leave value unchanged + AtomicWordT(Value aValue): value(aValue) {} // XXX: unsafe + + Value operator +=(int) { assert(false); return *this; } + Value operator ++() { return *this += 1; } + Value operator --() { return *this += -1; } + Value operator ++(int) { assert(false); return *this; } + Value operator --(int) { assert(false); return *this; } + + bool swap_if(const int comparand, const int replacement) + { assert(false); return false; } + + /// v1 = value; value &= v2; return v1; + Value fetchAndAnd(const Value v2) + { assert(false); return value; } + + // TODO: no need for __sync_bool_compare_and_swap here? + bool operator ==(int v2) { assert(false); return false; } + + // TODO: no need for __sync_fetch_and_add here? + Value get() const { assert(false); return value; } + operator Value () const { return get(); } + +private: + Value value; +}; + +enum { AtomicOperationsSupported = 0 }; + +#endif /* HAVE_ATOMIC_OPS */ + typedef AtomicWordT AtomicWord; #endif // SQUID_IPC_ATOMIC_WORD_H