]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Detect support for __sync_add_and_fetch() and friends,
authorAlex Rousskov <rousskov@measurement-factory.com>
Wed, 25 May 2011 03:14:15 +0000 (21:14 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Wed, 25 May 2011 03:14:15 +0000 (21:14 -0600)
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.

configure.ac
src/MemStore.cc
src/cf.data.pre
src/ipc/AtomicWord.h

index f3abae336282c352b0f3b6b026352f44a12fbbd3..66cda2ed543c07773c46b4bfe04d347d56493089 100644 (file)
@@ -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]), [ 
index 7944840bddc7b14185de9f1750999a1d3633fec1..5496c089f0f54f1c0238ff8f779a341165f3adcc 100644 (file)
@@ -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)
index 7f0a73035d7ce4e686d85fade3d2e4f83e3eb2d8..4da9db78399bd5023dafb6405c61c5ae6438a714 100644 (file)
@@ -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
index 9d9080f50212a57643c73e8df68e8b8fe63c2517..815fcbb2f0f85536c54a42b45726b8b2b18b0874 100644 (file)
@@ -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 Value>
 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 Value>
+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<int> AtomicWord;
 
 #endif // SQUID_IPC_ATOMIC_WORD_H