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.
# 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]), [
{
// 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)
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
#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:
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