diff --git a/net/ucx/Makefile b/net/ucx/Makefile index 0df5bef86db1..22cc4a832fef 100644 --- a/net/ucx/Makefile +++ b/net/ucx/Makefile @@ -1,67 +1,69 @@ -PORTNAME= ucx -DISTVERSION= 1.20.0 -PORTREVISION= 1 -CATEGORIES= net -MASTER_SITES= https://github.com/openucx/ucx/releases/download/v${DISTVERSION}/ +PORTNAME= ucx +DISTVERSION= 1.20.1 +CATEGORIES= net +MASTER_SITES= https://github.com/openucx/ucx/releases/download/v${DISTVERSION}/ -MAINTAINER= rikka.goering@outlook.de -COMMENT= Unified Communication X framework (UCX) -WWW= https://openucx.org/ +MAINTAINER= rikka.goering@outlook.de +COMMENT= Unified Communication X framework (UCX) +WWW= https://openucx.org/ -LICENSE= BSD3CLAUSE +LICENSE= BSD3CLAUSE +LICENSE_FILE= ${WRKSRC}/LICENSE ONLY_FOR_ARCHS= aarch64 amd64 powerpc64le ONLY_FOR_ARCHS_REASON= uses arch-specific CPU backends; armv7 is not supported upstream and does not build on FreeBSD -BUILD_DEPENDS= ${LOCALBASE}/share/aclocal/ax_c_float_words_bigendian.m4:devel/autoconf-archive - -USES= autoreconf gmake libtool pkgconfig -USE_LDCONFIG= yes - -GNU_CONFIGURE= yes -CONFIGURE_ARGS= --enable-mt \ - --with-go=no \ - --enable-compiler-opt=0 \ - --disable-doxygen-doc -CONFIGURE_ENV+= GIT=/usr/bin/false - -INSTALL_TARGET= install-strip - -TEST_ENV+= LD_LIBRARY_PATH=${STAGEDIR}${PREFIX}/lib - -CFLAGS+= -Wno-error -CXXFLAGS+= -Wno-error -LDFLAGS+= -lexecinfo - -PORTDOCS= * -PORTEXAMPLES= * - -OPTIONS_DEFINE= DOCS EXAMPLES FUSE IBVERBS IODEMO UMAD PERFTEST -OPTIONS_DEFAULT= IODEMO PERFTEST FUSE +BUILD_DEPENDS= ${LOCALBASE}/share/aclocal/ax_c_float_words_bigendian.m4:devel/autoconf-archive + +USES= autoreconf dos2unix gmake libtool pkgconfig +USE_LDCONFIG= yes + +GNU_CONFIGURE= yes +CONFIGURE_ARGS= --disable-doxygen-doc \ + --enable-compiler-opt=0 \ + --enable-gtest \ + --enable-mt \ + --with-go=no +CONFIGURE_ENV= GIT=/usr/bin/false +INSTALL_TARGET= install-strip +TEST_ENV+= LD_LIBRARY_PATH=${STAGEDIR}${PREFIX}/lib +CFLAGS+= -Wno-error +CXXFLAGS+= -Wno-error +LDFLAGS+= -lexecinfo -lprocstat -lutil + +PORTDOCS= * +PORTEXAMPLES= * + +OPTIONS_DEFINE= DOCS EXAMPLES FUSE IBVERBS IODEMO PERFTEST UMAD +OPTIONS_DEFAULT= FUSE IODEMO PERFTEST OPTIONS_SUB= yes IBVERBS_DESC= Enable InfiniBand/RDMA (verbs) transport IODEMO_DESC= Install io_demo test application PERFTEST_DESC= Install ucx_perftest benchmarks UMAD_DESC= Build/install perftest MAD plugin (umad) FUSE_LIB_DEPENDS= libfuse3.so:filesystems/fusefs-libs3 FUSE_CONFIGURE_ON= --with-fuse3=${LOCALBASE} FUSE_CONFIGURE_OFF= --with-fuse3=no IBVERBS_CONFIGURE_ON= --with-verbs=${LOCALBASE} IBVERBS_CONFIGURE_OFF= --with-verbs=no UMAD_IMPLIES= IBVERBS PERFTEST UMAD_CONFIGURE_ON= --with-mad=${LOCALBASE} UMAD_CONFIGURE_OFF= --with-mad=no +post-patch: + ${REINPLACE_CMD} 's|^examplesdir = $$(pkgdatadir)/examples$$|examplesdir = ${EXAMPLESDIR}|' \ + ${WRKSRC}/examples/Makefile.am + post-install: ${MV} ${STAGEDIR}${ETCDIR}/ucx.conf ${STAGEDIR}${ETCDIR}/ucx.conf.sample do-test: - @${ECHO_MSG} "===> Running UCX smoke tests (ucx_info)" - ${SETENVI} ${TEST_ENV} ${STAGEDIR}${PREFIX}/bin/ucx_info -v >/dev/null - ${SETENVI} ${TEST_ENV} ${STAGEDIR}${PREFIX}/bin/ucx_info -d >/dev/null + cd ${WRKSRC}/test/gtest && \ + ${SETENV} ${TEST_ENV} ${MAKE_CMD} && \ + ${SETENV} ${TEST_ENV} ./gtest --gtest_filter=-malloc_hook*:sysv/*:test_rcache*:test_rcache_pfn*:test_vfs_sock*:test_datatype.hlist_for_each_extract_if:tcp/test_uct_pending.pending_fairness*:tcp/test_uct_peer_failure.purge_failed_peer*:tcp/test_uct_pending.pending_purge*:tcp/test_uct_iface.is_reachable*:tcp/test_uct_perf*:tcp/test_uct_loopback*:tcp/test_uct_tcp.listener_flood_connect_and_send_large*:tcp/test_uct_tcp.listener_flood_connect_and_send_small*:tcp/test_uct_tcp.check_addr_len*:shm*/*:mm_tcp/*:ib_shm/*:ud_tcp/*:all/*:*/test_ucp_am*:*/test_ucp_loopback*:tcp/test_ucp_perf*:*/test_ucp_proto_mock_self.rkey_ptr*:*/test_ucp_tag_probe*:test_config.test_config_file:test_config.test_config_file_parse_files:signal/*:*/test_async.many_timers*:*/test_ucp_peer_failure_keepalive*:*/test_ucp_mmap*:self/test_ucp_wakeup.signal*:tcp/test_ucp_wakeup.signal*:tcp/test_proto_reset.am_eager_multi_bcopy*:tcp/test_uct_sockaddr.err_handle*:tcp/test_ucp_sockaddr_protocols_diff_net_devices*:*.*rndv*:*/test_ucp_tag_match_rndv_align*:tcp/test_ucp_sockaddr_iface_activate* .include diff --git a/net/ucx/distinfo b/net/ucx/distinfo index 03dfb53b5e8e..a2d38f6413d8 100644 --- a/net/ucx/distinfo +++ b/net/ucx/distinfo @@ -1,3 +1,3 @@ -TIMESTAMP = 1771060207 -SHA256 (ucx-1.20.0.tar.gz) = 7c8a6093cada179aa1d851b83625e3b25ed5658966e309de5118c27a038c7ef9 -SIZE (ucx-1.20.0.tar.gz) = 3500736 +TIMESTAMP = 1781120416 +SHA256 (ucx-1.20.1.tar.gz) = 545c419a7b5e04643cb8bff5a19b3b5071a8f8f0605f1e8efb36f8f3d7bfb9d3 +SIZE (ucx-1.20.1.tar.gz) = 3505964 diff --git a/net/ucx/files/patch-configure.ac b/net/ucx/files/patch-configure.ac index 59c76d368312..80c52b4ff672 100644 --- a/net/ucx/files/patch-configure.ac +++ b/net/ucx/files/patch-configure.ac @@ -1,108 +1,106 @@ ---- configure.ac.orig 2026-02-05 12:41:56 UTC +--- configure.ac.orig 2026-06-12 20:50:26 UTC +++ configure.ac @@ -14,8 +14,6 @@ define([ucx_ver_extra], ) # Extra version string. Em - define([ucx_ver_patch], 0) # Patch version. Increased for a bugfix release. + define([ucx_ver_patch], 1) # Patch version. Increased for a bugfix release. define([ucx_ver_extra], ) # Extra version string. Empty for a general release. -define([ts], esyscmd([sh -c "date +%Y%m%d%H%M%S"])) - # This is the API version (see libtool library versioning) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # current:rev:age @@ -31,14 +29,20 @@ AC_CONFIG_HEADERS([config.h]) AC_USE_SYSTEM_EXTENSIONS AC_CONFIG_HEADERS([config.h]) -AC_CHECK_PROG(GITBIN, git, yes) -AS_IF([test x"${GITBIN}" = x"yes"], - [# remove preceding "refs/heads/" (11 characters) for symbolic ref - AC_SUBST(SCM_BRANCH, esyscmd([sh -c 'git symbolic-ref --quiet HEAD | sed "s/^.\{11\}//"'])) - AC_SUBST(SCM_VERSION, esyscmd([sh -c 'git rev-parse --short=7 HEAD']))], - [AC_SUBST(SCM_BRANCH, "") - AC_SUBST(SCM_VERSION, "0000000")]) +AC_PATH_PROG([GIT], [git], [:]) +SCM_BRANCH="" +SCM_VERSION="0000000" + +AS_IF([test -d "${srcdir}/.git" && test "x$GIT" != "x:" && \ + $GIT -C "${srcdir}" rev-parse --is-inside-work-tree >/dev/null 2>&1], [ + SCM_BRANCH=`$GIT -C "${srcdir}" symbolic-ref --quiet HEAD 2>/dev/null | sed 's,^refs/heads/,,'` + SCM_VERSION=`$GIT -C "${srcdir}" rev-parse --short=7 HEAD 2>/dev/null` +]) + +AC_SUBST([SCM_BRANCH]) +AC_SUBST([SCM_VERSION]) + AH_TOP([ #ifndef UCX_CONFIG_H #define UCX_CONFIG_H @@ -85,9 +89,44 @@ AC_FUNC_STRERROR_R AC_C_RESTRICT AC_FUNC_STRERROR_R -AC_PATH_TOOL([PKG_CONFIG], [pkg-config], [pkg-config]) +PKG_PROG_PKG_CONFIG +dnl Float word order can differ from integer endianness on some ABIs. + dnl Prefer Autoconf's macro if available; otherwise fall back to autoconf-archive. + m4_ifdef([AC_C_FLOAT_WORDS_BIGENDIAN], + [AC_C_FLOAT_WORDS_BIGENDIAN], + [m4_ifdef([AX_C_FLOAT_WORDS_BIGENDIAN], + [AX_C_FLOAT_WORDS_BIGENDIAN], + [AC_MSG_ERROR([need AC_C_FLOAT_WORDS_BIGENDIAN or AX_C_FLOAT_WORDS_BIGENDIAN])])]) +AC_CHECK_HEADERS([sys/eventfd.h sys/timerfd.h]) +AC_CHECK_HEADERS([netinet/in.h arpa/inet.h]) + +AC_CHECK_FUNCS([brk sbrk]) + +AS_IF([test "x$ac_cv_func_brk" = "xyes" && test "x$ac_cv_func_sbrk" = "xyes"], + [have_brk_sbrk=yes], + [have_brk_sbrk=no]) + +have_ucm_malloc_hooks=no +case "$host_os" in + linux*) have_ucm_malloc_hooks=yes ;; + *) have_ucm_malloc_hooks=no ;; +esac +AM_CONDITIONAL([HAVE_UCM_MALLOC_HOOKS], [test "x$have_ucm_malloc_hooks" = xyes]) + +AM_CONDITIONAL([HAVE_BRK_SBRK], [test "x$have_brk_sbrk" = "xyes"]) +AS_IF([test "x$have_brk_sbrk" = "xyes"], + [AC_DEFINE([HAVE_BRK_SBRK], [1], + [Define if both brk() and sbrk() are available])], + []) + +case "$host_os" in + freebsd*) build_gtest=no ;; + *) build_gtest=yes ;; +esac +AM_CONDITIONAL([BUILD_GTEST], [test "x$build_gtest" = xyes]) + # # Define SHARED_LIB preprocessor macro when building a shared library # -@@ -255,6 +294,22 @@ AS_IF([test "x$with_docs_only" = xyes], +@@ -255,6 +294,20 @@ AS_IF([test "x$with_docs_only" = xyes], m4_include([test/apps/iodemo/configure.m4]) m4_include([test/apps/uct_info/configure.m4]) -+AS_IF([test "x$with_docs_only" != xyes && test "x$build_gtest" = xyes], [ -+ PKG_CHECK_MODULES([GTEST], [gtest_main], -+ [have_gtest=yes], -+ [have_gtest=no]) ++AS_IF([test "x$with_docs_only" != xyes], [ ++ have_gtest=yes +], [ + have_gtest=no +]) + +AM_CONDITIONAL([HAVE_GTEST], [test "x$have_gtest" = "xyes"]) + +GTEST_CPPFLAGS="${GTEST_CFLAGS}" +GTEST_CXXFLAGS="${GTEST_CFLAGS}" +GTEST_LDFLAGS="" +AC_SUBST([GTEST_CPPFLAGS]) +AC_SUBST([GTEST_CXXFLAGS]) +AC_SUBST([GTEST_LDFLAGS]) # # Disable checking user parameters diff --git a/net/ucx/files/patch-src_tools_info_Makefile.am b/net/ucx/files/patch-src_tools_info_Makefile.am index bb0ea71e540e..9c5b81819aba 100644 --- a/net/ucx/files/patch-src_tools_info_Makefile.am +++ b/net/ucx/files/patch-src_tools_info_Makefile.am @@ -1,15 +1,15 @@ ---- src/tools/info/Makefile.am.orig 2026-02-04 09:52:46 UTC +--- src/tools/info/Makefile.am.orig 2026-06-10 21:28:13 UTC +++ src/tools/info/Makefile.am @@ -14,7 +14,11 @@ build_config.h: $(top_builddir)/config.h Makefile # Produce a C header file which contains all defined variables from config.h # build_config.h: $(top_builddir)/config.h Makefile - $(SED) -nr 's:\s*#define\s+(\w+)(\s+(\w+)|\s+(".*")|\s*)$$:{"\1", UCS_PP_MAKE_STRING(\3\4)},:p' <$(top_builddir)/config.h >$@ + $(SED) -nE \ + -e 's/^[[:space:]]*#define[[:space:]]+([A-Za-z_][A-Za-z_0-9]*)[[:space:]]+(".*")$$/{"\1", UCS_PP_MAKE_STRING(\2)},/p' \ + -e 's/^[[:space:]]*#define[[:space:]]+([A-Za-z_][A-Za-z0-9_]*)[[:space:]]+([^[:space:]]+)$$/{"\1", UCS_PP_MAKE_STRING(\2)},/p' \ + -e 's/^[[:space:]]*#define[[:space:]]+([A-Za-z_][A-Za-z0-9_]*)$$/{"\1", ""},/p' \ + <$(top_builddir)/config.h >$@ ucx_info_CPPFLAGS = $(BASE_CPPFLAGS) ucx_info_CFLAGS = $(BASE_CFLAGS) diff --git a/net/ucx/files/patch-src_ucm_Makefile.am b/net/ucx/files/patch-src_ucm_Makefile.am index 49b81a7ad4b8..f543ead036ea 100644 --- a/net/ucx/files/patch-src_ucm_Makefile.am +++ b/net/ucx/files/patch-src_ucm_Makefile.am @@ -1,50 +1,12 @@ ---- src/ucm/Makefile.am.orig 2026-02-04 09:52:46 UTC +--- src/ucm/Makefile.am.orig 2026-06-10 21:24:01 UTC +++ src/ucm/Makefile.am -@@ -21,8 +21,6 @@ noinst_HEADERS = \ - - noinst_HEADERS = \ - event/event.h \ -- malloc/malloc_hook.h \ -- malloc/allocator.h \ - mmap/mmap.h \ - util/khash_safe.h \ - util/replace.h \ -@@ -38,7 +36,6 @@ libucm_la_SOURCES = \ - - libucm_la_SOURCES = \ - event/event.c \ -- malloc/malloc_hook.c \ - mmap/install.c \ - util/replace.c \ - util/log.c \ -@@ -50,6 +47,17 @@ libucm_la_SOURCES = \ +@@ -48,7 +48,8 @@ libucm_la_SOURCES = \ + bistro/bistro_x86_64.c \ + bistro/bistro_aarch64.c \ bistro/bistro_ppc64.c \ - bistro/bistro_rv64.c +- bistro/bistro_rv64.c ++ bistro/bistro_rv64.c \ ++ malloc/brk_sbrk_override_stub.c -+if HAVE_UCM_MALLOC_HOOKS -+noinst_HEADERS += \ -+ malloc/malloc_hook.h \ -+ malloc/allocator.h -+ -+libucm_la_SOURCES += \ -+ malloc/malloc_hook.c -+else -+libucm_la_SOURCES += \ -+ malloc/malloc_hook_stub.c -+ if HAVE_UCM_PTMALLOC286 libucm_la_CPPFLAGS += \ - -fno-strict-aliasing \ -@@ -61,5 +69,12 @@ noinst_HEADERS += \ - - noinst_HEADERS += \ - ptmalloc286/malloc-2.8.6.h -+endif -+endif -+ -+if HAVE_BRK_SBRK -+else -+libucm_la_SOURCES += \ -+ malloc/brk_sbrk_override_stub.c - endif - diff --git a/net/ucx/files/patch-src_ucm_util_sys.c b/net/ucx/files/patch-src_ucm_util_sys.c index 8982c6fd9cda..d09fb998b3f3 100644 --- a/net/ucx/files/patch-src_ucm_util_sys.c +++ b/net/ucx/files/patch-src_ucm_util_sys.c @@ -1,103 +1,161 @@ --- src/ucm/util/sys.c.orig 2026-02-04 09:52:46 UTC +++ src/ucm/util/sys.c -@@ -21,10 +21,17 @@ +@@ -14,6 +14,13 @@ + # include "config.h" + #endif + ++#if defined(__FreeBSD__) ++#include ++#include ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -21,10 +28,17 @@ #include #include #include +#ifdef HAVE_LINUX_MMAN_H #include +#endif #include #include +#ifdef __linux__ #include +#elif defined(__FreeBSD__) +#include +#include +#endif #include #include #include -@@ -34,6 +41,24 @@ +@@ -34,6 +48,24 @@ #define UCM_PROC_SELF_MAPS "/proc/self/maps" +#if !defined(__linux__) +#include +#include + +void *ucm_orig_mremap(void *old_address, size_t old_size, size_t new_size, + int flags, void *new_address) +{ + (void)old_address; + (void)old_size; + (void)new_size; + (void)flags; + (void)new_address; + + errno = ENOSYS; + return MAP_FAILED; +} +#endif + ucm_global_config_t ucm_global_opts = { .log_level = UCS_LOG_LEVEL_WARN, .enable_events = 1, -@@ -136,7 +161,22 @@ void *ucm_sys_realloc(void *ptr, size_t size) +@@ -136,7 +168,22 @@ void *ucm_sys_realloc(void *ptr, size_t size) return ptr; } +#if defined(__linux__) newptr = ucm_orig_mremap(oldptr, oldsize, sys_size, MREMAP_MAYMOVE, NULL); +#else + /* FreeBSD: no Linux mremap/MREMAP_MAYMOVE. Fallback: allocate+copy+unmap. + * If upper layers can tolerate "not supported", you can instead: + * errno = ENOTSUP; return MAP_FAILED; + */ + newptr = mmap(NULL, sys_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (newptr != MAP_FAILED) { + size_t copy_sz = (oldsize < sys_size) ? oldsize : sys_size; + memcpy(newptr, oldptr, copy_sz); + munmap(oldptr, oldsize); + } +#endif + if (newptr == MAP_FAILED) { ucm_error("mremap(oldptr=%p oldsize=%zu, newsize=%zu) failed: %m", oldptr, oldsize, sys_size); -@@ -377,15 +417,31 @@ void *ucm_brk_syscall(void *addr) +@@ -148,6 +195,35 @@ void ucm_parse_proc_self_maps(ucm_proc_maps_cb_t cb, v + + void ucm_parse_proc_self_maps(ucm_proc_maps_cb_t cb, void *arg) + { ++#if defined(__FreeBSD__) ++ struct kinfo_vmentry *vmmap; ++ int count, i, prot; ++ char *path; ++ char empty_path[] = ""; ++ ++ vmmap = kinfo_getvmmap(getpid(), &count); ++ if (vmmap == NULL) { ++ ucm_warn("kinfo_getvmmap() failed: %m"); ++ return; ++ } ++ ++ for (i = 0; i < count; i++) { ++ prot = 0; ++ if (vmmap[i].kve_protection & KVME_PROT_READ) prot |= PROT_READ; ++ if (vmmap[i].kve_protection & KVME_PROT_WRITE) prot |= PROT_WRITE; ++ if (vmmap[i].kve_protection & KVME_PROT_EXEC) prot |= PROT_EXEC; ++ ++ path = (vmmap[i].kve_path[0] != '\0') ? vmmap[i].kve_path ++ : empty_path; ++ if (cb(arg, (void *)vmmap[i].kve_start, ++ vmmap[i].kve_end - vmmap[i].kve_start, ++ prot, path)) { ++ break; ++ } ++ } ++ ++ free(vmmap); ++#else + static char *buffer = MAP_FAILED; + static size_t buffer_size = 32768; + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +@@ -263,6 +339,7 @@ out: + + out: + pthread_mutex_unlock(&lock); ++#endif + } + + typedef struct { +@@ -377,15 +454,31 @@ void *ucm_brk_syscall(void *addr) void *ucm_brk_syscall(void *addr) { +#if defined(__linux__) /* Return type is equivalent to full pointer size */ UCS_STATIC_ASSERT(sizeof(syscall(0)) == sizeof(void*)); - return (void*)syscall(SYS_brk, addr); +#else + (void)addr; + errno = ENOSYS; + return NULL; +#endif } -pid_t ucm_get_tid() +pid_t ucm_get_tid(void) { - return syscall(SYS_gettid); +#if defined(__linux__) + return (pid_t)syscall(SYS_gettid); +#elif defined(__FreeBSD__) + long tid; + if (thr_self(&tid) == 0) { + return (pid_t)tid; + } + /* fallback */ + return (pid_t)getpid(); +#else + return (pid_t)getpid(); +#endif } void UCS_F_CTOR ucm_init() diff --git a/net/ucx/files/patch-src_ucp_core_ucp__worker.c b/net/ucx/files/patch-src_ucp_core_ucp__worker.c index dbb3d655732e..671c3fa16573 100644 --- a/net/ucx/files/patch-src_ucp_core_ucp__worker.c +++ b/net/ucx/files/patch-src_ucp_core_ucp__worker.c @@ -1,127 +1,184 @@ --- src/ucp/core/ucp_worker.c.orig 2026-02-05 12:41:56 UTC +++ src/ucp/core/ucp_worker.c @@ -9,6 +9,8 @@ # include "config.h" #endif +#include + #include "ucp_am.h" #include "ucp_ep_vfs.h" #include "ucp_worker.h" -@@ -35,9 +37,15 @@ +@@ -35,9 +37,18 @@ #include #include #include --#include --#include --#include +#if defined(HAVE_SYS_EVENTFD_H) -+# include + #include +-#include +#endif +#if defined(HAVE_SYS_TIMERFD_H) -+# include + #include +#endif +#if defined(__linux__) -+# include ++#include ++#endif ++#if defined(__FreeBSD__) ++#include +#endif #include -@@ -320,6 +328,7 @@ static ucs_status_t ucp_worker_wakeup_init(ucp_worker_ +@@ -290,7 +301,10 @@ static ucs_status_t ucp_worker_wakeup_init(ucp_worker_ + worker->event_fd = -1; + worker->event_set = NULL; + worker->eventfd = -1; +- worker->uct_events = 0; ++#if defined(__FreeBSD__) ++ worker->eventfd_write = -1; ++#endif ++ worker->uct_events = 0; + status = UCS_OK; + goto out; + } +@@ -320,6 +334,19 @@ static ucs_status_t ucp_worker_wakeup_init(ucp_worker_ worker->flags |= UCP_WORKER_FLAG_EDGE_TRIGGERED; } -+#if defined(HAVE_SYS_EVENTFD_H) ++#if defined(__FreeBSD__) ++ { ++ int pipefd[2]; ++ if (pipe2(pipefd, O_CLOEXEC | O_NONBLOCK) < 0) { ++ ucs_error("Failed to create wakeup pipe: %m"); ++ status = UCS_ERR_IO_ERROR; ++ goto err_cleanup_event_set; ++ } ++ worker->eventfd = pipefd[0]; /* read end: monitored by kqueue */ ++ worker->eventfd_write = pipefd[1]; /* write end: used to signal */ ++ } ++ ucp_worker_wakeup_ctl_fd(worker, UCP_WORKER_EPFD_OP_ADD, worker->eventfd); ++#elif defined(HAVE_SYS_EVENTFD_H) worker->eventfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (worker->eventfd == -1) { ucs_error("Failed to create event fd: %m"); -@@ -328,6 +337,10 @@ static ucs_status_t ucp_worker_wakeup_init(ucp_worker_ +@@ -328,6 +355,13 @@ static ucs_status_t ucp_worker_wakeup_init(ucp_worker_ } ucp_worker_wakeup_ctl_fd(worker, UCP_WORKER_EPFD_OP_ADD, worker->eventfd); +#else + /* No eventfd(). */ + worker->eventfd = -1; ++#if defined(__FreeBSD__) ++ worker->eventfd_write = -1; ++#endif +#endif worker->uct_events = 0; -@@ -427,6 +440,10 @@ static ucs_status_t ucp_worker_wakeup_signal_fd(ucp_wo +@@ -371,6 +405,12 @@ static void ucp_worker_wakeup_cleanup(ucp_worker_h wor + } + if (worker->eventfd != -1) { + close(worker->eventfd); ++#if defined(__FreeBSD__) ++ if (worker->eventfd_write != -1) { ++ close(worker->eventfd_write); ++ worker->eventfd_write = -1; ++ } ++#endif + } + } + +@@ -423,12 +463,24 @@ static ucs_status_t ucp_worker_wakeup_signal_fd(ucp_wo + static ucs_status_t ucp_worker_wakeup_signal_fd(ucp_worker_h worker) + { + uint64_t dummy = 1; ++ int write_fd; + int ret; - ucs_trace_func("worker=%p fd=%d", worker, worker->eventfd); +- ucs_trace_func("worker=%p fd=%d", worker, worker->eventfd); ++#if defined(__FreeBSD__) ++ write_fd = worker->eventfd_write; ++#else ++ write_fd = worker->eventfd; ++#endif -+ if (worker->eventfd == -1) { ++ ucs_trace_func("worker=%p fd=%d", worker, write_fd); ++ ++ if (write_fd == -1) { ++ + return UCS_OK; + } + do { - ret = write(worker->eventfd, &dummy, sizeof(dummy)); +- ret = write(worker->eventfd, &dummy, sizeof(dummy)); ++ ret = write(write_fd, &dummy, sizeof(dummy)); if (ret == sizeof(dummy)) { -@@ -3375,7 +3392,7 @@ void ucp_worker_print_info(ucp_worker_h worker, FILE * + return UCS_OK; + } else if (ret == -1) { +@@ -3375,7 +3427,7 @@ void ucp_worker_print_info(ucp_worker_h worker, FILE * UCP_WORKER_THREAD_CS_EXIT_CONDITIONAL(worker); } -static UCS_F_ALWAYS_INLINE void +static UCS_F_ALWAYS_INLINE ucs_status_t ucp_worker_keepalive_timerfd_init(ucp_worker_h worker) { ucs_time_t ka_interval = worker->context->config.ext.keepalive_interval; -@@ -3385,14 +3402,18 @@ ucp_worker_keepalive_timerfd_init(ucp_worker_h worker) +@@ -3385,14 +3437,18 @@ ucp_worker_keepalive_timerfd_init(ucp_worker_h worker) if (!(worker->context->config.features & UCP_FEATURE_WAKEUP) || (worker->keepalive.timerfd >= 0)) { - return; + return UCS_OK; } +/* timerfd_* are Linux-only */ +#if !defined(HAVE_SYS_TIMERFD_H) + worker->keepalive.timerfd = -1; + return UCS_OK; +#else worker->keepalive.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if (worker->keepalive.timerfd < 0) { - ucs_warn("worker %p: failed to create keepalive timer fd: %m", - worker); - return; + ucs_error("timerfd_create() failed: %m"); + return UCS_ERR_IO_ERROR; } ucs_assert(ka_interval > 0); -@@ -3412,10 +3433,11 @@ ucp_worker_keepalive_timerfd_init(ucp_worker_h worker) +@@ -3412,10 +3468,11 @@ ucp_worker_keepalive_timerfd_init(ucp_worker_h worker) ucp_worker_wakeup_ctl_fd(worker, UCP_WORKER_EPFD_OP_ADD, worker->keepalive.timerfd); - return; + return UCS_OK; err_close_timerfd: close(worker->keepalive.timerfd); +#endif } static UCS_F_ALWAYS_INLINE void -@@ -3571,6 +3593,7 @@ void ucp_worker_keepalive_add_ep(ucp_ep_h ep) +@@ -3571,6 +3628,7 @@ void ucp_worker_keepalive_add_ep(ucp_ep_h ep) void ucp_worker_keepalive_add_ep(ucp_ep_h ep) { ucp_worker_h worker = ep->worker; + ucs_status_t status; if (ucp_ep_config(ep)->key.keepalive_lane == UCP_NULL_LANE) { ucs_trace("ep %p flags 0x%x cfg_index %d err_mode %d: keepalive lane" -@@ -3579,7 +3602,12 @@ void ucp_worker_keepalive_add_ep(ucp_ep_h ep) +@@ -3579,7 +3637,12 @@ void ucp_worker_keepalive_add_ep(ucp_ep_h ep) return; } - ucp_worker_keepalive_timerfd_init(worker); + status = ucp_worker_keepalive_timerfd_init(worker); + if ((status != UCS_OK) && (status != UCS_ERR_UNSUPPORTED)) { + ucs_warn("worker %p: failed to initialize keepalive timerfd: %s", + worker, ucs_status_string(status)); + } + ucs_trace("ep %p flags 0x%x: set keepalive lane to %u", ep, ep->flags, ucp_ep_config(ep)->key.keepalive_lane); uct_worker_progress_register_safe(worker->uct, diff --git a/net/ucx/files/patch-src_ucp_core_ucp__worker.h b/net/ucx/files/patch-src_ucp_core_ucp__worker.h new file mode 100644 index 000000000000..3a91f11aef42 --- /dev/null +++ b/net/ucx/files/patch-src_ucp_core_ucp__worker.h @@ -0,0 +1,13 @@ +--- src/ucp/core/ucp_worker.h.orig 2026-02-05 12:41:56 UTC ++++ src/ucp/core/ucp_worker.h +@@ -319,6 +319,10 @@ typedef struct ucp_worker { + int event_fd; /* Allocated (on-demand) event fd for wakeup */ + ucs_sys_event_set_t *event_set; /* Allocated UCS event set for wakeup */ + int eventfd; /* Event fd to support signal() calls */ ++#if defined(__FreeBSD__) ++ int eventfd_write; /* Write end of wakeup pipe (FreeBSD only). ++ * eventfd holds the read end. */ ++#endif + unsigned uct_events; /* UCT arm events */ + ucs_list_link_t arm_ifaces; /* List of interfaces to arm */ + diff --git a/net/ucx/files/patch-src_ucs_datastruct_string__buffer.c b/net/ucx/files/patch-src_ucs_datastruct_string__buffer.c new file mode 100644 index 000000000000..e69c65333301 --- /dev/null +++ b/net/ucx/files/patch-src_ucs_datastruct_string__buffer.c @@ -0,0 +1,18 @@ +--- src/ucs/datastruct/string_buffer.c.orig 2026-05-17 17:31:16 UTC ++++ src/ucs/datastruct/string_buffer.c +@@ -141,8 +141,13 @@ void ucs_string_buffer_append_iovec(ucs_string_buffer_ + size_t iov_index; + + for (iov_index = 0; iov_index < iovcnt; ++iov_index) { +- ucs_string_buffer_appendf(strb, "%p,%zu|", iov[iov_index].iov_base, +- iov[iov_index].iov_len); ++ if (iov[iov_index].iov_base == NULL) { ++ ucs_string_buffer_appendf(strb, "(nil),%zu|", ++ iov[iov_index].iov_len); ++ } else { ++ ucs_string_buffer_appendf(strb, "%p,%zu|", iov[iov_index].iov_base, ++ iov[iov_index].iov_len); ++ } + } + ucs_string_buffer_rtrim(strb, "|"); + } diff --git a/net/ucx/files/patch-src_ucs_datastruct_usage__tracker.c b/net/ucx/files/patch-src_ucs_datastruct_usage__tracker.c new file mode 100644 index 000000000000..c7b2e5fd591c --- /dev/null +++ b/net/ucx/files/patch-src_ucs_datastruct_usage__tracker.c @@ -0,0 +1,21 @@ +--- src/ucs/datastruct/usage_tracker.c.orig 2026-05-06 13:47:14 UTC ++++ src/ucs/datastruct/usage_tracker.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #define UCS_USAGE_TRACKER_VERIFY_SCORE_PARAM(_params, _field) \ + if (((_params)->_field > 1) || ((_params)->_field < 0)) { \ +@@ -207,8 +208,8 @@ static void ucs_usage_tracker_promote(ucs_usage_tracke + elem_index ++; + ) + +- qsort_r(elems_array, elems_count, sizeof(*elems_array), +- ucs_usage_tracker_compare, params); ++ ucs_qsort_r(elems_array, elems_count, sizeof(*elems_array), ++ ucs_usage_tracker_compare, params); + + promote_count = ucs_min(params->promote_thresh, elems_count); + for (elem_index = 0; elem_index < promote_count; ++elem_index) { diff --git a/net/ucx/files/patch-src_ucs_debug_memtrack.c b/net/ucx/files/patch-src_ucs_debug_memtrack.c new file mode 100644 index 000000000000..846896bed0c1 --- /dev/null +++ b/net/ucx/files/patch-src_ucs_debug_memtrack.c @@ -0,0 +1,46 @@ +--- src/ucs/debug/memtrack.c.orig 2026-02-04 09:52:46 UTC ++++ src/ucs/debug/memtrack.c +@@ -327,7 +327,11 @@ void *ucs_malloc(size_t size, const char *name) + + void *ucs_malloc(size_t size, const char *name) + { +- void *ptr = malloc(size); ++ void *ptr; ++#ifdef UCX_ALLOC_ALIGN ++ size = ucs_align_up_pow2(size, UCX_ALLOC_ALIGN); ++#endif ++ ptr = malloc(size); + UCS_MEMTRACK_LOG_ZERO_SIZE_ALLOACTION(size, ptr, name); + ucs_memtrack_allocated_internal(ptr, size, name); + return ptr; +@@ -335,14 +339,29 @@ void *ucs_calloc(size_t nmemb, size_t size, const char + + void *ucs_calloc(size_t nmemb, size_t size, const char *name) + { +- void *ptr = calloc(nmemb, size); ++ void *ptr; ++#ifdef UCX_ALLOC_ALIGN ++ size_t total = ucs_align_up_pow2(nmemb * size, UCX_ALLOC_ALIGN); ++ ptr = malloc(total); ++ if (ptr != NULL) { ++ memset(ptr, 0, total); ++ } ++ UCS_MEMTRACK_LOG_ZERO_SIZE_ALLOACTION(total, ptr, name); ++ ucs_memtrack_allocated_internal(ptr, total, name); ++ return ptr; ++#else ++ ptr = calloc(nmemb, size); + UCS_MEMTRACK_LOG_ZERO_SIZE_ALLOACTION(nmemb * size, ptr, name); + ucs_memtrack_allocated_internal(ptr, nmemb * size, name); + return ptr; ++#endif + } + + void *ucs_realloc(void *ptr, size_t size, const char *name) + { ++#ifdef UCX_ALLOC_ALIGN ++ size = ucs_align_up_pow2(size, UCX_ALLOC_ALIGN); ++#endif + ucs_memtrack_releasing_internal(ptr); + ptr = realloc(ptr, size); + UCS_MEMTRACK_LOG_ZERO_SIZE_ALLOACTION(size, ptr, name); diff --git a/net/ucx/files/patch-src_ucs_sys_netlink.c b/net/ucx/files/patch-src_ucs_sys_netlink.c index 5fd9c75cc883..a1a451b6e205 100644 --- a/net/ucx/files/patch-src_ucs_sys_netlink.c +++ b/net/ucx/files/patch-src_ucs_sys_netlink.c @@ -1,50 +1,92 @@ ---- src/ucs/sys/netlink.c.orig 2026-02-05 12:41:56 UTC +--- src/ucs/sys/netlink.c.orig 2026-05-06 13:47:14 UTC +++ src/ucs/sys/netlink.c @@ -8,6 +8,8 @@ #include "config.h" #endif +#if defined(__linux__) + #include "netlink.h" #include -@@ -310,3 +312,38 @@ int ucs_netlink_route_exists(int if_index, const struc +@@ -347,3 +349,80 @@ int ucs_netlink_is_best_route(int if_index, const stru - return info.found; + return (ucs_netlink_max_netmask_len(sa_remote) == netmask_len); } +#else + +#include "netlink.h" + -+/* -+ * Netlink is Linux-specific. On non-Linux platforms (e.g., FreeBSD), -+ * UCX should build and run without netlink-based route checks. -+ */ ++#include ++ ++#include ++#include ++#include ++#include ++ +ucs_status_t +ucs_netlink_send_request(int protocol, unsigned short nlmsg_type, + unsigned short nlmsg_flags, + const void *protocol_header, size_t header_length, + ucs_netlink_parse_cb_t parse_cb, void *arg) +{ + (void)protocol; + (void)nlmsg_type; + (void)nlmsg_flags; + (void)protocol_header; + (void)header_length; + (void)parse_cb; + (void)arg; + return UCS_ERR_UNSUPPORTED; +} + +int +ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote, -+ int allow_default_gw) ++ int *netmask_len_p) ++{ ++ char if_name[IF_NAMESIZE]; ++ struct ifreq ifr; ++ struct sockaddr_in local_addr, netmask; ++ in_addr_t local_ip, mask, remote_ip; ++ ++ if (sa_remote->sa_family != AF_INET) { ++ return 0; /* IPv6 not yet handled */ ++ } ++ ++ if (if_indextoname(if_index, if_name) == NULL) { ++ return 0; ++ } ++ ++ memset(&ifr, 0, sizeof(ifr)); ++ if (ucs_netif_ioctl(if_name, SIOCGIFADDR, &ifr) != UCS_OK) { ++ return 0; ++ } ++ memcpy(&local_addr, &ifr.ifr_addr, sizeof(local_addr)); ++ ++ memset(&ifr, 0, sizeof(ifr)); ++ if (ucs_netif_ioctl(if_name, SIOCGIFNETMASK, &ifr) != UCS_OK) { ++ return 0; ++ } ++ memcpy(&netmask, &ifr.ifr_addr, sizeof(netmask)); ++ ++ local_ip = local_addr.sin_addr.s_addr; ++ mask = netmask.sin_addr.s_addr; ++ remote_ip = ((const struct sockaddr_in *)sa_remote)->sin_addr.s_addr; ++ ++ if (netmask_len_p != NULL) { ++ *netmask_len_p = __builtin_popcount(ntohl(mask)); ++ } ++ ++ /* Remote is reachable if it is in the same subnet as the local interface */ ++ return (remote_ip & mask) == (local_ip & mask); ++} ++ ++int ++ucs_netlink_is_best_route(int if_index, const struct sockaddr *sa_remote) +{ -+ (void)if_index; -+ (void)sa_remote; -+ (void)allow_default_gw; -+ return 0; ++ int netmask_len; ++ ++ return ucs_netlink_route_exists(if_index, sa_remote, &netmask_len); +} + +#endif diff --git a/net/ucx/files/patch-src_ucs_sys_sock.c b/net/ucx/files/patch-src_ucs_sys_sock.c new file mode 100644 index 000000000000..541411d97e83 --- /dev/null +++ b/net/ucx/files/patch-src_ucs_sys_sock.c @@ -0,0 +1,30 @@ +--- src/ucs/sys/sock.c.orig 2026-05-06 13:47:14 UTC ++++ src/ucs/sys/sock.c +@@ -20,7 +20,10 @@ + + #include + #include ++#include + #include ++#include ++#include + #include + #include + #include +@@ -517,6 +520,16 @@ int ucs_socket_max_conn() + int ucs_socket_max_conn() + { + static long somaxconn_val = 0; ++ ++#if defined(__FreeBSD__) ++ if (!somaxconn_val) { ++ int val; ++ size_t len = sizeof(val); ++ if (sysctlbyname("kern.ipc.somaxconn", &val, &len, NULL, 0) == 0) { ++ somaxconn_val = val; ++ } ++ } ++#endif + + if (somaxconn_val || + (ucs_read_file_number(&somaxconn_val, 1, diff --git a/net/ucx/files/patch-src_ucs_sys_sys.c b/net/ucx/files/patch-src_ucs_sys_sys.c index 39d00cd926db..0e8f1cf6cef2 100644 --- a/net/ucx/files/patch-src_ucs_sys_sys.c +++ b/net/ucx/files/patch-src_ucs_sys_sys.c @@ -1,321 +1,354 @@ ---- src/ucs/sys/sys.c.orig 2026-02-05 12:41:56 UTC +--- src/ucs/sys/sys.c.orig 2026-05-06 13:47:14 UTC +++ src/ucs/sys/sys.c -@@ -23,16 +23,27 @@ +@@ -23,16 +23,28 @@ #include #include +#include #include #include #include #include #include #include +#include #include +#include #include #include #include +#include +#if defined(__FreeBSD__) +#include +#include +#include +#include +#include ++#include +#endif #ifdef HAVE_SYS_THR_H #include #endif -@@ -94,7 +105,7 @@ const char *ucs_get_host_name() +@@ -94,7 +106,7 @@ const char *ucs_get_host_name() const char *ucs_get_host_name() { - static char hostname[HOST_NAME_MAX] = {0}; + static char hostname[UCS_HOST_NAME_MAX] = {0}; if (*hostname == 0) { gethostname(hostname, sizeof(hostname)); -@@ -180,6 +191,41 @@ int ucs_netif_is_ipoib(const char *if_name) - - int ucs_netif_is_ipoib(const char *if_name) - { -+#if defined(__FreeBSD__) -+ struct ifaddrs *ifap = NULL, *ifa; -+ int is_ipoib = 0; -+ -+ if (getifaddrs(&ifap) != 0) { -+ ucs_debug("getifaddrs() failed for %s: %m", if_name); -+ return 0; -+ } -+ -+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { -+ const struct sockaddr *sa = ifa->ifa_addr; -+ const struct sockaddr_dl *sdl; -+ -+ if ((ifa->ifa_name == NULL) || (sa == NULL)) { -+ continue; -+ } -+ if (strcmp(ifa->ifa_name, if_name) != 0) { -+ continue; -+ } -+ if (sa->sa_family != AF_LINK) { -+ continue; -+ } -+ -+ sdl = (const struct sockaddr_dl *)sa; -+#ifdef IFT_INFINIBAND -+ if (sdl->sdl_type == IFT_INFINIBAND) { -+ is_ipoib = 1; -+ break; -+ } -+#endif -+ } -+ -+ freeifaddrs(ifap); -+ return is_ipoib; -+#else - struct ifreq ifr; - ucs_status_t status; - -@@ -191,11 +237,56 @@ int ucs_netif_is_ipoib(const char *if_name) - } - - return ifr.ifr_hwaddr.sa_family == ARPHRD_INFINIBAND; -+#endif - } - +@@ -181,6 +193,46 @@ static uint64_t ucs_get_mac_address() static uint64_t ucs_get_mac_address() { static uint64_t mac_address = 0; +#if defined(__FreeBSD__) + struct ifaddrs *ifap = NULL, *ifa; + + if (mac_address != 0) { + return mac_address; + } + + if (getifaddrs(&ifap) != 0) { + ucs_error("getifaddrs() failed: %m"); + return 0; + } + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + const struct sockaddr *sa = ifa->ifa_addr; + const struct sockaddr_dl *sdl; + const unsigned char *lladdr; + + if ((ifa->ifa_flags & IFF_LOOPBACK) || (sa == NULL)) { + continue; + } + if (sa->sa_family != AF_LINK) { + continue; + } + + sdl = (const struct sockaddr_dl *)sa; + if (sdl->sdl_alen < 6) { + continue; + } + + lladdr = (const unsigned char *)LLADDR(sdl); -+ /* -+ * Copy first 6 bytes (MAC). Keep same semantics as Linux code: -+ * store into low bytes of uint64_t. -+ */ + mac_address = 0; + memcpy(&mac_address, lladdr, 6); + break; + } + + freeifaddrs(ifap); + + ucs_trace("MAC address is 0x%012"PRIX64, mac_address); + return mac_address; +#else struct ifreq ifr, *it, *end; struct ifconf ifc; char buf[1024]; -@@ -243,6 +334,7 @@ static uint64_t ucs_get_mac_address() +@@ -228,6 +280,7 @@ static uint64_t ucs_get_mac_address() } return mac_address; +#endif } static uint64_t __sumup_host_name(unsigned prime_index) -@@ -766,6 +858,10 @@ static void ucs_sysv_shmget_error_check_ENOSPC(size_t +@@ -671,6 +724,21 @@ size_t ucs_get_memfree_size() + { + ssize_t mem_free; + ++#if defined(__FreeBSD__) ++ unsigned long v_free_count; ++ unsigned long pagesize; ++ size_t len; ++ ++ len = sizeof(v_free_count); ++ if (sysctlbyname("vm.stats.vm.v_free_count", &v_free_count, &len, ++ NULL, 0) == 0) { ++ len = sizeof(pagesize); ++ if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) == 0) { ++ return v_free_count * pagesize; ++ } ++ } ++ return UCS_DEFAULT_MEM_FREE; ++#else + mem_free = ucs_get_meminfo_entry("MemFree"); + if (mem_free == -1) { + mem_free = UCS_DEFAULT_MEM_FREE; +@@ -679,12 +747,16 @@ size_t ucs_get_memfree_size() + } + + return mem_free; ++#endif + } + + ssize_t ucs_get_huge_page_size() + { + static ssize_t huge_page_size = 0; + ++#if defined(__FreeBSD__) ++ return -1; ++#else + /* Cache the huge page size value */ + if (huge_page_size == 0) { + huge_page_size = ucs_get_meminfo_entry("Hugepagesize"); +@@ -696,6 +768,7 @@ ssize_t ucs_get_huge_page_size() + } + + return huge_page_size; ++#endif + } + + size_t ucs_get_phys_mem_size() +@@ -751,6 +824,10 @@ static void ucs_sysv_shmget_error_check_ENOSPC(size_t const struct shminfo *ipc_info, char *buf, size_t max) { +#if defined(__FreeBSD__) + (void)alloc_size; (void)ipc_info; (void)buf; (void)max; + return; +#else unsigned long new_used_ids; unsigned long new_shm_tot; struct shm_info shm_info; -@@ -797,6 +893,7 @@ static void ucs_sysv_shmget_error_check_ENOSPC(size_t +@@ -782,6 +859,7 @@ static void ucs_sysv_shmget_error_check_ENOSPC(size_t " limit in /proc/sys/kernel/shmall (=%lu)", new_shm_tot, ipc_info->shmall); } +#endif } ucs_status_t ucs_sys_get_proc_cap(uint32_t *effective) -@@ -857,6 +954,14 @@ static void ucs_sysv_shmget_format_error(size_t alloc_ +@@ -842,6 +920,14 @@ static void ucs_sysv_shmget_format_error(size_t alloc_ const char *alloc_name, int sys_errno, char *buf, size_t max) { +#if defined(__FreeBSD__) + /* FreeBSD does not have Linux shmctl(IPC_INFO/SHM_INFO) or struct shminfo. */ + snprintf(buf, max, + "shmget(size=%zu flags=0x%x) for %s failed: %s, please check shared " + "memory limits by 'sysctl kern.ipc' / 'sysctl hw.pagesize' / 'ipcs -a'", + alloc_size, flags, alloc_name, strerror(sys_errno)); + return; +#else struct shminfo ipc_info; char *p, *endp, *errp; int ret; -@@ -894,6 +999,7 @@ static void ucs_sysv_shmget_format_error(size_t alloc_ +@@ -879,6 +965,7 @@ static void ucs_sysv_shmget_format_error(size_t alloc_ if (p == errp) { snprintf(p, endp - p, ", please check shared memory limits by 'ipcs -l'"); } +#endif } ucs_status_t ucs_sysv_alloc(size_t *size, size_t max_size, void **address_p, -@@ -1287,11 +1393,44 @@ void *ucs_sys_realloc(void *old_ptr, size_t old_length +@@ -1272,11 +1359,44 @@ void *ucs_sys_realloc(void *old_ptr, size_t old_length { void *ptr; +#if defined(__FreeBSD__) + size_t copy_length; + new_length = ucs_align_up_pow2(new_length, ucs_get_page_size()); if (old_ptr == NULL) { + ptr = mmap(NULL, new_length, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (ptr == MAP_FAILED) { + ucs_log_fatal_error("mmap(NULL, %zu, READ|WRITE, PRIVATE|ANON) failed: %m", + new_length); + return NULL; + } + return ptr; + } + + old_length = ucs_align_up_pow2(old_length, ucs_get_page_size()); + ptr = mmap(NULL, new_length, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (ptr == MAP_FAILED) { + ucs_log_fatal_error("mmap(NULL, %zu, READ|WRITE, PRIVATE|ANON) failed: %m", + new_length); + return NULL; + } + + copy_length = ucs_min(old_length, new_length); + memcpy(ptr, old_ptr, copy_length); + + if (munmap(old_ptr, old_length) != 0) { + ucs_log_fatal_error("munmap(%p, %zu) failed: %m", old_ptr, old_length); + } + + return ptr; +#elif defined(__linux__) + new_length = ucs_align_up_pow2(new_length, ucs_get_page_size()); + if (old_ptr == NULL) { /* Note: Must pass the 0 offset as "long", otherwise it will be * partially undefined when converted to syscall arguments */ - ptr = (void*)syscall(__NR_mmap, NULL, new_length, PROT_READ|PROT_WRITE, + ptr = (void*)syscall(SYS_mmap, NULL, new_length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0ul); if (ptr == MAP_FAILED) { ucs_log_fatal_error("mmap(NULL, %zu, READ|WRITE, PRIVATE|ANON) failed: %m", -@@ -1300,7 +1439,7 @@ void *ucs_sys_realloc(void *old_ptr, size_t old_length +@@ -1285,7 +1405,7 @@ void *ucs_sys_realloc(void *old_ptr, size_t old_length } } else { old_length = ucs_align_up_pow2(old_length, ucs_get_page_size()); - ptr = (void*)syscall(__NR_mremap, old_ptr, old_length, new_length, + ptr = (void*)syscall(SYS_mremap, old_ptr, old_length, new_length, MREMAP_MAYMOVE); if (ptr == MAP_FAILED) { ucs_log_fatal_error("mremap(%p, %zu, %zu, MAYMOVE) failed: %m", -@@ -1310,6 +1449,13 @@ void *ucs_sys_realloc(void *old_ptr, size_t old_length +@@ -1295,6 +1415,13 @@ void *ucs_sys_realloc(void *old_ptr, size_t old_length } return ptr; +#else +(void)old_ptr; + (void)old_length; + (void)new_length; + ucs_log_fatal_error("ucs_sys_realloc() is not implemented on this platform"); + return NULL; +#endif } void ucs_sys_free(void *ptr, size_t length) -@@ -1317,11 +1463,19 @@ void ucs_sys_free(void *ptr, size_t length) +@@ -1302,11 +1429,19 @@ void ucs_sys_free(void *ptr, size_t length) int ret; if (ptr != NULL) { +#if defined(__FreeBSD__) length = ucs_align_up_pow2(length, ucs_get_page_size()); - ret = syscall(__NR_munmap, ptr, length); + ret = munmap(ptr, length); if (ret) { ucs_log_fatal_error("munmap(%p, %zu) failed: %m", ptr, length); } +#else + length = ucs_align_up_pow2(length, ucs_get_page_size()); + ret = syscall(SYS_munmap, ptr, length); + if (ret) { + ucs_log_fatal_error("munmap(%p, %zu) failed: %m", ptr, length); + } +#endif } } -@@ -1391,12 +1545,32 @@ ucs_status_t ucs_sys_pthread_getaffinity(ucs_sys_cpuse +@@ -1376,12 +1511,32 @@ ucs_status_t ucs_sys_pthread_getaffinity(ucs_sys_cpuse ucs_status_t ucs_sys_pthread_getaffinity(ucs_sys_cpuset_t *cpuset) { +#if defined(__FreeBSD__) + long tid; + int ret; + +#ifdef HAVE_SYS_THR_H + thr_self(&tid); +#else + /* Fallback: best-effort use process id */ + tid = (long)getpid(); +#endif + + ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, tid, + sizeof(*cpuset), cpuset); + if (ret != 0) { + ucs_error("cpuset_getaffinity(TID=%ld) failed: %m", tid); + return UCS_ERR_INVALID_PARAM; + } + return UCS_OK; +#else if (pthread_getaffinity_np(pthread_self(), sizeof(*cpuset), cpuset)) { ucs_error("pthread_getaffinity_np() failed: %m"); return UCS_ERR_INVALID_PARAM; } return UCS_OK; +#endif } void ucs_sys_cpuset_copy(ucs_cpu_set_t *dst, const ucs_sys_cpuset_t *src) -@@ -1557,7 +1731,8 @@ ucs_status_t ucs_pthread_create(pthread_t *thread_id_p +@@ -1435,6 +1590,10 @@ ucs_status_t ucs_sys_get_boot_id(uint64_t *high, uint6 + + static ucs_init_once_t init_once = UCS_INIT_ONCE_INITIALIZER; + static ucs_status_t status = UCS_ERR_IO_ERROR; ++#if defined(__FreeBSD__) ++ struct timeval boottime; ++ size_t len; ++#else + char bootid_str[256]; + ssize_t size; + uint32_t v1; +@@ -1444,8 +1603,17 @@ ucs_status_t ucs_sys_get_boot_id(uint64_t *high, uint6 + uint8_t v5[6]; + int res; + int i; ++#endif + + UCS_INIT_ONCE(&init_once) { ++#if defined(__FreeBSD__) ++ len = sizeof(boottime); ++ if (sysctlbyname("kern.boottime", &boottime, &len, NULL, 0) == 0) { ++ boot_id.high = (uint64_t)boottime.tv_sec; ++ boot_id.low = (uint64_t)boottime.tv_usec; ++ status = UCS_OK; ++ } ++#else + size = ucs_read_file_str(bootid_str, sizeof(bootid_str), 1, + "%s", UCS_PROCESS_BOOTID_FILE); + if (size <= 0) { +@@ -1465,6 +1633,7 @@ ucs_status_t ucs_sys_get_boot_id(uint64_t *high, uint6 + boot_id.high |= (uint64_t)v5[i] << (16 + (i * 8)); + } + } ++#endif + } + + if (status == UCS_OK) { +@@ -1542,7 +1711,8 @@ ucs_status_t ucs_pthread_create(pthread_t *thread_id_p ret = pthread_create(&thread_id, NULL, start_routine, arg); if (ret != 0) { - ucs_error("pthread_create() failed: %m"); + ucs_error("pthread_create(start_routine=%p arg=%p) failed: %s (%d)", + start_routine, arg, strerror(ret), ret); return UCS_ERR_IO_ERROR; } diff --git a/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c b/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c index 4daa7a79a795..03e48c699cb6 100644 --- a/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c +++ b/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c @@ -1,78 +1,96 @@ --- src/ucs/vfs/sock/vfs_sock.c.orig 2026-02-04 09:52:46 UTC +++ src/ucs/vfs/sock/vfs_sock.c @@ -24,6 +24,9 @@ #include #include #include +#if defined(__FreeBSD__) +#include +#endif typedef struct { @@ -76,7 +79,13 @@ int ucs_vfs_sock_setopt_passcred(int sockfd) int optval, ret; optval = 1; +#if defined(__linux__) ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)); +#elif defined(__FreeBSD__) + ret = setsockopt(sockfd, SOL_LOCAL, LOCAL_CREDS, &optval, sizeof(optval)); +#else + ret = 0; /* no-op on other platforms for now */ +#endif if (ret < 0) { return -errno; } +@@ -106,6 +115,8 @@ int ucs_vfs_sock_send(int sockfd, const ucs_vfs_sock_m + + memset(cbuf, 0, sizeof(cbuf)); + memset(&msgh, 0, sizeof(msgh)); ++ msgh.msg_control = cbuf; ++ msgh.msg_controllen = sizeof(cbuf); + msg.action = vfs_msg->action; + iov.iov_base = &msg; + iov.iov_len = sizeof(msg); +@@ -114,8 +125,6 @@ int ucs_vfs_sock_send(int sockfd, const ucs_vfs_sock_m + + if (vfs_msg->action == UCS_VFS_SOCK_ACTION_MOUNT_REPLY) { + /* send file descriptor */ +- msgh.msg_control = cbuf; +- msgh.msg_controllen = sizeof(cbuf); + cmsgp = CMSG_FIRSTHDR(&msgh); + cmsgp->cmsg_level = SOL_SOCKET; + cmsgp->cmsg_len = CMSG_LEN(sizeof(vfs_msg->fd)); @@ -132,7 +141,11 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message_t *vfs_msg) { char cbuf[CMSG_SPACE(sizeof(*vfs_msg))] UCS_V_ALIGNED(sizeof(size_t)); +#if defined(__FreeBSD__) + const struct cmsgcred *cred; +#else const struct ucred *cred; +#endif struct cmsghdr *cmsgp; struct msghdr msgh; ucs_vfs_msg_t msg; @@ -178,12 +191,30 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message memcpy(&vfs_msg->fd, CMSG_DATA(cmsgp), sizeof(vfs_msg->fd)); } else { /* expect credentials */ +#if defined(__FreeBSD__) + if ((cmsgp->cmsg_level != SOL_SOCKET) || + (cmsgp->cmsg_type != SCM_CREDS) || + (cmsgp->cmsg_len != CMSG_LEN(sizeof(*cred)))) { + return -EINVAL; + } + + cred = (const struct cmsgcred*)CMSG_DATA(cmsgp); + + if ((cred->cmcred_euid != geteuid()) || (cred->cmcred_gid != getegid())) { + return -EPERM; + } + + if (msg.action == UCS_VFS_SOCK_ACTION_MOUNT) { + vfs_msg->pid = cred->cmcred_pid; + } +#else if ((cmsgp->cmsg_type != SCM_CREDENTIALS) || - (cmsgp->cmsg_len != CMSG_LEN(sizeof(*cred)))) { + (cmsgp->cmsg_len != CMSG_LEN(sizeof(*cred)))) { return -EINVAL; } cred = (const struct ucred*)CMSG_DATA(cmsgp); + if ((cred->uid != getuid()) || (cred->gid != getgid())) { return -EPERM; } @@ -191,6 +222,7 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message if (msg.action == UCS_VFS_SOCK_ACTION_MOUNT) { vfs_msg->pid = cred->pid; } +#endif } return 0; diff --git a/net/ucx/files/patch-src_uct_tcp_tcp.h b/net/ucx/files/patch-src_uct_tcp_tcp.h new file mode 100644 index 000000000000..04deb28ada00 --- /dev/null +++ b/net/ucx/files/patch-src_uct_tcp_tcp.h @@ -0,0 +1,10 @@ +--- src/uct/tcp/tcp.h.orig 2026-06-10 21:16:37 UTC ++++ src/uct/tcp/tcp.h +@@ -20,6 +20,7 @@ + #include + + #include ++#include + + #define UCT_TCP_NAME "tcp" + diff --git a/net/ucx/files/patch-src_uct_tcp_tcp__iface.c b/net/ucx/files/patch-src_uct_tcp_tcp__iface.c index 6049d4462248..6dbced1b33d7 100644 --- a/net/ucx/files/patch-src_uct_tcp_tcp__iface.c +++ b/net/ucx/files/patch-src_uct_tcp_tcp__iface.c @@ -1,173 +1,190 @@ ---- src/uct/tcp/tcp_iface.c.orig 2026-03-14 01:11:54 UTC +--- src/uct/tcp/tcp_iface.c.orig 2026-05-06 13:47:14 UTC +++ src/uct/tcp/tcp_iface.c @@ -20,6 +20,10 @@ #include #include #include +#if defined(__FreeBSD__) +#include +#include +#endif #define UCT_TCP_IFACE_NETDEV_DIR "/sys/class/net" -@@ -289,6 +293,11 @@ uct_tcp_iface_get_sysfs_path(const char *dev_name, cha +@@ -284,6 +288,11 @@ uct_tcp_iface_get_sysfs_path(const char *dev_name, cha static const char * uct_tcp_iface_get_sysfs_path(const char *dev_name, char *path_buffer) { +#if defined(__FreeBSD__) + (void)dev_name; + (void)path_buffer; + return NULL; +#else const char *sysfs_path = NULL; ucs_status_t status; char *lowest_path_buf; -@@ -315,6 +324,7 @@ out: +@@ -310,6 +319,7 @@ out: ucs_free(lowest_path_buf); out: return sysfs_path; +#endif } static ucs_status_t uct_tcp_iface_query(uct_iface_h tl_iface, -@@ -948,6 +958,10 @@ static int uct_tcp_is_bridge(const char *if_name) +@@ -422,7 +432,16 @@ static void uct_tcp_iface_handle_events(void *callback + unsigned *count = (unsigned*)arg; + uct_tcp_ep_t *ep = (uct_tcp_ep_t*)callback_data; + ++#if defined(__FreeBSD__) ++ /* kqueue may deliver a queued event for an ep that was closed and ++ * removed from the event set between the kevent() call and this ++ * callback. Treat it as a no-op rather than aborting. */ ++ if (ep->conn_state == UCT_TCP_EP_CONN_STATE_CLOSED) { ++ return; ++ } ++#else + ucs_assertv(ep->conn_state != UCT_TCP_EP_CONN_STATE_CLOSED, "ep=%p", ep); ++#endif + + if (events & UCS_EVENT_SET_EVREAD) { + *count += uct_tcp_ep_cm_state[ep->conn_state].rx_progress(ep); +@@ -943,6 +962,10 @@ static int uct_tcp_is_bridge(const char *if_name) static int uct_tcp_is_bridge(const char *if_name) { +#if defined(__FreeBSD__) + (void)if_name; + return 0; +#else char *path; int ret; struct stat st; -@@ -967,6 +981,7 @@ out: +@@ -962,6 +985,7 @@ out: ucs_free(path); out: return ret; +#endif } ucs_status_t uct_tcp_query_devices(uct_md_h md, -@@ -976,7 +991,11 @@ ucs_status_t uct_tcp_query_devices(uct_md_h md, +@@ -971,7 +995,11 @@ ucs_status_t uct_tcp_query_devices(uct_md_h md, uct_tcp_md_t *tcp_md = ucs_derived_of(md, uct_tcp_md_t); const unsigned sys_device_priority = 10; uct_tl_device_resource_t *devices, *tmp; - struct dirent **entries, **entry; +#if defined(__FreeBSD__) + struct if_nameindex *ifn, *it; +#else + struct dirent **entries, **entry; +#endif unsigned num_devices; int is_active, i, n; ucs_status_t status; -@@ -984,21 +1003,77 @@ ucs_status_t uct_tcp_query_devices(uct_md_h md, +@@ -979,21 +1007,77 @@ ucs_status_t uct_tcp_query_devices(uct_md_h md, char *path_buffer; ucs_sys_device_t sys_dev; +#if defined(__FreeBSD__) + ifn = if_nameindex(); + if (ifn == NULL) { + ucs_error("if_nameindex() failed: %m"); + status = UCS_ERR_IO_ERROR; + goto out; + } +#else n = scandir(UCT_TCP_IFACE_NETDEV_DIR, &entries, NULL, alphasort); if (n == -1) { ucs_error("scandir(%s) failed: %m", UCT_TCP_IFACE_NETDEV_DIR); status = UCS_ERR_IO_ERROR; goto out; } +#endif devices = NULL; num_devices = 0; +#if defined(__FreeBSD__) + path_buffer = NULL; + status = UCS_OK; +#else status = ucs_string_alloc_path_buffer(&path_buffer, "path_buffer"); if (status != UCS_OK) { - goto out; + goto out_release; } +#endif +#if defined(__FreeBSD__) + for (it = ifn; it->if_name != NULL; ++it) { + is_active = 0; + for (i = 0; i < tcp_md->config.af_prio_count; i++) { + if (ucs_netif_is_active(it->if_name, + tcp_md->config.af_prio_list[i])) { + is_active = 1; + break; + } + } + + if (!is_active) { + continue; + } + + if (!tcp_md->config.bridge_enable && + uct_tcp_is_bridge(it->if_name)) { + ucs_debug("filtered out bridge device %s", it->if_name); + continue; + } + + tmp = ucs_realloc(devices, sizeof(*devices) * (num_devices + 1), + "tcp devices"); + if (tmp == NULL) { + ucs_free(devices); + status = UCS_ERR_NO_MEMORY; + goto out_release; + } + devices = tmp; + + sysfs_path = uct_tcp_iface_get_sysfs_path(it->if_name, path_buffer); + sys_dev = ucs_topo_get_sysfs_dev(it->if_name, sysfs_path, + sys_device_priority); + + ucs_snprintf_zero(devices[num_devices].name, + sizeof(devices[num_devices].name), "%s", + it->if_name); + devices[num_devices].type = UCT_DEVICE_TYPE_NET; + devices[num_devices].sys_device = sys_dev; + ++num_devices; + } +#else ucs_carray_for_each(entry, entries, n) { /* According to the sysfs(5) manual page, all of entries * has to be a symbolic link representing one of the real -@@ -1050,18 +1125,28 @@ ucs_status_t uct_tcp_query_devices(uct_md_h md, +@@ -1045,18 +1129,28 @@ ucs_status_t uct_tcp_query_devices(uct_md_h md, devices[num_devices].sys_device = sys_dev; ++num_devices; } +#endif *num_devices_p = num_devices; *devices_p = devices; status = UCS_OK; out_release: +#if defined(__FreeBSD__) + if (ifn != NULL) { + if_freenameindex(ifn); + } + if (path_buffer != NULL) { + ucs_free(path_buffer); + } +#else ucs_carray_for_each(entry, entries, n) { free(*entry); } free(entries); ucs_free(path_buffer); +#endif out: return status; } diff --git a/net/ucx/files/patch-test_gtest_common_googletest_gtest.h b/net/ucx/files/patch-test_gtest_common_googletest_gtest.h new file mode 100644 index 000000000000..c1ebcf6940ea --- /dev/null +++ b/net/ucx/files/patch-test_gtest_common_googletest_gtest.h @@ -0,0 +1,17 @@ +--- test/gtest/common/googletest/gtest.h.orig 2026-06-12 20:49:52 UTC ++++ test/gtest/common/googletest/gtest.h +@@ -1629,6 +1629,14 @@ GTEST_IMPL_CMP_HELPER_(GT, >); + GTEST_IMPL_CMP_HELPER_(GT, >); + + #undef GTEST_IMPL_CMP_HELPER_ ++template ++AssertionResult CmpHelperNE(const char* e1, const char* e2, std::nullptr_t, T* val2) { ++ if (nullptr != val2) { return AssertionSuccess(); } ++ return CmpHelperOpFailure(e1, e2, static_cast(nullptr), val2, "!="); } ++template ++AssertionResult CmpHelperNE(const char* e1, const char* e2, T* val1, std::nullptr_t) { ++ if (val1 != nullptr) { return AssertionSuccess(); } ++ return CmpHelperOpFailure(e1, e2, val1, static_cast(nullptr), "!="); } + + // The helper function for {ASSERT|EXPECT}_STREQ. + // diff --git a/net/ucx/files/patch-test_gtest_common_test.cc b/net/ucx/files/patch-test_gtest_common_test.cc new file mode 100644 index 000000000000..8137143df0f5 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_common_test.cc @@ -0,0 +1,19 @@ +--- test/gtest/common/test.cc.orig 2026-05-07 20:53:46 UTC ++++ test/gtest/common/test.cc +@@ -481,14 +481,15 @@ static void clear_dontcopy_regions_vma_cb(ucs_sys_vma_ + + static void clear_dontcopy_regions_vma_cb(ucs_sys_vma_info_t *info, void *ctx) { + int ret; +- + if (info->flags & UCS_SYS_VMA_FLAG_DONTCOPY) { ++#ifdef __linux__ + ret = madvise((void*)info->start, info->end - info->start, MADV_DOFORK); + if (ret != 0) { + UCS_TEST_MESSAGE << "madvise(DOFORK) failed, errno: " << errno + << std::hex << " 0x" << info->start + << "-0x" << info->end; + } ++#endif + } + } + diff --git a/net/ucx/files/patch-test_gtest_common_test__helpers.cc b/net/ucx/files/patch-test_gtest_common_test__helpers.cc index e371b490b40b..76f9a5f7f136 100644 --- a/net/ucx/files/patch-test_gtest_common_test__helpers.cc +++ b/net/ucx/files/patch-test_gtest_common_test__helpers.cc @@ -1,13 +1,25 @@ ---- test/gtest/common/test_helpers.cc.orig 2026-02-04 09:52:46 UTC +--- test/gtest/common/test_helpers.cc.orig 2026-05-06 13:47:14 UTC +++ test/gtest/common/test_helpers.cc -@@ -13,6 +13,10 @@ +@@ -13,6 +13,11 @@ #include #include +#include +#include +#include ++#include + #include extern "C" { +@@ -513,7 +518,9 @@ out_close: + } + + out_close: +- closedir(dir); ++ if (dir != NULL) { ++ closedir(dir); ++ } + return result; + } + diff --git a/net/ucx/files/patch-test_gtest_common_test__helpers.h b/net/ucx/files/patch-test_gtest_common_test__helpers.h new file mode 100644 index 000000000000..1dc0916147ab --- /dev/null +++ b/net/ucx/files/patch-test_gtest_common_test__helpers.h @@ -0,0 +1,10 @@ +--- test/gtest/common/test_helpers.h.orig 2026-06-10 22:15:23 UTC ++++ test/gtest/common/test_helpers.h +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + + #ifndef UINT16_MAX diff --git a/net/ucx/files/patch-test_gtest_ucm_malloc__hook.cc b/net/ucx/files/patch-test_gtest_ucm_malloc__hook.cc new file mode 100644 index 000000000000..0e2f74d6c6f5 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucm_malloc__hook.cc @@ -0,0 +1,93 @@ +--- test/gtest/ucm/malloc_hook.cc.orig 2026-02-04 09:52:46 UTC ++++ test/gtest/ucm/malloc_hook.cc +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -244,7 +245,9 @@ class malloc_hook : public ucs::test { (protected) + + m_got_event = 0; + ucm_malloc_state_reset(128 * 1024, 128 * 1024); +- malloc_trim(0); ++#ifdef __linux__ ++ malloc_trim(0); ++#endif + status = event.set(UCM_EVENT_VM_MAPPED); + ASSERT_UCS_OK(status); + +@@ -483,7 +486,9 @@ void test_thread::test() { + new_ptrs.clear(); + + /* Call several malloc routines */ ++#ifdef __linux__ + malloc_trim(0); ++#endif + + ptr = malloc(large_alloc_size); + +@@ -514,6 +519,7 @@ void test_thread::test() { + } + + /* mremap(FIXED) */ ++#ifdef __linux__ + { + ptr = mmap(NULL, shm_seg_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +@@ -538,6 +544,7 @@ void test_thread::test() { + /* coverity[pass_freed_arg] */ + EXPECT_TRUE(is_ptr_in_range(ptr2, shm_seg_size, m_unmap_ranges)); + } ++#endif + + /* Print results */ + pthread_mutex_lock(&lock); +@@ -569,7 +576,9 @@ UCS_TEST_SKIP_COND_F(malloc_hook, multi_threads, + ucs::ptr_vector threads; + pthread_barrier_t barrier; + ++#ifdef __linux__ + malloc_trim(0); ++#endif + + pthread_barrier_init(&barrier, NULL, num_threads); + for (int i = 0; i < num_threads; ++i) { +@@ -849,8 +858,10 @@ class mmap_hooks { (public) + /* sbrk call is used to extend/cut memory heap, + * don't add any evaluations between calls sbrk+/sbrk- - it + * may break heap */ ++#ifdef HAVE_SBRK + sbrk(size); + sbrk(-size); ++#endif + + EXPECT_INCREASED(m_mapped_size, mapped_size, size, m_name); + EXPECT_INCREASED(m_unmapped_size, unmapped_size, size, m_name); +@@ -895,13 +906,16 @@ UCS_TEST_F(malloc_hook_cplusplus, new_delete) { + std::vector vec3(size, 0); + } + ++#ifdef __linux__ + malloc_trim(0); ++#endif + + EXPECT_GE(m_unmapped_size, size); + + unset(); + } + ++#ifdef __linux__ + UCS_TEST_SKIP_COND_F(malloc_hook_cplusplus, dynamic_mmap_enable, + RUNNING_ON_VALGRIND || skip_on_bistro()) { + EXPECT_TRUE(ucm_global_opts.enable_dynamic_mmap_thresh); +@@ -1044,6 +1058,7 @@ UCS_TEST_SKIP_COND_F(malloc_hook_cplusplus, mmap_ptrs, + unset(); + + } ++#endif + + UCS_TEST_F(malloc_hook_cplusplus, remap_override_single_thread) { + pthread_barrier_t barrier; diff --git a/net/ucx/files/patch-test_gtest_ucp_test__ucp__wakeup.cc b/net/ucx/files/patch-test_gtest_ucp_test__ucp__wakeup.cc new file mode 100644 index 000000000000..5426fa1d5fe0 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucp_test__ucp__wakeup.cc @@ -0,0 +1,53 @@ +--- test/gtest/ucp/test_ucp_wakeup.cc.orig 2026-05-07 22:24:17 UTC ++++ test/gtest/ucp/test_ucp_wakeup.cc +@@ -7,7 +7,11 @@ + #include "ucp_test.h" + + #include ++#ifdef __linux__ + #include ++#else ++#include ++#endif + #include + + +@@ -195,7 +199,11 @@ class test_ucp_wakeup_external_epollfd : public test_u + static void* const USER_DATA; + + virtual void init() { ++#ifdef __linux__ + m_epfd = epoll_create(1); ++#else ++ m_epfd = kqueue(); ++#endif + ASSERT_GE(m_epfd, 0); + test_ucp_wakeup::init(); + } +@@ -248,6 +256,7 @@ UCS_TEST_P(test_ucp_wakeup_external_epollfd, epoll_wai + } + ASSERT_UCS_OK(status); + ++#ifdef __linux__ + struct epoll_event event; + int ret; + do { +@@ -258,6 +267,18 @@ UCS_TEST_P(test_ucp_wakeup_external_epollfd, epoll_wai + } + ASSERT_EQ(1, ret); + EXPECT_EQ(USER_DATA, event.data.ptr); ++#else ++ struct kevent event; ++ int ret; ++ do { ++ ret = kevent(m_epfd, NULL, 0, &event, 1, NULL); ++ } while ((ret < 0) && (errno == EINTR)); ++ if (ret < 0) { ++ UCS_TEST_MESSAGE << "kevent() failed: " << strerror(errno); ++ } ++ ASSERT_EQ(1, ret); ++ EXPECT_EQ(USER_DATA, event.udata); ++#endif + } + + ucp_request_release(req); diff --git a/net/ucx/files/patch-test_gtest_ucs_test__algorithm.cc b/net/ucx/files/patch-test_gtest_ucs_test__algorithm.cc new file mode 100644 index 000000000000..9454d62d47a3 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucs_test__algorithm.cc @@ -0,0 +1,14 @@ +--- test/gtest/ucs/test_algorithm.cc.orig 2026-05-10 22:50:36 UTC ++++ test/gtest/ucs/test_algorithm.cc +@@ -41,9 +41,9 @@ UCS_TEST_F(test_algorithm, qsort_r) { + } + + std::vector vec2 = vec; +- qsort(&vec2[0], nmemb, sizeof(int), compare_func); ++ qsort(vec2.data(), nmemb, sizeof(int), compare_func); + +- ucs_qsort_r(&vec[0], nmemb, sizeof(int), compare_func_r, MAGIC); ++ ucs_qsort_r(vec.data(), nmemb, sizeof(int), compare_func_r, MAGIC); + ASSERT_EQ(vec2, vec); + } + } diff --git a/net/ucx/files/patch-test_gtest_ucs_test__async.cc b/net/ucx/files/patch-test_gtest_ucs_test__async.cc new file mode 100644 index 000000000000..e10d275c44d2 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucs_test__async.cc @@ -0,0 +1,11 @@ +--- test/gtest/ucs/test_async.cc.orig 2026-06-08 19:48:30 UTC ++++ test/gtest/ucs/test_async.cc +@@ -544,7 +544,7 @@ UCS_TEST_P(test_async, many_timers) { + const int max_timers = ucs_max(10, 250 / ucs::test_time_multiplier()); + + std::vector timers; +- timers.reserve(max_timers); ++ timers.resize(max_timers); + + for (int count = 0; count < max_iters; ++count) { + for (int count2 = 0; count2 < max_timers; ++count2) { diff --git a/net/ucx/files/patch-test_gtest_ucs_test__config.cc b/net/ucx/files/patch-test_gtest_ucs_test__config.cc new file mode 100644 index 000000000000..e421a5b37e21 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucs_test__config.cc @@ -0,0 +1,62 @@ +--- test/gtest/ucs/test_config.cc.orig 2026-02-05 12:41:56 UTC ++++ test/gtest/ucs/test_config.cc +@@ -365,22 +365,18 @@ class test_config : public ucs::test { (protected) + std::string + dump(ucs_config_print_flags_t flags, const char *filter = nullptr) const + { +- char *dump_data = nullptr; ++ char *dump_data = nullptr; + size_t dump_size; +- char line_buf[1024]; + std::string res; + + FILE *file = open_memstream(&dump_data, &dump_size); + ucs_config_parser_print_opts(file, "", &m_opts, car_opts_table, + nullptr, UCS_DEFAULT_ENV_PREFIX, flags, + filter); +- fseek(file, 0, SEEK_SET); +- +- while (fgets(line_buf, sizeof(line_buf), file)) { +- res += line_buf; +- } +- + fclose(file); ++ if (dump_data != nullptr) { ++ res = std::string(dump_data, dump_size); ++ } + free(dump_data); + return res; + } +@@ -432,12 +428,19 @@ class test_config : public ucs::test { (protected) + ucs_config_parser_print_opts(file, "", *opts, car_opts_table, prefix, + UCS_DEFAULT_ENV_PREFIX, + (ucs_config_print_flags_t)flags, nullptr); +- ++ fclose(file); + /* Sanity check - all lines begin with UCS_ */ + unsigned num_lines = 0; +- fseek(file, 0, SEEK_SET); +- while (fgets(line_buf, sizeof(line_buf), file)) { +- if (line_buf[0] == '\n') { ++ char *pos = dump_data; ++ char *end = dump_data + dump_size; ++ while (pos < end) { ++ char *nl = (char*)memchr(pos, '\n', end - pos); ++ size_t len = nl ? (size_t)(nl - pos) : (size_t)(end - pos); ++ if (len >= sizeof(line_buf)) len = sizeof(line_buf) - 1; ++ memcpy(line_buf, pos, len); ++ line_buf[len] = '\0'; ++ pos = nl ? nl + 1 : end; ++ if (line_buf[0] == '\n'|| line_buf[0] == '\0') { + continue; + } + +@@ -465,7 +468,7 @@ class test_config : public ucs::test { (protected) + + size_t cnt = 0; + for (size_t i = 2 + strlen("alias of: ") + 1; +- line_buf[i] != '\n'; i++) { ++ line_buf[i] != '\n' && line_buf[i] != '\0'; i++) { + alias[cnt++] = line_buf[i]; + } + } diff --git a/net/ucx/files/patch-test_gtest_ucs_test__debug.cc b/net/ucx/files/patch-test_gtest_ucs_test__debug.cc index 45d9f13aff89..adebbc2366b8 100644 --- a/net/ucx/files/patch-test_gtest_ucs_test__debug.cc +++ b/net/ucx/files/patch-test_gtest_ucs_test__debug.cc @@ -1,22 +1,10 @@ ---- test/gtest/ucs/test_debug.cc.orig 2026-02-04 09:52:47 UTC +--- test/gtest/ucs/test_debug.cc.orig 2026-05-07 22:42:39 UTC +++ test/gtest/ucs/test_debug.cc @@ -11,6 +11,7 @@ extern "C" { #include } +#include #include extern "C" { -@@ -24,7 +25,10 @@ std::string __basename(const std::string& path) { - - std::string __basename(const std::string& path) { - char *p = strdup(path.c_str()); -- std::string bn(::basename(p)); -+ /* basename() may modify its argument on some platforms */ -+ char *path = strdup(p); -+ std::string bn(::basename(path)); -+ free(path); - free(p); - return bn; - } diff --git a/net/ucx/files/patch-test_gtest_ucs_test__event__set.cc b/net/ucx/files/patch-test_gtest_ucs_test__event__set.cc new file mode 100644 index 000000000000..9c60619ac3b8 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucs_test__event__set.cc @@ -0,0 +1,28 @@ +--- test/gtest/ucs/test_event_set.cc.orig 2026-02-04 09:52:47 UTC ++++ test/gtest/ucs/test_event_set.cc +@@ -8,7 +8,11 @@ extern "C" { + extern "C" { + #include + #include ++#ifdef __linux__ + #include ++#else ++#include ++#endif + } + + #define MAX_BUF_LEN 255 +@@ -40,8 +44,12 @@ class test_event_set : public ucs::test_base, (protect + protected: + void init() { + if (GetParam() & UCS_EVENT_SET_EXTERNAL_FD) { ++#ifdef __linux__ + m_ext_fd = epoll_create(1); +- ASSERT_TRUE(m_ext_fd > 0); ++#else ++ m_ext_fd = kqueue(); ++#endif ++ ASSERT_TRUE(m_ext_fd > 0); + } else { + m_ext_fd = -1; + } diff --git a/net/ucx/files/patch-test_gtest_ucs_test__profile.cc b/net/ucx/files/patch-test_gtest_ucs_test__profile.cc new file mode 100644 index 000000000000..95f5e3739a5b --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucs_test__profile.cc @@ -0,0 +1,20 @@ +--- test/gtest/ucs/test_profile.cc.orig 2026-02-04 09:52:47 UTC ++++ test/gtest/ucs/test_profile.cc +@@ -13,6 +13,7 @@ extern "C" { + #include + } + ++#include + #include + #include + +@@ -235,7 +236,8 @@ void test_profile::test_locations(const ucs_profile_lo + std::set loc_names; + for (unsigned i = 0; i < num_locations; ++i) { + const ucs_profile_location_t *loc = &locations[i]; +- EXPECT_EQ(std::string(basename(__FILE__)), std::string(loc->file)); ++ char file_copy[] = __FILE__; ++ EXPECT_EQ(std::string(basename(file_copy)), std::string(loc->file)); + EXPECT_GE(loc->line, MIN_LINE); + EXPECT_LE(loc->line, MAX_LINE); + loc_names.insert(loc->name); diff --git a/net/ucx/files/patch-test_gtest_ucs_test__sock.cc b/net/ucx/files/patch-test_gtest_ucs_test__sock.cc new file mode 100644 index 000000000000..5e0d1bac2407 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_ucs_test__sock.cc @@ -0,0 +1,21 @@ +--- test/gtest/ucs/test_sock.cc.orig 2026-02-04 09:52:47 UTC ++++ test/gtest/ucs/test_sock.cc +@@ -102,7 +102,6 @@ UCS_TEST_F(test_socket, sockaddr_sizeof) { + struct sockaddr *saddr = (struct sockaddr*)&ss; + size_t size; + +- + /* Check with IPv4 */ + { + size = 0; +@@ -551,6 +550,10 @@ UCS_TEST_F(test_socket, socket_setopt) { + level = SOL_SOCKET; + optname = SO_REUSEADDR; + optval = 1; ++ ++#if defined(__FreeBSD__) ++ UCS_TEST_SKIP_R("IPPROTO_TCP/SO_REUSEADDR returns success on FreeBSD"); ++#endif + + status = ucs_socket_setopt(fd, level, optname, &optval, optlen); + EXPECT_UCS_OK(status); diff --git a/net/ucx/files/patch-test_gtest_uct_test__md.cc b/net/ucx/files/patch-test_gtest_uct_test__md.cc new file mode 100644 index 000000000000..9401c6fea420 --- /dev/null +++ b/net/ucx/files/patch-test_gtest_uct_test__md.cc @@ -0,0 +1,10 @@ +--- test/gtest/uct/test_md.cc.orig 2026-05-07 22:05:14 UTC ++++ test/gtest/uct/test_md.cc +@@ -21,6 +21,7 @@ extern "C" { + #include + #endif + } ++#include + #include + #include + #include diff --git a/net/ucx/files/patch-test_gtest_uct_test__p2p__rma.cc b/net/ucx/files/patch-test_gtest_uct_test__p2p__rma.cc new file mode 100644 index 000000000000..f34cae71891c --- /dev/null +++ b/net/ucx/files/patch-test_gtest_uct_test__p2p__rma.cc @@ -0,0 +1,10 @@ +--- test/gtest/uct/test_p2p_rma.cc.orig 2026-05-07 22:05:47 UTC ++++ test/gtest/uct/test_p2p_rma.cc +@@ -6,6 +6,7 @@ + + #include "test_p2p_rma.h" + ++#include + #include + + diff --git a/net/ucx/files/patch-test_gtest_uct_uct__test.cc b/net/ucx/files/patch-test_gtest_uct_uct__test.cc index e27d655d7fdb..0586fff6a8ab 100644 --- a/net/ucx/files/patch-test_gtest_uct_uct__test.cc +++ b/net/ucx/files/patch-test_gtest_uct_uct__test.cc @@ -1,28 +1,29 @@ ---- test/gtest/uct/uct_test.cc.orig 2026-02-04 09:52:47 UTC +--- test/gtest/uct/uct_test.cc.orig 2026-05-06 13:47:14 UTC +++ test/gtest/uct/uct_test.cc -@@ -12,6 +12,7 @@ +@@ -12,6 +12,8 @@ #include #include #include +#include ++#include #include #ifdef HAVE_MALLOC_H #include -@@ -31,7 +32,7 @@ resource::resource() : component(NULL), dev_type(UCT_D +@@ -31,7 +33,7 @@ resource::resource() : component(NULL), dev_type(UCT_D sys_device(UCS_SYS_DEVICE_ID_UNKNOWN), variant(DEFAULT_VARIANT) { - CPU_ZERO(&local_cpus); + UCS_CPU_ZERO(&local_cpus); } resource::resource(uct_component_h component, const std::string& component_name, -@@ -385,7 +386,7 @@ void uct_test::set_cm_resources(std::vector& +@@ -385,7 +387,7 @@ void uct_test::set_cm_resources(std::vector& if (component_attr.flags & UCT_COMPONENT_FLAG_CM) { ucs_cpu_set_t local_cpus; - CPU_ZERO(&local_cpus); + UCS_CPU_ZERO(&local_cpus); uct_test::set_cm_sockaddr_resources(uct_components[cmpt_index], component_attr.name, local_cpus, all_resources); diff --git a/net/ucx/pkg-plist b/net/ucx/pkg-plist index 11e50f7e2d4e..6badef7bc065 100644 --- a/net/ucx/pkg-plist +++ b/net/ucx/pkg-plist @@ -1,144 +1,139 @@ %%IODEMO%%bin/io_demo bin/ucx_info %%PERFTEST%%bin/ucx_perftest %%PERFTEST%%bin/ucx_perftest_daemon bin/ucx_read_profile +%%FUSE%%bin/ucx_vfs @sample %%ETCDIR%%/ucx.conf.sample include/ucm/api/ucm.h include/ucp/api/ucp.h include/ucp/api/ucp_compat.h include/ucp/api/ucp_def.h include/ucp/api/ucp_version.h include/ucp/api/device/ucp_device_impl.h include/ucp/api/device/ucp_device_types.h include/ucp/api/device/ucp_host.h include/ucs/sys/device_code.h include/uct/api/device/uct_device_impl.h include/uct/api/device/uct_device_types.h include/ucs/algorithm/crc.h include/ucs/algorithm/qsort_r.h include/ucs/algorithm/string_distance.h include/ucs/arch/aarch64/bitops.h include/ucs/arch/aarch64/global_opts.h include/ucs/arch/atomic.h include/ucs/arch/bitops.h include/ucs/arch/generic/atomic.h include/ucs/arch/global_opts.h include/ucs/arch/ppc64/bitops.h include/ucs/arch/ppc64/global_opts.h include/ucs/arch/rv64/bitops.h include/ucs/arch/rv64/global_opts.h include/ucs/arch/x86_64/atomic.h include/ucs/arch/x86_64/bitops.h include/ucs/arch/x86_64/global_opts.h include/ucs/async/async_fwd.h include/ucs/config/global_opts.h include/ucs/config/ini.h include/ucs/config/parser.h include/ucs/config/types.h include/ucs/datastruct/array.h include/ucs/datastruct/callbackq.h include/ucs/datastruct/callbackq_compat.h include/ucs/datastruct/hlist.h include/ucs/datastruct/khash.h include/ucs/datastruct/linear_func.h include/ucs/datastruct/list.h include/ucs/datastruct/mpool.h include/ucs/datastruct/mpool_set.h include/ucs/datastruct/pgtable.h include/ucs/datastruct/piecewise_func.h include/ucs/datastruct/queue_types.h include/ucs/datastruct/strided_alloc.h include/ucs/datastruct/string_buffer.h include/ucs/datastruct/string_set.h include/ucs/debug/debug.h include/ucs/debug/log_def.h include/ucs/debug/memtrack.h include/ucs/memory/memory_type.h include/ucs/memory/memtype_cache.h include/ucs/memory/numa.h include/ucs/memory/rcache.h include/ucs/profile/profile_defs.h include/ucs/profile/profile_off.h include/ucs/profile/profile_on.h include/ucs/stats/libstats.h include/ucs/stats/stats_fwd.h include/ucs/sys/compiler_def.h include/ucs/sys/event_set.h include/ucs/sys/math.h include/ucs/sys/preprocessor.h include/ucs/sys/sock.h include/ucs/sys/string.h include/ucs/sys/stubs.h include/ucs/sys/topo/base/topo.h include/ucs/sys/uid.h include/ucs/time/time_def.h include/ucs/type/class.h include/ucs/type/cpu_set.h include/ucs/type/init_once.h include/ucs/type/param.h include/ucs/type/spinlock.h include/ucs/type/status.h include/ucs/type/thread_mode.h include/ucs/vfs/base/vfs_cb.h include/ucs/vfs/base/vfs_obj.h include/uct/api/tl.h include/uct/api/uct.h include/uct/api/uct_def.h include/uct/api/version.h lib/cmake/ucx/ucx-config-version.cmake lib/cmake/ucx/ucx-config.cmake lib/cmake/ucx/ucx-targets.cmake lib/libucm.a lib/libucm.so lib/libucm.so.0 lib/libucm.so.0.0.0 lib/libucp.a lib/libucp.so lib/libucp.so.0 lib/libucp.so.0.0.0 lib/libucs.a lib/libucs.so lib/libucs.so.0 lib/libucs.so.0.0.0 lib/libucs_signal.a lib/libucs_signal.so lib/libucs_signal.so.0 lib/libucs_signal.so.0.0.0 lib/libuct.a lib/libuct.so lib/libuct.so.0 lib/libuct.so.0.0.0 %%IBVERBS%%lib/ucx/libuct_ib.a %%IBVERBS%%lib/ucx/libuct_ib.so %%IBVERBS%%lib/ucx/libuct_ib.so.0 %%IBVERBS%%lib/ucx/libuct_ib.so.0.0.0 +%%FUSE%%lib/ucx/libucs_fuse.a +%%FUSE%%lib/ucx/libucs_fuse.so +%%FUSE%%lib/ucx/libucs_fuse.so.0 +%%FUSE%%lib/ucx/libucs_fuse.so.0.0.0 %%UMAD%%lib/ucx/libucx_perftest_mad.a %%UMAD%%lib/ucx/libucx_perftest_mad.so %%UMAD%%lib/ucx/libucx_perftest_mad.so.0 %%UMAD%%lib/ucx/libucx_perftest_mad.so.0.0.0 +%%FUSE%%libdata/pkgconfig/ucx-fuse.pc %%IBVERBS%%libdata/pkgconfig/ucx-ib.pc libdata/pkgconfig/ucx-ucs.pc libdata/pkgconfig/ucx-uct.pc libdata/pkgconfig/ucx.pc -%%EXAMPLES%%%%DATADIR%%/examples/hello_world_util.h -%%EXAMPLES%%%%DATADIR%%/examples/ucp_client_server.c -%%EXAMPLES%%%%DATADIR%%/examples/ucp_hello_world.c -%%EXAMPLES%%%%DATADIR%%/examples/ucp_util.h -%%EXAMPLES%%%%DATADIR%%/examples/uct_hello_world.c %%PERFTEST%%%%DATADIR%%/perftest/README %%PERFTEST%%%%DATADIR%%/perftest/msg_pow2 %%PERFTEST%%%%DATADIR%%/perftest/msg_pow2_large %%PERFTEST%%%%DATADIR%%/perftest/test_types_ucp %%PERFTEST%%%%DATADIR%%/perftest/test_types_ucp_amo %%PERFTEST%%%%DATADIR%%/perftest/test_types_ucp_daemon %%PERFTEST%%%%DATADIR%%/perftest/test_types_ucp_rma %%PERFTEST%%%%DATADIR%%/perftest/test_types_uct %%PERFTEST%%%%DATADIR%%/perftest/transports %%PERFTEST%%%%DATADIR%%/perftest/test_types_ucp_device_cuda -%%FUSE%%bin/ucx_vfs -%%FUSE%%lib/ucx/libucs_fuse.a -%%FUSE%%lib/ucx/libucs_fuse.so -%%FUSE%%lib/ucx/libucs_fuse.so.0 -%%FUSE%%lib/ucx/libucs_fuse.so.0.0.0 -%%FUSE%%libdata/pkgconfig/ucx-fuse.pc