diff --git a/CMakeLists.txt b/CMakeLists.txt index e09cbf49..07bb3edc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,6 +251,14 @@ include(CMakeDependentOption) include(CheckCXXSymbolExists) include(CheckSymbolExists) +execute_process(COMMAND getconf LEVEL1_DCACHE_LINESIZE OUTPUT_VARIABLE CACHELINE_SIZE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) +if(CACHELINE_SIZE STREQUAL "" OR CACHELINE_SIZE EQUAL 0 OR CACHELINE_SIZE EQUAL -1) + set(ZMQ_CACHELINE_SIZE 64) +else() + set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE}) +endif() +message(STATUS "Using ${ZMQ_CACHELINE_SIZE} bytes alignment for lock-free data structures") + if(NOT CYGWIN) # TODO cannot we simply do 'if(WIN32) set(ZMQ_HAVE_WINDOWS ON)' or similar? check_include_files(windows.h ZMQ_HAVE_WINDOWS) diff --git a/acinclude.m4 b/acinclude.m4 index 036a30a0..8e3f4d2a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1169,3 +1169,23 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{ AC_MSG_ERROR([Invalid API poller '$api_poller' specified]) fi }]) + +dnl ############################################################################## +dnl # LIBZMQ_CHECK_CACHELINE # +dnl # Check cacheline size for alignment purposes # +dnl ############################################################################## +AC_DEFUN([LIBZMQ_CHECK_CACHELINE], [{ + + zmq_cacheline_size=64 + AC_CHECK_TOOL(libzmq_getconf, getconf) + if ! test "x$libzmq_getconf" = "x"; then + zmq_cacheline_size=$($libzmq_getconf LEVEL1_DCACHE_LINESIZE 2>/dev/null || echo 64) + if test "x$zmq_cacheline_size" = "x0" -o "x$zmq_cacheline_size" = "x-1"; then + # getconf on some architectures does not know the size, try to fallback to + # the value the kernel knows on Linux + zmq_cacheline_size=$(cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size 2>/dev/null || echo 64) + fi + fi + AC_MSG_NOTICE([Using "$zmq_cacheline_size" bytes alignment for lock-free data structures]) + AC_DEFINE_UNQUOTED(ZMQ_CACHELINE_SIZE, $zmq_cacheline_size, [Using "$zmq_cacheline_size" bytes alignment for lock-free data structures]) +}]) diff --git a/builds/cmake/platform.hpp.in b/builds/cmake/platform.hpp.in index 82c49d8f..21a848fd 100644 --- a/builds/cmake/platform.hpp.in +++ b/builds/cmake/platform.hpp.in @@ -11,6 +11,8 @@ #cmakedefine ZMQ_POLL_BASED_ON_SELECT #cmakedefine ZMQ_POLL_BASED_ON_POLL +#cmakedefine ZMQ_CACHELINE_SIZE @ZMQ_CACHELINE_SIZE@ + #cmakedefine ZMQ_FORCE_MUTEXES #cmakedefine HAVE_FORK diff --git a/configure.ac b/configure.ac index ec593c87..71d393ea 100644 --- a/configure.ac +++ b/configure.ac @@ -376,6 +376,9 @@ LIBZMQ_CHECK_DOC_BUILD # Check polling system, set appropriate macro in src/platform.hpp LIBZMQ_CHECK_POLLER +# Check cacheline size, set appropriate macro in src/platform.hpp +LIBZMQ_CHECK_CACHELINE + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(\ diff --git a/src/yqueue.hpp b/src/yqueue.hpp index 9e8b3ec0..c2dde691 100644 --- a/src/yqueue.hpp +++ b/src/yqueue.hpp @@ -55,8 +55,9 @@ namespace zmq // posix_memalign available. Default value is 64, this alignment will // prevent two queue chunks from occupying the same CPU cache line on // architectures where cache lines are <= 64 bytes (e.g. most things -// except POWER). -template class yqueue_t +// except POWER). It is detected at build time to try to account for other +// platforms like POWER and s390x. +template class yqueue_t #else template class yqueue_t #endif