From 50a609ade9bfcdc7af263dc7fb2481661347a004 Mon Sep 17 00:00:00 2001 From: Jari Sundell Date: Mon, 1 Jun 2026 13:11:02 +0200 Subject: [PATCH] Fixed cacheline size check. --- .gitignore | 1 + configure.ac | 3 +- scripts/checks.m4 | 123 ++++++++++++++++++++++++++++++++++-- scripts/common.m4 | 79 ++++++++++++++++++----- src/input/input_event.cc | 4 +- src/input/input_event.h | 6 +- src/main.cc | 1 + src/rpc/scgi.cc | 2 +- src/rpc/scgi_task.cc | 4 +- test/helpers/test_thread.cc | 2 +- 10 files changed, 196 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index cc5365a2..3613fe0d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ .libs Makefile aclocal.m4 +‎actmp.* ar-lib autom4te.cache compile diff --git a/configure.ac b/configure.ac index d5b7c308..83b7d78e 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,8 @@ LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $ZLIB_LIBS $DEPENDENCIES_LIBS $LIBS CFLAGS="$CFLAGS $PTHREAD_CFLAGS $CURSES_CFLAGS $ZLIB_CFLAGS $DEPENDENCIES_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $CURSES_CFLAGS $ZLIB_CFLAGS $DEPENDENCIES_CFLAGS" -TORRENT_CHECK_POPCOUNT() +TORRENT_CHECK_CACHELINE +TORRENT_CHECK_POPCOUNT AC_CONFIG_FILES([ Makefile diff --git a/scripts/checks.m4 b/scripts/checks.m4 index ccc08e47..663b1e8c 100644 --- a/scripts/checks.m4 +++ b/scripts/checks.m4 @@ -54,6 +54,8 @@ AC_DEFUN([TORRENT_CHECK_EPOLL], [ } ])], [ + use_epoll=yes + AC_DEFINE(USE_EPOLL, 1, Use epoll.) AC_MSG_RESULT(yes) ], [ @@ -86,6 +88,8 @@ AC_DEFUN([TORRENT_CHECK_KQUEUE], [ } ])], [ + use_kqueue=yes + AC_DEFINE(USE_KQUEUE, 1, Use kqueue.) AC_MSG_RESULT(yes) ], [ @@ -125,7 +129,7 @@ AC_DEFUN([TORRENT_CHECK_FALLOCATE], [ #include ]], [[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0; ]])],[ - AC_DEFINE(HAVE_FALLOCATE, 1, Linux's fallocate supported.) + AC_DEFINE(USE_FALLOCATE, 1, Linux's fallocate supported.) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) @@ -157,6 +161,116 @@ AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [ ]) ]) +AC_DEFUN([TORRENT_CHECK_STATVFS], [ + AC_CHECK_HEADERS(sys/vfs.h sys/statvfs.h sys/statfs.h) + + AC_MSG_CHECKING(for statvfs) + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #if HAVE_SYS_VFS_H + #include + #endif + #if HAVE_SYS_STATVFS_H + #include + #endif + #if HAVE_SYS_STATFS_H + #include + #endif + ]], [[ + struct statvfs s; fsblkcnt_t c; + statvfs("", &s); + fstatvfs(0, &s); + ]])],[ + AC_DEFINE(FS_STAT_FD, [fstatvfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd) + AC_DEFINE(FS_STAT_FN, [statvfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename) + AC_DEFINE(FS_STAT_STRUCT, [struct statvfs], Type of second argument to statfs function) + AC_DEFINE(FS_STAT_SIZE_TYPE, [unsigned long], Type of block size member in stat struct) + AC_DEFINE(FS_STAT_COUNT_TYPE, [fsblkcnt_t], Type of block count member in stat struct) + AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_frsize)], Determine the block size) + AC_MSG_RESULT(ok) + have_stat_vfs=yes + ],[ + AC_MSG_RESULT(no) + have_stat_vfs=no + ]) +]) + +AC_DEFUN([TORRENT_CHECK_STATFS], [ + AC_CHECK_HEADERS(sys/statfs.h) + + AC_MSG_CHECKING(for statfs) + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #if HAVE_SYS_STATFS_H + #include + #endif + ]], [[ + struct statfs s; + statfs("", &s); + fstatfs(0, &s); + ]])],[ + AC_DEFINE(FS_STAT_FD, [fstatfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd) + AC_DEFINE(FS_STAT_FN, [statfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename) + AC_DEFINE(FS_STAT_STRUCT, [struct statfs], Type of second argument to statfs function) + AC_DEFINE(FS_STAT_SIZE_TYPE, [long], Type of block size member in stat struct) + AC_DEFINE(FS_STAT_COUNT_TYPE, [long], Type of block count member in stat struct) + AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_bsize)], Determine the block size) + AC_MSG_RESULT(ok) + have_stat_vfs=yes + ],[ + AC_MSG_RESULT(no) + have_stat_vfs=no + ]) +]) + +AC_DEFUN([TORRENT_DISABLED_STATFS], [ + AC_DEFINE(FS_STAT_FD, [(errno = ENOSYS) == 0], Function to determine filesystem stats from fd) + AC_DEFINE(FS_STAT_FN, [(errno = ENOSYS) == 0], Function to determine filesystem stats from filename) + AC_DEFINE(FS_STAT_STRUCT, [struct {blocksize_type f_bsize; blockcount_type f_bavail;}], Type of second argument to statfs function) + AC_DEFINE(FS_STAT_SIZE_TYPE, [int], Type of block size member in stat struct) + AC_DEFINE(FS_STAT_COUNT_TYPE, [int], Type of block count member in stat struct) + AC_DEFINE(FS_STAT_BLOCK_SIZE, [(4096)], Determine the block size) + AC_MSG_RESULT(No filesystem stats available) +]) + +AC_DEFUN([TORRENT_WITHOUT_STATVFS], [ + AC_ARG_WITH(statvfs, + AS_HELP_STRING([--without-statvfs],[don't try to use statvfs to find free diskspace]), + [ + if test "$withval" = "yes"; then + TORRENT_CHECK_STATVFS + else + have_stat_vfs=no + fi + ], + [ + TORRENT_CHECK_STATVFS + ]) +]) + +AC_DEFUN([TORRENT_WITHOUT_STATFS], [ + AC_ARG_WITH(statfs, + AS_HELP_STRING([--without-statfs],[don't try to use statfs to find free diskspace]), + [ + if test "$have_stat_vfs" = "no"; then + if test "$withval" = "yes"; then + TORRENT_CHECK_STATFS + else + TORRENT_DISABLED_STATFS + fi + fi + ], + [ + if test "$have_stat_vfs" = "no"; then + TORRENT_CHECK_STATFS + if test "$have_stat_vfs" = "no"; then + TORRENT_DISABLED_STATFS + fi + fi + ]) +]) + + AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [ AC_ARG_WITH(address-space, AS_HELP_STRING([--with-address-space=MB],[change the default address space size [[default=1024mb]]]), @@ -189,7 +303,7 @@ AC_DEFUN([TORRENT_WITH_FASTCGI], [ elif test "$withval" = "yes"; then CXXFLAGS="$CXXFLAGS" - LIBS="$LIBS -lfcgi" + LIBS="$LIBS -lfcgi" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ FCGX_Init(); ]])],[ @@ -312,14 +426,14 @@ AC_DEFUN([TORRENT_WITH_LUA], [ AC_DEFUN([TORRENT_WITH_INOTIFY], [ AC_LANG_PUSH(C++) - AC_CHECK_HEADERS([sys/inotify.h mcheck.h]) + AC_CHECK_HEADERS([sys/inotify.h]) AC_MSG_CHECKING([whether sys/inotify.h actually works]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include int main(int,const char**) { return (-1 == inotify_init()); }]) ],[ - AC_DEFINE(HAVE_INOTIFY, 1, [sys/inotify.h exists and works correctly]) + AC_DEFINE(USE_INOTIFY, 1, [sys/inotify.h exists and works correctly]) AC_MSG_RESULT(yes)], [AC_MSG_RESULT(failed)] ) @@ -333,6 +447,7 @@ AC_DEFUN([TORRENT_CHECK_PTHREAD_SETNAME_NP], [ AC_MSG_CHECKING(for pthread_setname_np type) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #define _GNU_SOURCE #include #include ]], [[ diff --git a/scripts/common.m4 b/scripts/common.m4 index d8ee0199..cf3796f6 100644 --- a/scripts/common.m4 +++ b/scripts/common.m4 @@ -159,23 +159,72 @@ AC_DEFUN([TORRENT_CHECK_POPCOUNT], [ ]) AC_DEFUN([TORRENT_CHECK_CACHELINE], [ - AC_MSG_CHECKING(for cacheline) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_MSG_CHECKING([for target cacheline size]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ - #include - #include - void* vptr __cacheline_aligned; - void f() { posix_memalign(&vptr, SMP_CACHE_BYTES, 42); } - ])], - [ - AC_MSG_RESULT(found builtin) -dnl Need to fix this so that it uses the stuff defined by the system. + case "$host_os" in + linux*) + # REGION: Linux Kernel Extraction Loop + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + #include + #include + void* vptr; + void f() { + int res = posix_memalign(&vptr, SMP_CACHE_BYTES, 42); + (void)res; + } + ]])],[ + # We need an explicit variable fallback condition inside AC_COMPUTE_INT + AC_COMPUTE_INT([torrent_cv_cacheline_size], [SMP_CACHE_BYTES], [#include ], [torrent_cv_cacheline_size=0]) - AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.) - ], [ - AC_MSG_RESULT(using default 128 bytes) - AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.) - ]) + if test "$torrent_cv_cacheline_size" -gt 0; then + AC_MSG_RESULT([linux builtin ($torrent_cv_cacheline_size bytes)]) + AC_DEFINE_UNQUOTED([LT_SMP_CACHE_BYTES], [$torrent_cv_cacheline_size], [System-defined Linux L1 SMP cacheline size.]) + else + # Handle scenarios where macro maps to a complex runtime expression or fails + AC_MSG_RESULT([failed to parse SMP_CACHE_BYTES value]) + AC_MSG_FAILURE([Linux kernel headers found, but cacheline constant could not be computed at compile-time.]) + fi + ],[ + # Explicitly validate the CPU type even on Linux if the header check fails + case "$host_cpu" in + x86_64*|amd64*|i386*|i486*|i586*|i686*) + AC_MSG_RESULT([linux fallback x86 64 bytes]) + AC_DEFINE([LT_SMP_CACHE_BYTES], 64, [Fallback 64-byte alignment for Linux x86 hardware.]) + ;; + arm*|aarch64*|powerpc*|ppc*|s390x*) + AC_MSG_RESULT([linux fallback enterprise 128 bytes]) + AC_DEFINE([LT_SMP_CACHE_BYTES], 128, [Fallback 128-byte alignment for Linux enterprise hardware.]) + ;; + *) + AC_MSG_RESULT([unrecognized CPU arch on Linux header fallback]) + AC_MSG_FAILURE([Unrecognized CPU architecture ($host_cpu) on Linux fallback path. Aborting build.]) + ;; + esac + ]) + ;; + + *) + # REGION: Cross-Platform Strict Hardware Mapping (macOS, FreeBSD, OpenBSD, NetBSD) + case "$host_cpu" in + x86_64*|amd64*|i386*|i486*|i586*|i686*) + # Explicit x86 desktop hardware baseline block + AC_MSG_RESULT([$host_os ($host_cpu) standard x86 64 bytes]) + AC_DEFINE([LT_SMP_CACHE_BYTES], 64, [Standard 64-byte alignment for stable x86 hardware layout.]) + ;; + arm*|aarch64*|powerpc*|ppc*|s390x*) + # Explicit modern enterprise and Apple Silicon hardware baseline block + AC_MSG_RESULT([$host_os ($host_cpu) stable enterprise 128 bytes]) + AC_DEFINE([LT_SMP_CACHE_BYTES], 128, [Optimized 128-byte alignment for newer high-performance chipsets.]) + ;; + *) + # STRICT ENFORCEMENT: Fail the build immediately if the CPU isn't explicitly known + AC_MSG_RESULT([unrecognized architecture]) + AC_MSG_FAILURE([The target CPU architecture ($host_cpu) is unrecognized. Aborting configuration to prevent fatal runtime false-sharing or memory misalignment errors.]) + ;; + esac + ;; + esac ]) AC_DEFUN([TORRENT_CHECK_ALIGNED], [ diff --git a/src/input/input_event.cc b/src/input/input_event.cc index bd623b2a..1eab3760 100644 --- a/src/input/input_event.cc +++ b/src/input/input_event.cc @@ -7,13 +7,13 @@ namespace input { void -InputEvent::insert(torrent::net::Poll* p) { +InputEvent::insert(torrent::system::Poll* p) { p->open(this); p->insert_read(this); } void -InputEvent::remove(torrent::net::Poll* p) { +InputEvent::remove(torrent::system::Poll* p) { p->remove_read(this); p->close(this); } diff --git a/src/input/input_event.h b/src/input/input_event.h index d37e9056..7082ca3e 100644 --- a/src/input/input_event.h +++ b/src/input/input_event.h @@ -4,7 +4,7 @@ #include #include -#include +#include namespace input { @@ -16,8 +16,8 @@ public: const char* type_name() const override { return "input"; } - void insert(torrent::net::Poll* p); - void remove(torrent::net::Poll* p); + void insert(torrent::system::Poll* p); + void remove(torrent::system::Poll* p); void event_read() override; void event_write() override; diff --git a/src/main.cc b/src/main.cc index e9130341..2af6234f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -112,6 +112,7 @@ main(int argc, char** argv) { // TODO: Create a fake thread object for initializing other processes and enabling logging. torrent::initialize_main_thread(); + // All signal handlers must restore errno if they return. SignalHandler::set_ignore(SIGPIPE); SignalHandler::set_handler(SIGSEGV, std::bind(&do_panic, SIGSEGV)); SignalHandler::set_handler(SIGILL, std::bind(&do_panic, SIGILL)); diff --git a/src/rpc/scgi.cc b/src/rpc/scgi.cc index 2cb8368d..e482bcba 100644 --- a/src/rpc/scgi.cc +++ b/src/rpc/scgi.cc @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include #include "control.h" diff --git a/src/rpc/scgi_task.cc b/src/rpc/scgi_task.cc index 0af85c65..e759a2c7 100644 --- a/src/rpc/scgi_task.cc +++ b/src/rpc/scgi_task.cc @@ -11,10 +11,10 @@ #include #include #include -#include #include -#include #include +#include +#include #include "control.h" #include "globals.h" diff --git a/test/helpers/test_thread.cc b/test/helpers/test_thread.cc index 201be929..9520ae9f 100644 --- a/test/helpers/test_thread.cc +++ b/test/helpers/test_thread.cc @@ -6,7 +6,7 @@ #include "test/helpers/mock_function.h" #include "torrent/exceptions.h" -#include "torrent/net/poll.h" +#include "torrent/system/poll.h" const int test_thread::test_flag_pre_stop; const int test_thread::test_flag_long_timeout;