net/ucx: Unified Communication X for high-performance messaging

UCX (Unified Communication X) is a high-performance communication framework
for modern HPC and data-intensive workloads. It provides low-latency,
high-bandwidth messaging and remote-memory-access primitives across a wide
range of transports, including shared memory, TCP/IP, and RDMA-capable
interconnects such as InfiniBand and RoCE (when supported by the platform).

UCX is commonly used as a communication substrate for MPI, OpenSHMEM, and
other distributed runtimes. It exposes a set of layered APIs (UCP/UCT/UCS/UCM)
to balance portability and performance while enabling optimized transport
selection, rendezvous protocols, and progress models.

PR:		292889
This commit is contained in:
GenericRikka
2026-02-18 14:02:58 +01:00
committed by Robert Clausecker
parent 30f8f24960
commit 294f65945a
49 changed files with 2489 additions and 0 deletions
+1
View File
@@ -1633,6 +1633,7 @@
SUBDIR += turnserver
SUBDIR += u6rd
SUBDIR += ucarp
SUBDIR += ucx
SUBDIR += udp-over-tcp
SUBDIR += udpbroadcastrelay
SUBDIR += udptunnel
+66
View File
@@ -0,0 +1,66 @@
PORTNAME= ucx
DISTVERSION= 1.20.0
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/
LICENSE= BSD3CLAUSE
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
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-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
.include <bsd.port.mk>
+3
View File
@@ -0,0 +1,3 @@
TIMESTAMP = 1771060207
SHA256 (ucx-1.20.0.tar.gz) = 7c8a6093cada179aa1d851b83625e3b25ed5658966e309de5118c27a038c7ef9
SIZE (ucx-1.20.0.tar.gz) = 3500736
+13
View File
@@ -0,0 +1,13 @@
--- Makefile.am.orig 2026-02-05 12:41:56 UTC
+++ Makefile.am
@@ -59,8 +59,10 @@ SUBDIRS += \
cmake \
config
+if BUILD_GTEST
if HAVE_GTEST
SUBDIRS += test/gtest
+endif
endif
if HAVE_MPICC
+33
View File
@@ -0,0 +1,33 @@
--- config/m4/ucm.m4.orig 2026-02-04 09:52:46 UTC
+++ config/m4/ucm.m4
@@ -15,11 +15,18 @@ AC_ARG_WITH([allocator],
[],
[with_allocator=ptmalloc286])
+AC_CHECK_FUNCS([brk sbrk], [], [], [#include <unistd.h>])
+
+HAVE_UCM_PTMALLOC286=no
+
case ${with_allocator} in
ptmalloc286)
AC_MSG_NOTICE(Memory allocator is ptmalloc-2.8.6 version)
- AC_DEFINE([HAVE_UCM_PTMALLOC286], 1, [Use ptmalloc-2.8.6 version])
- HAVE_UCM_PTMALLOC286=yes
+ AS_IF([test "x$ac_cv_func_brk" = "xyes" && test "x$ac_cv_func_sbrk" = "xyes"],
+ [AC_DEFINE([HAVE_UCM_PTMALLOC286], 1, [Use ptmalloc-2.8.6 version])
+ HAVE_UCM_PTMALLOC286=yes],
+ [AC_MSG_WARN([brk()/sbrk() not available; disabling ptmalloc286 allocator])
+ HAVE_UCM_PTMALLOC286=no])
;;
*)
AC_MSG_ERROR(Cannot continue. Unsupported memory allocator name
@@ -83,6 +90,9 @@ AS_IF([test "x$mmap_hooks_happy" = "xyes"],
AS_IF([test "x$mmap_hooks_happy" = "xyes"],
AS_IF([test "x$ipc_hooks_happy" = "xyes" -o "x$shm_hooks_happy" = "xyes"],
[bistro_hooks_happy=yes]))
+
+AS_IF([test "x$ac_cv_func_brk" != "xyes" -o "x$ac_cv_func_sbrk" != "xyes"],
+ [bistro_hooks_happy=no])
AS_IF([test "x$bistro_hooks_happy" = "xyes"],
[AC_DEFINE([UCM_BISTRO_HOOKS], [1], [Enable BISTRO hooks])],
+108
View File
@@ -0,0 +1,108 @@
--- configure.ac.orig 2026-02-05 12:41:56 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_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, "<unknown>")
- AC_SUBST(SCM_VERSION, "0000000")])
+AC_PATH_PROG([GIT], [git], [:])
+SCM_BRANCH="<unknown>"
+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],
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])
+], [
+ 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
@@ -0,0 +1,15 @@
--- src/tools/info/Makefile.am.orig 2026-02-04 09:52:46 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)
@@ -0,0 +1,16 @@
--- src/tools/perf/mad/perftest_mad.c.orig 2026-02-04 09:52:46 UTC
+++ src/tools/perf/mad/perftest_mad.c
@@ -20,7 +20,13 @@
#include <unistd.h>
#include <netdb.h>
#include <sys/poll.h>
+#if defined(__linux__)
#include <linux/types.h> /* __be64 */
+#else
+#include <sys/types.h>
+#include <sys/endian.h> /* be64toh */
+typedef uint64_t __be64;
+#endif
#include <infiniband/mad.h>
#include <infiniband/umad.h>
+50
View File
@@ -0,0 +1,50 @@
--- src/ucm/Makefile.am.orig 2026-02-04 09:52:46 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 = \
bistro/bistro_ppc64.c \
bistro/bistro_rv64.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
+18
View File
@@ -0,0 +1,18 @@
--- src/ucm/event/event.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/event/event.c
@@ -36,6 +36,15 @@ KHASH_INIT(ucm_ptr_size, const void*, size_t, 1, ucm_p
#define ucm_ptr_hash(_ptr) kh_int64_hash_func((uintptr_t)(_ptr))
KHASH_INIT(ucm_ptr_size, const void*, size_t, 1, ucm_ptr_hash, kh_int64_hash_equal)
+#if defined(__FreeBSD__)
+#ifndef MREMAP_FIXED
+#define MREMAP_FIXED 0
+#endif
+#ifndef MREMAP_MAYMOVE
+#define MREMAP_MAYMOVE 0
+#endif
+#endif
+
static pthread_rwlock_t ucm_event_lock = PTHREAD_RWLOCK_INITIALIZER;
static ucs_init_once_t ucm_library_init_once = UCS_INIT_ONCE_INITIALIZER;
static ucs_list_link_t ucm_event_handlers;
@@ -0,0 +1,28 @@
--- src/ucm/malloc/brk_sbrk_override_stub.c.orig 2026-02-20 03:25:07 UTC
+++ src/ucm/malloc/brk_sbrk_override_stub.c
@@ -0,0 +1,25 @@
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+/*
+ * Stubs for platforms/builds where we don't implement brk/sbrk overriding.
+ * Fail gracefully so callers can fall back or treat as unsupported.
+ *
+ * Marked weak so a real implementation (if later added) can override it.
+ */
+__attribute__((weak))
+int ucm_override_brk(void *addr)
+{
+ (void)addr;
+ errno = ENOSYS;
+ return -1;
+}
+
+__attribute__((weak))
+void *ucm_override_sbrk(intptr_t increment)
+{
+ (void)increment;
+ errno = ENOSYS;
+ return (void*)-1;
+}
@@ -0,0 +1,35 @@
--- src/ucm/malloc/malloc_hook.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/malloc/malloc_hook.c
@@ -35,6 +35,12 @@
#include <ucs/sys/sys.h>
#include <ucs/type/spinlock.h>
+#if defined(__FreeBSD__)
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
#include <netdb.h>
@@ -45,7 +51,6 @@
#define UCM_MALLOC_INSTALLED_OPT_SYMS UCS_BIT(2) /* Installed optional symbols */
#define UCM_MALLOC_INSTALLED_MALL_SYMS UCS_BIT(3) /* Installed malloc symbols */
-
/* Mangled symbols of C++ allocators */
#define UCM_OPERATOR_NEW_SYMBOL "_Znwm"
#define UCM_OPERATOR_DELETE_SYMBOL "_ZdlPv"
@@ -659,7 +664,11 @@ static void ucm_malloc_populate_glibc_cache()
static void ucm_malloc_populate_glibc_cache()
{
+#if defined(__FreeBSD__)
+ static char hostname[UCS_HOST_NAME_MAX] = {0};
+#else
char hostname[HOST_NAME_MAX];
+#endif
/* Trigger NSS initialization before we install malloc hooks.
* This is needed because NSS could allocate strings with our malloc(), but
@@ -0,0 +1,58 @@
--- src/ucm/malloc/malloc_hook_stub.c.orig 2026-02-20 02:50:52 UTC
+++ src/ucm/malloc/malloc_hook_stub.c
@@ -0,0 +1,55 @@
+/*
+ * FreeBSD / non-glibc stub for UCX malloc hook support.
+ *
+ * This file provides the public API declared in malloc_hook.h, but does not
+ * attempt to install malloc hooks, relocate symbols, or tweak mallopt-style
+ * thresholds. Those mechanisms are glibc/ptmalloc-centric.
+ *
+ * The goal for now: link cleanly, behave safely, and fail gracefully when
+ * malloc hooking is actually required.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "malloc_hook.h"
+
+#include <ucm/util/log.h>
+#include <ucs/sys/compiler.h>
+
+ucs_status_t ucm_malloc_install(int events)
+{
+ static int warned = 0;
+
+ /* We don't implement malloc hook installation on this platform (yet). */
+ if (!warned) {
+ ucm_debug("ucm_malloc_install(events=0x%x): stub (malloc hooks not supported on this build)",
+ events);
+ warned = 1;
+ }
+
+ /*
+ * Conservative choice:
+ * - Return UNSUPPORTED so callers that *need* these hooks can fall back
+ * or disable the feature.
+ *
+ * If you find a call site that expects OK unconditionally, we can make this
+ * conditional (e.g., return OK when events==0), but UNSUPPORTED is the honest
+ * default.
+ */
+ return (events == 0) ? UCS_OK : UCS_ERR_UNSUPPORTED;
+}
+
+void ucm_init_malloc_hook(void)
+{
+ /* No-op for stub. */
+}
+
+void ucm_malloc_state_reset(int default_mmap_thresh, int default_trim_thresh)
+{
+ (void)default_mmap_thresh;
+ (void)default_trim_thresh;
+
+ /* No-op for stub (no mallopt-style tuning here). */
+}
@@ -0,0 +1,55 @@
--- src/ucm/mmap/install.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/mmap/install.c
@@ -86,8 +86,10 @@ static ucm_mmap_func_t ucm_mmap_funcs[] = {
#endif
{ UCM_MMAP_RELOC_ENTRY(shmat), UCM_EVENT_SHMAT, UCM_EVENT_NONE},
{ UCM_MMAP_RELOC_ENTRY(shmdt), UCM_EVENT_SHMDT, UCM_EVENT_SHMAT},
+#ifdef HAVE_BRK_SBRK
{ UCM_MMAP_RELOC_ENTRY(sbrk), UCM_EVENT_SBRK, UCM_EVENT_NONE},
{ UCM_MMAP_RELOC_ENTRY(brk), UCM_EVENT_BRK, UCM_EVENT_NONE},
+#endif
{ UCM_MMAP_RELOC_ENTRY(madvise), UCM_EVENT_MADVISE, UCM_EVENT_NONE},
{ {NULL, NULL, NULL}, UCM_EVENT_NONE}
};
@@ -135,6 +137,7 @@ static void ucm_mmap_event_test_callback(ucm_event_typ
}
}
+#ifdef HAVE_BRK_SBRK
/* Call brk() and check return value, to avoid compile error of unused result */
static void ucm_brk_checked(void *addr)
{
@@ -143,6 +146,7 @@ static void ucm_brk_checked(void *addr)
ucm_diag("brk(addr=%p) failed: %m", addr);
}
}
+#endif
/* Fire events with pre/post action. The problem is in call sequence: we
* can't just fire single event - most of the system calls require set of
@@ -199,6 +203,7 @@ ucm_fire_mmap_events_internal(int events, ucm_mmap_tes
}
if (exclusive && !RUNNING_ON_VALGRIND) {
+#ifdef HAVE_BRK_SBRK
sbrk_size = ucm_get_page_size();
if (events & (UCM_EVENT_BRK|UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED)) {
p = ucm_get_current_brk();
@@ -213,14 +218,17 @@ ucm_fire_mmap_events_internal(int events, ucm_mmap_tes
UCM_FIRE_EVENT(events, UCM_EVENT_SBRK|UCM_EVENT_VM_UNMAPPED,
data, (void)sbrk(-sbrk_size));
}
+#endif
} else {
/* To avoid side effects on other threads and valgrind heap corruption,
* pass invalid parameters. We assume that if the natives events are
* delivered, it means VM_MAPPED/UNMAPPED would be delivered as well.
*/
+#ifdef HAVE_BRK_SBRK
if (events & UCM_EVENT_BRK) {
UCM_FIRE_EVENT(events, UCM_EVENT_BRK, data, ucm_brk_checked(NULL));
}
+#endif
}
if (events & (UCM_EVENT_MADVISE|UCM_EVENT_VM_UNMAPPED)) {
+40
View File
@@ -0,0 +1,40 @@
--- src/ucm/util/log.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/util/log.c
@@ -13,6 +13,7 @@
#include <ucs/sys/compiler.h>
#include <ucs/sys/string.h>
+#include <ucs/sys/sys.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
@@ -23,12 +24,21 @@
#include <ctype.h>
#include <errno.h>
#include <limits.h>
+#if defined(__FreeBSD__)
+#include <sys/thr.h>
+#include <sys/syscall.h>
+#else
#include <syscall.h>
+#endif
#define UCM_LOG_BUF_SIZE 512
static int ucm_log_fileno = 1; /* stdout */
+#if defined(__FreeBSD__)
+static char ucm_log_hostname[UCS_HOST_NAME_MAX] = {0};
+#else
static char ucm_log_hostname[HOST_NAME_MAX] = {0};
+#endif
const char *ucm_log_level_names[] = {
[UCS_LOG_LEVEL_FATAL] = "FATAL",
@@ -47,7 +57,6 @@ const char *ucm_log_level_names[] = {
#define UCM_LOG_LTOA_FLAG_LONG UCS_BIT(2) /* long number */
#define UCM_LOG_LTOA_FLAG_PAD0 UCS_BIT(3) /* pad with zeroes */
#define UCM_LOG_LTOA_PAD_LEFT UCS_BIT(4) /* pad to left */
-
static char *ucm_log_add_padding(char *p, char *end, int pad, char fill)
{
+18
View File
@@ -0,0 +1,18 @@
--- src/ucm/util/reloc.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/util/reloc.c
@@ -673,10 +673,13 @@ static int ucm_dlclose(void *handle)
* cached information anyway, and it may be re-added on the next call to
* ucm_reloc_apply_patch().
*/
- dl_name = ucm_reloc_get_dl_name(lm_entry->l_name, lm_entry->l_addr,
+ ElfW(Addr) dlpi_addr;
+ dlpi_addr = (ElfW(Addr))(uintptr_t)lm_entry->l_addr;
+
+ dl_name = ucm_reloc_get_dl_name(lm_entry->l_name, dlpi_addr,
dl_name_buffer, sizeof(dl_name_buffer));
pthread_mutex_lock(&ucm_reloc_patch_list_lock);
- ucm_reloc_dl_info_cleanup(lm_entry->l_addr, dl_name);
+ ucm_reloc_dl_info_cleanup(dlpi_addr, dl_name);
pthread_mutex_unlock(&ucm_reloc_patch_list_lock);
}
@@ -0,0 +1,68 @@
--- src/ucm/util/replace.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/util/replace.c
@@ -55,8 +55,10 @@ UCM_DEFINE_REPLACE_FUNC(shmdt, int, -1, co
#endif
UCM_DEFINE_REPLACE_FUNC(shmat, void*, MAP_FAILED, int, const void*, int)
UCM_DEFINE_REPLACE_FUNC(shmdt, int, -1, const void*)
+#ifdef HAVE_BRK_SBRK
UCM_DEFINE_REPLACE_FUNC(sbrk, void*, MAP_FAILED, intptr_t)
UCM_DEFINE_REPLACE_FUNC(brk, int, -1, void*)
+#endif
UCM_DEFINE_REPLACE_FUNC(madvise, int, -1, void*, size_t, int)
UCM_DEFINE_SELECT_FUNC(mmap, void*, SYS_mmap, void*, size_t, int, int, int,
@@ -122,6 +124,7 @@ int ucm_orig_shmdt(const void *shmaddr)
#endif
+#ifdef HAVE_BRK_SBRK
_UCM_DEFINE_DLSYM_FUNC(brk, ucm_orig_dlsym_brk, ucm_override_brk, int, void*)
int ucm_orig_brk(void *addr)
@@ -156,7 +159,32 @@ void *ucm_orig_sbrk(intptr_t increment)
(void*)-1 : prev;
}
}
+#else
+int ucm_orig_brk(void *addr)
+{
+ (void)addr;
+ errno = ENOSYS;
+ return -1;
+}
+void *ucm_orig_sbrk(intptr_t increment)
+{
+ (void)increment;
+ errno = ENOSYS;
+ return MAP_FAILED;
+}
+
+int ucm_override_brk(void *addr)
+{
+ return ucm_orig_brk(addr);
+}
+
+void *ucm_override_sbrk(intptr_t increment)
+{
+ return ucm_orig_sbrk(increment);
+}
+#endif
+
#else /* UCM_BISTRO_HOOKS */
UCM_DEFINE_DLSYM_FUNC(brk, int, void*)
@@ -168,9 +196,13 @@ void *ucm_get_current_brk()
void *ucm_get_current_brk()
{
+#ifdef HAVE_BRK_SBRK
#if HAVE___CURBRK
return __curbrk;
#else
return ucm_brk_syscall(0);
+#endif
+#else
+ return NULL;
#endif
}
+103
View File
@@ -0,0 +1,103 @@
--- src/ucm/util/sys.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/util/sys.c
@@ -21,10 +21,17 @@
#include <ucs/type/init_once.h>
#include <ucs/sys/math.h>
#include <ucs/sys/ptr_arith.h>
+#ifdef HAVE_LINUX_MMAN_H
#include <linux/mman.h>
+#endif
#include <sys/mman.h>
#include <pthread.h>
+#ifdef __linux__
#include <syscall.h>
+#elif defined(__FreeBSD__)
+#include <sys/syscall.h>
+#include <sys/thr.h>
+#endif
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
@@ -34,6 +41,24 @@
#define UCM_PROC_SELF_MAPS "/proc/self/maps"
+#if !defined(__linux__)
+#include <errno.h>
+#include <sys/mman.h>
+
+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)
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)
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()
+11
View File
@@ -0,0 +1,11 @@
--- src/ucm/util/sys.h.orig 2026-02-04 09:52:46 UTC
+++ src/ucm/util/sys.h
@@ -108,7 +108,7 @@ void *ucm_brk_syscall(void *addr);
/**
* @return System thread id of the current thread.
*/
-pid_t ucm_get_tid();
+pid_t ucm_get_tid(void);
/**
@@ -0,0 +1,127 @@
--- 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 <errno.h>
+
#include "ucp_am.h"
#include "ucp_ep_vfs.h"
#include "ucp_worker.h"
@@ -35,9 +37,15 @@
#include <ucs/vfs/base/vfs_cb.h>
#include <ucs/vfs/base/vfs_obj.h>
#include <sys/poll.h>
-#include <sys/eventfd.h>
-#include <sys/epoll.h>
-#include <sys/timerfd.h>
+#if defined(HAVE_SYS_EVENTFD_H)
+# include <sys/eventfd.h>
+#endif
+#if defined(HAVE_SYS_TIMERFD_H)
+# include <sys/timerfd.h>
+#endif
+#if defined(__linux__)
+# include <sys/epoll.h>
+#endif
#include <time.h>
@@ -320,6 +328,7 @@ static ucs_status_t ucp_worker_wakeup_init(ucp_worker_
worker->flags |= UCP_WORKER_FLAG_EDGE_TRIGGERED;
}
+#if 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_
}
ucp_worker_wakeup_ctl_fd(worker, UCP_WORKER_EPFD_OP_ADD, worker->eventfd);
+#else
+ /* No eventfd(). */
+ worker->eventfd = -1;
+#endif
worker->uct_events = 0;
@@ -427,6 +440,10 @@ static ucs_status_t ucp_worker_wakeup_signal_fd(ucp_wo
ucs_trace_func("worker=%p fd=%d", worker, worker->eventfd);
+ if (worker->eventfd == -1) {
+ return UCS_OK;
+ }
+
do {
ret = write(worker->eventfd, &dummy, sizeof(dummy));
if (ret == sizeof(dummy)) {
@@ -3375,7 +3392,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)
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)
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)
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)
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,
@@ -0,0 +1,10 @@
--- src/ucs/arch/aarch64/cpu.h.orig 2026-02-17 21:08:28 UTC
+++ src/ucs/arch/aarch64/cpu.h
@@ -15,6 +15,7 @@
#include <string.h>
#include <sys/times.h>
#include <ucs/sys/compiler_def.h>
+#include <ucs/sys/ptr_arith.h>
#include <ucs/arch/generic/cpu.h>
#include <ucs/sys/math.h>
#include <ucs/type/status.h>
@@ -0,0 +1,47 @@
--- src/ucs/async/signal.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/async/signal.c
@@ -220,15 +220,30 @@ static void ucs_async_signal_handler(int signo, siginf
case POLL_ERR:
case POLL_MSG:
case POLL_PRI:
+ {
+#if defined(__linux__)
ucs_trace_async("async signal handler called for fd %d", siginfo->si_fd);
ucs_async_dispatch_handlers(&siginfo->si_fd, 1,
ucs_signal_map_to_events(siginfo->si_code));
+#else
+ /*
+ * FreeBSD does not provide si_fd in siginfo_t for SIGIO-style delivery,
+ * so we can't know which fd triggered the signal here.
+ *
+ * Fallback: dispatch without a specific fd. UCX usually treats fd<0 as
+ * "dispatch all"
+ */
+ int fd = -1;
+ ucs_trace_async("async signal handler called (no si_fd on this platform)");
+ ucs_async_dispatch_handlers(&fd, 1, ucs_signal_map_to_events(siginfo->si_code));
+#endif
return;
default:
ucs_warn("signal handler called with unexpected event code %d, ignoring",
siginfo->si_code);
return;
}
+ }
}
static void ucs_async_signal_allow(int allow)
@@ -382,11 +397,13 @@ static ucs_status_t ucs_async_signal_add_event_fd(ucs_
/* Send signal when fd is ready */
ucs_trace_async("fcntl(F_STSIG, fd=%d, sig=%s)", event_fd,
ucs_signal_names[ucs_global_opts.async_signo]);
+#if defined(__linux__)
if (0 > fcntl(event_fd, F_SETSIG, ucs_global_opts.async_signo)) {
ucs_error("fcntl F_SETSIG failed: %m");
status = UCS_ERR_IO_ERROR;
goto err_remove_handler;
}
+#endif
/* Send the signal to the desired thread */
tid = ucs_async_signal_context_tid(async);
@@ -0,0 +1,54 @@
--- src/ucs/config/parser.c.orig 2026-02-05 12:41:56 UTC
+++ src/ucs/config/parser.c
@@ -25,6 +25,7 @@
#include <fnmatch.h>
#include <ctype.h>
#include <libgen.h>
+#include <signal.h>
/* width of titles in docstring */
@@ -693,6 +694,8 @@ int ucs_config_sscanf_signo(const char *buf, void *des
int ucs_config_sscanf_signo(const char *buf, void *dest, const void *arg)
{
char *endptr;
+ const char *name;
+ const char *name_nosig;
int signo;
signo = strtol(buf, &endptr, 10);
@@ -701,11 +704,31 @@ int ucs_config_sscanf_signo(const char *buf, void *des
return 1;
}
- if (!strncmp(buf, "SIG", 3)) {
- buf += 3;
+ name = buf;
+ if (!strncasecmp(name, "SIG", 3)) {
+ name_nosig = name + 3;
+ } else {
+ name_nosig = name;
}
- return ucs_config_sscanf_enum(buf, dest, ucs_signal_names);
+#if defined(__FreeBSD__)
+ for (signo = 1; signo < NSIG; ++signo) {
+ if ((sys_signame[signo] != NULL) &&
+ !strcasecmp(name_nosig, sys_signame[signo])) {
+ *(int*)dest = signo;
+ return 1;
+ }
+ }
+#endif
+
+ if (ucs_config_sscanf_enum(name_nosig, dest, ucs_signal_names)) {
+ return 1;
+ }
+ if (name_nosig != name) {
+ return ucs_config_sscanf_enum(name, dest, ucs_signal_names);
+ }
+
+ return 0;
}
int ucs_config_sprintf_signo(char *buf, size_t max,
+11
View File
@@ -0,0 +1,11 @@
--- src/ucs/debug/debug.c.orig 2026-01-12 18:10:14 UTC
+++ src/ucs/debug/debug.c
@@ -24,6 +24,8 @@
#include <dlfcn.h>
#include <link.h>
#include <dirent.h>
+#include <signal.h>
+#include <stdlib.h>
#ifdef HAVE_DETAILED_BACKTRACE
# include <bfd.h>
#endif /* HAVE_DETAILED_BACKTRACE */
+14
View File
@@ -0,0 +1,14 @@
--- src/ucs/debug/log.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/debug/log.c
@@ -78,7 +78,11 @@ static int __thread ucs_log_current_indent = 0;
static unsigned ucs_log_handlers_count = 0;
static int ucs_log_initialized = 0;
static int __thread ucs_log_current_indent = 0;
+#if defined(__FreeBSD__)
+static char ucs_log_hostname[UCS_HOST_NAME_MAX] = {0};
+#else
static char ucs_log_hostname[HOST_NAME_MAX] = {0};
+#endif
static int ucs_log_pid = 0;
static FILE *ucs_log_file = NULL;
static char *ucs_log_file_base_name = NULL;
+23
View File
@@ -0,0 +1,23 @@
--- src/ucs/memory/numa.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/memory/numa.c
@@ -20,6 +20,20 @@
#include <sched.h>
#include <dirent.h>
+#ifndef __CPU_SETSIZE
+# if defined(__FreeBSD__)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+# endif
+# if defined(CPU_SETSIZE)
+# define __CPU_SETSIZE CPU_SETSIZE
+# elif defined(MAXCPU)
+# define __CPU_SETSIZE MAXCPU
+# else
+# define __CPU_SETSIZE 1024
+# endif
+#endif
+
#define UCS_NUMA_MIN_DISTANCE 10
#define UCS_NUMA_NODE_MAX INT16_MAX
#define UCS_NUMA_CORE_DIR_PATH UCS_SYS_FS_CPUS_PATH "/cpu%d"
@@ -0,0 +1,17 @@
--- src/ucs/sys/compiler.h.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/sys/compiler.h
@@ -32,7 +32,13 @@
/* A function which should not be optimized */
#if defined(HAVE_ATTRIBUTE_NOOPTIMIZE) && (HAVE_ATTRIBUTE_NOOPTIMIZE == 1)
-#define UCS_F_NOOPTIMIZE __attribute__((optimize("O0")))
+#if defined(__clang__)
+# define UCS_F_NOOPTIMIZE __attribute__((optnone))
+#elif defined(__GNUC__)
+# define UCS_F_NOOPTIMIZE __attribute__((optimize("O0")))
+#else
+# define UCS_F_NOOPTIMIZE
+#endif
#else
#define UCS_F_NOOPTIMIZE
#endif
@@ -0,0 +1,232 @@
--- src/ucs/sys/event_set.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/sys/event_set.c
@@ -19,9 +19,14 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#if defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#else
#include <sys/epoll.h>
+#endif
-
enum {
UCS_SYS_EVENT_SET_EXTERNAL_EVENT_FD = UCS_BIT(0),
};
@@ -32,9 +37,46 @@ const unsigned ucs_sys_event_set_max_wait_events =
};
const unsigned ucs_sys_event_set_max_wait_events =
+#if defined(__FreeBSD__)
+ UCS_ALLOCA_MAX_SIZE / sizeof(struct kevent);
+#else
UCS_ALLOCA_MAX_SIZE / sizeof(struct epoll_event);
+#endif
+#if defined(__FreeBSD__)
+static inline int ucs_event_set_map_to_raw_flags(ucs_event_set_types_t events)
+{
+ /* Approximate edge-triggered behavior with EV_CLEAR */
+ return (events & UCS_EVENT_SET_EDGE_TRIGGERED) ? EV_CLEAR : 0;
+}
+
+static inline int ucs_event_set_map_to_events(const struct kevent *kev)
+{
+ ucs_event_set_types_t events = 0;
+
+ if (kev->filter == EVFILT_READ) {
+ events |= UCS_EVENT_SET_EVREAD;
+ } else if (kev->filter == EVFILT_WRITE) {
+ events |= UCS_EVENT_SET_EVWRITE;
+ }
+ if (kev->flags & EV_ERROR) {
+ events |= UCS_EVENT_SET_EVERR;
+ }
+ return events;
+}
+
+static int ucs_kqueue_ctl(int kq, int fd, int filter, int op_flags,
+ int fflags, intptr_t data, void *udata)
+{
+ struct kevent kev;
+ EV_SET(&kev, (uintptr_t)fd, filter, op_flags, fflags, data, udata);
+ if (kevent(kq, &kev, 1, NULL, 0, NULL) < 0) {
+ return -1;
+ }
+ return 0;
+}
+#else
static inline int ucs_event_set_map_to_raw_events(ucs_event_set_types_t events)
{
int raw_events = 0;
@@ -72,6 +114,7 @@ static inline int ucs_event_set_map_to_events(int raw_
}
return events;
}
+#endif
static ucs_sys_event_set_t *ucs_event_set_alloc(int event_fd, unsigned flags)
{
@@ -105,12 +148,21 @@ ucs_status_t ucs_event_set_create(ucs_sys_event_set_t
ucs_status_t status;
int event_fd;
+#if defined(__FreeBSD__)
+ /* Create kqueue set the thread will wait on */
+ event_fd = kqueue();
+ if (event_fd < 0) {
+ ucs_error("kqueue() failed: %m");
+ return UCS_ERR_IO_ERROR;
+ }
+#else
/* Create epoll set the thread will wait on */
event_fd = epoll_create(1);
if (event_fd < 0) {
ucs_error("epoll_create() failed: %m");
return UCS_ERR_IO_ERROR;
}
+#endif
*event_set_p = ucs_event_set_alloc(event_fd, 0);
if (*event_set_p == NULL) {
@@ -129,6 +181,26 @@ ucs_status_t ucs_event_set_add(ucs_sys_event_set_t *ev
ucs_event_set_types_t events,
void *callback_data)
{
+#if defined(__FreeBSD__)
+ int kq = event_set->event_fd;
+ int raw_flags = ucs_event_set_map_to_raw_flags(events);
+
+ if (events & UCS_EVENT_SET_EVREAD) {
+ if (ucs_kqueue_ctl(kq, fd, EVFILT_READ, EV_ADD | EV_ENABLE | raw_flags,
+ 0, 0, callback_data) < 0) {
+ ucs_error("kevent(kq=%d, ADD, fd=%d, READ) failed: %m", kq, fd);
+ return UCS_ERR_IO_ERROR;
+ }
+ }
+ if (events & UCS_EVENT_SET_EVWRITE) {
+ if (ucs_kqueue_ctl(kq, fd, EVFILT_WRITE, EV_ADD | EV_ENABLE | raw_flags,
+ 0, 0, callback_data) < 0) {
+ ucs_error("kevent(kq=%d, ADD, fd=%d, WRITE) failed: %m", kq, fd);
+ return UCS_ERR_IO_ERROR;
+ }
+ }
+ return UCS_OK;
+#else
struct epoll_event raw_event;
int ret;
@@ -144,12 +216,18 @@ ucs_status_t ucs_event_set_add(ucs_sys_event_set_t *ev
}
return UCS_OK;
+#endif
}
ucs_status_t ucs_event_set_mod(ucs_sys_event_set_t *event_set, int fd,
ucs_event_set_types_t events,
void *callback_data)
{
+#if defined(__FreeBSD__)
+ /* Simplest: delete then re-add with new mask */
+ (void)ucs_event_set_del(event_set, fd);
+ return ucs_event_set_add(event_set, fd, events, callback_data);
+#else
struct epoll_event raw_event;
int ret;
@@ -165,10 +243,28 @@ ucs_status_t ucs_event_set_mod(ucs_sys_event_set_t *ev
}
return UCS_OK;
+#endif
}
ucs_status_t ucs_event_set_del(ucs_sys_event_set_t *event_set, int fd)
{
+#if defined(__FreeBSD__)
+ int kq = event_set->event_fd;
+ int ret = 0;
+
+ /* Delete both filters; ignore ENOENT (not registered). */
+ if ((ucs_kqueue_ctl(kq, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL) < 0) &&
+ (errno != ENOENT)) {
+ ucs_error("kevent(kq=%d, DEL, fd=%d, READ) failed: %m", kq, fd);
+ ret = -1;
+ }
+ if ((ucs_kqueue_ctl(kq, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL) < 0) &&
+ (errno != ENOENT)) {
+ ucs_error("kevent(kq=%d, DEL, fd=%d, WRITE) failed: %m", kq, fd);
+ ret = -1;
+ }
+ return (ret < 0) ? UCS_ERR_IO_ERROR : UCS_OK;
+#else
int ret;
ret = epoll_ctl(event_set->event_fd, EPOLL_CTL_DEL, fd, NULL);
@@ -179,6 +275,7 @@ ucs_status_t ucs_event_set_del(ucs_sys_event_set_t *ev
}
return UCS_OK;
+#endif
}
ucs_status_t ucs_event_set_wait(ucs_sys_event_set_t *event_set,
@@ -186,6 +283,45 @@ ucs_status_t ucs_event_set_wait(ucs_sys_event_set_t *e
ucs_event_set_handler_t event_set_handler,
void *arg)
{
+#if defined(__FreeBSD__)
+ struct kevent *events;
+ int nready, i, io_events;
+ struct timespec ts, *tsp;
+
+ ucs_assert(event_set_handler != NULL);
+ ucs_assert(num_events != NULL);
+ ucs_assert(*num_events <= ucs_sys_event_set_max_wait_events);
+
+ events = ucs_alloca(sizeof(*events) * *num_events);
+
+ if (timeout_ms < 0) {
+ tsp = NULL;
+ } else {
+ ts.tv_sec = timeout_ms / 1000;
+ ts.tv_nsec = (timeout_ms % 1000) * 1000000;
+ tsp = &ts;
+ }
+
+ nready = kevent(event_set->event_fd, NULL, 0, events, *num_events, tsp);
+ if (ucs_unlikely(nready < 0)) {
+ *num_events = 0;
+ if (errno == EINTR) {
+ return UCS_INPROGRESS;
+ }
+ ucs_error("kevent() failed: %m");
+ return UCS_ERR_IO_ERROR;
+ }
+
+ ucs_assert(nready <= *num_events);
+
+ for (i = 0; i < nready; i++) {
+ io_events = ucs_event_set_map_to_events(&events[i]);
+ event_set_handler(events[i].udata, io_events, arg);
+ }
+
+ *num_events = nready;
+ return UCS_OK;
+#else
struct epoll_event *events;
int nready, i, io_events;
@@ -217,6 +353,7 @@ ucs_status_t ucs_event_set_wait(ucs_sys_event_set_t *e
*num_events = nready;
return UCS_OK;
+#endif
}
void ucs_event_set_cleanup(ucs_sys_event_set_t *event_set)
+50
View File
@@ -0,0 +1,50 @@
--- src/ucs/sys/netlink.c.orig 2026-02-05 12:41:56 UTC
+++ src/ucs/sys/netlink.c
@@ -8,6 +8,8 @@
#include "config.h"
#endif
+#if defined(__linux__)
+
#include "netlink.h"
#include <ucs/datastruct/khash.h>
@@ -310,3 +312,38 @@ int ucs_netlink_route_exists(int if_index, const struc
return info.found;
}
+#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.
+ */
+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)
+{
+ (void)if_index;
+ (void)sa_remote;
+ (void)allow_default_gw;
+ return 0;
+}
+
+#endif
+15
View File
@@ -0,0 +1,15 @@
--- src/ucs/sys/netlink.h.orig 2026-02-05 12:41:56 UTC
+++ src/ucs/sys/netlink.h
@@ -9,7 +9,12 @@
#include <ucs/type/status.h>
+#if defined(__linux__)
#include <linux/netlink.h>
+#else
+struct nlmsghdr;
+#endif
+#include <sys/socket.h>
#include <netinet/in.h>
BEGIN_C_DECLS
+21
View File
@@ -0,0 +1,21 @@
--- src/ucs/sys/sock.h.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/sys/sock.h
@@ -8,6 +8,18 @@
#ifndef UCS_SOCKET_H
#define UCS_SOCKET_H
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#if defined(HAVE_NETINET_IN_H)
+#include <netinet/in.h>
+#endif
+
+/* inet_pton/inet_ntop */
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h>
+#endif
+
#include <ucs/type/status.h>
#include <ucs/config/parser.h>
+310
View File
@@ -0,0 +1,310 @@
--- src/ucs/sys/sys.c.orig 2026-02-05 12:41:56 UTC
+++ src/ucs/sys/sys.c
@@ -23,16 +23,26 @@
#include <ucm/util/sys.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/resource.h>
+#include <netinet/in.h>
#include <net/if.h>
#include <dirent.h>
#include <sched.h>
#include <ctype.h>
+#include <sys/syscall.h>
+#if defined(__FreeBSD__)
+#include <ifaddrs.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#endif
#ifdef HAVE_SYS_THR_H
#include <sys/thr.h>
#endif
@@ -94,7 +104,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 +190,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 +236,56 @@ int ucs_netif_is_ipoib(const char *if_name)
}
return ifr.ifr_hwaddr.sa_family == ARPHRD_INFINIBAND;
+#endif
}
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 +333,7 @@ static uint64_t ucs_get_mac_address()
}
return mac_address;
+#endif
}
static uint64_t __sumup_host_name(unsigned prime_index)
@@ -766,6 +857,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 +892,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 +953,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 +998,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 +1392,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 +1438,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 +1448,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 +1462,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 +1544,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)
+26
View File
@@ -0,0 +1,26 @@
--- src/ucs/sys/sys.h.orig 2026-02-05 12:41:56 UTC
+++ src/ucs/sys/sys.h
@@ -50,6 +50,8 @@
#include <net/if.h>
#include <netdb.h>
#include <dirent.h>
+#include <limits.h>
+#include <unistd.h>
#include <sys/types.h>
@@ -61,6 +63,14 @@ typedef cpuset_t ucs_sys_cpuset_t;
typedef cpuset_t ucs_sys_cpuset_t;
#else
#error "Port me"
+#endif
+
+#ifndef UCS_HOST_NAME_MAX
+# ifdef _POSIX_HOST_NAME_MAX
+# define UCS_HOST_NAME_MAX _POSIX_HOST_NAME_MAX
+# else
+# define UCS_HOST_NAME_MAX 256
+# endif
#endif
#define UCS_SYS_FS_SYSTEM_PATH "/sys/devices/system"
+174
View File
@@ -0,0 +1,174 @@
--- src/ucs/type/float8.h.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/type/float8.h
@@ -3,12 +3,63 @@
*
* See file LICENSE for terms.
*/
-
#ifndef UCS_TYPE_FLOAT_H
#define UCS_TYPE_FLOAT_H
-#include <ieee754.h>
+#include <stdint.h>
+#include <string.h>
+/* IEEE754 double layout helpers without bitfields.
+ */
+static inline void
+ucs_double_to_words(double d, uint32_t *hi, uint32_t *lo)
+{
+ uint32_t w[2];
+ memcpy(w, &d, sizeof(w));
+#if defined(FLOAT_WORDS_BIGENDIAN)
+ *hi = w[0];
+ *lo = w[1];
+#else
+ *hi = w[1];
+ *lo = w[0];
+#endif
+}
+
+static inline double
+ucs_words_to_double(uint32_t hi, uint32_t lo)
+{
+ uint32_t w[2];
+ double d;
+#if defined(FLOAT_WORDS_BIGENDIAN)
+ w[0] = hi;
+ w[1] = lo;
+#else
+ w[0] = lo;
+ w[1] = hi;
+#endif
+ memcpy(&d, w, sizeof(d));
+ return d;
+}
+
+static inline uint32_t ucs_ieee_double_sign(uint32_t hi)
+{
+ return hi >> 31;
+}
+
+static inline uint32_t ucs_ieee_double_exp(uint32_t hi)
+{
+ return (hi >> 20) & 0x7ffu;
+}
+
+static inline uint32_t ucs_ieee_double_mant_hi20(uint32_t hi)
+{
+ return hi & 0x000fffffu;
+}
+
+#ifndef IEEE754_DOUBLE_BIAS
+# define IEEE754_DOUBLE_BIAS 1023
+#endif
+
#include <ucs/sys/preprocessor.h>
#include <ucs/debug/assert.h>
#include <ucs/arch/bitops.h>
@@ -18,7 +69,6 @@ typedef uint8_t ucs_fp8_t;
typedef uint8_t ucs_fp8_t;
-
/**
* Bits number in the exponent part of a packed floating-point number
*/
@@ -103,24 +153,31 @@ static UCS_F_ALWAYS_INLINE ucs_fp8_t ucs_fp8_pack(doub
static UCS_F_ALWAYS_INLINE ucs_fp8_t ucs_fp8_pack(double value, uint64_t min,
uint64_t max)
{
- union ieee754_double ieee_value = {0};
+ uint32_t hi, lo;
+ uint32_t exp;
+ uint32_t mant0;
uint8_t exponent;
int8_t min_exponent, max_exponent;
- ieee_value.d = value;
min_exponent = ucs_ilog2(min);
max_exponent = ucs_ilog2(max);
- if (ucs_unlikely(ieee_value.ieee.exponent == _UCS_FP8_IEEE_NAN_EXPONENT)) {
+ ucs_double_to_words(value, &hi, &lo);
+ exp = ucs_ieee_double_exp(hi);
+ mant0 = ucs_ieee_double_mant_hi20(hi);
+
+ if (ucs_unlikely(exp == _UCS_FP8_IEEE_NAN_EXPONENT)) {
/* NaN maps to a special value for NaN */
exponent = _UCS_FP8_NAN;
- } else if (ucs_unlikely(ieee_value.ieee.exponent >
+ } else if (ucs_unlikely(exp >
(max_exponent + _UCS_FP8_EXPONENT_OFFSET))) {
/* A number beyond the max supported is capped */
exponent = max_exponent - min_exponent;
- ieee_value.ieee.mantissa0 = 0;
- ieee_value.ieee.mantissa1 = 0;
- } else if (ucs_unlikely(ieee_value.ieee.exponent <=
+ /* zero mantissa in-place */
+ mant0 = 0;
+ lo = 0;
+ hi = (hi & 0xfff00000u); /* keep sign+exp, clear mantissa hi20 */
+ } else if (ucs_unlikely(exp <=
min_exponent + _UCS_FP8_EXPONENT_OFFSET)) {
if (ucs_unlikely(value == 0)) {
/* 0 maps to a special value for 0 */
@@ -128,15 +185,16 @@ static UCS_F_ALWAYS_INLINE ucs_fp8_t ucs_fp8_pack(doub
} else {
/* A number below the min supported is rounded up */
exponent = 1;
- ieee_value.ieee.mantissa0 = 0;
- ieee_value.ieee.mantissa1 = 0;
+ mant0 = 0;
+ lo = 0;
+ hi = (hi & 0xfff00000u);
}
} else {
- exponent = ieee_value.ieee.exponent - _UCS_FP8_EXPONENT_OFFSET -
+ exponent = exp - _UCS_FP8_EXPONENT_OFFSET -
min_exponent;
}
- return exponent | ((ieee_value.ieee.mantissa0 >> _UCS_FP_MANTISSA_OFFSET)
+ return exponent | ((mant0 >> _UCS_FP_MANTISSA_OFFSET)
<< _UCS_FP8_EXPONENT_BITS);
}
@@ -154,23 +212,28 @@ ucs_fp8_unpack(ucs_fp8_t value, uint64_t min, uint64_t
static UCS_F_ALWAYS_INLINE double
ucs_fp8_unpack(ucs_fp8_t value, uint64_t min, uint64_t max)
{
- union ieee754_double ieee_value = {0};
+ uint32_t hi = 0, lo = 0;
+ uint32_t exp;
+ uint32_t mant0;
uint8_t exponent = value & _UCS_FP8_EXPONENT_MASK;
- ieee_value.ieee.negative = 0;
+ (void)max;
+
if (ucs_unlikely(exponent == 0)) {
- ieee_value.ieee.exponent = 0;
+ exp = 0;
} else if (ucs_unlikely(exponent == _UCS_FP8_NAN)) {
- ieee_value.ieee.exponent = _UCS_FP8_IEEE_NAN_EXPONENT;
+ exp = _UCS_FP8_IEEE_NAN_EXPONENT;
} else {
- ieee_value.ieee.exponent = exponent + _UCS_FP8_EXPONENT_OFFSET +
+ exp = exponent + _UCS_FP8_EXPONENT_OFFSET +
ucs_ilog2(min);
}
- ieee_value.ieee.mantissa0 = value >> _UCS_FP8_EXPONENT_BITS;
- ieee_value.ieee.mantissa0 = ieee_value.ieee.mantissa0
- << _UCS_FP_MANTISSA_OFFSET;
+ mant0 = (uint32_t)(value >> _UCS_FP8_EXPONENT_BITS);
+ mant0 = (mant0 << _UCS_FP_MANTISSA_OFFSET) & 0x000fffffu;
- return ieee_value.d;
+ hi = ((exp & 0x7ffu) << 20) | (mant0 & 0x000fffffu);
+ lo = 0;
+
+ return ucs_words_to_double(hi, lo);
}
@@ -0,0 +1,109 @@
--- src/ucs/vfs/fuse/vfs_fuse.c.orig 2026-02-04 09:52:46 UTC
+++ src/ucs/vfs/fuse/vfs_fuse.c
@@ -37,6 +37,7 @@ static struct {
static struct {
pthread_t thread_id;
+ int thread_started;
pthread_mutex_t mutex;
struct fuse *fuse;
int fuse_fd;
@@ -44,15 +45,20 @@ static struct {
int inotify_fd;
int watch_desc;
} ucs_vfs_fuse_context = {
- .thread_id = -1,
- .mutex = PTHREAD_MUTEX_INITIALIZER,
- .fuse = NULL,
- .fuse_fd = -1,
- .stop = 0,
- .inotify_fd = -1,
- .watch_desc = -1
+ .thread_started = 0,
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+ .fuse = NULL,
+ .fuse_fd = -1,
+ .stop = 0,
+ .inotify_fd = -1,
+ .watch_desc = -1
};
+static void ucs_vfs_sigusr1_handler(int signo)
+{
+ (void)signo;
+}
+
static void ucs_vfs_enum_dir_cb(const char *name, void *arg)
{
ucs_vfs_enum_dir_context_t *ctx = arg;
@@ -492,10 +498,10 @@ static void ucs_fuse_thread_stop()
static void ucs_fuse_thread_stop()
{
- sighandler_t orig_handler;
+ sig_t orig_handler;
int ret;
- orig_handler = signal(SIGUSR1, (sighandler_t)ucs_empty_function);
+ orig_handler = signal(SIGUSR1, ucs_vfs_sigusr1_handler);
pthread_mutex_lock(&ucs_vfs_fuse_context.mutex);
@@ -518,15 +524,20 @@ static void ucs_fuse_thread_stop()
if (ucs_vfs_fuse_context.fuse != NULL) {
fuse_exit(ucs_vfs_fuse_context.fuse);
ucs_fuse_replace_fd_devnull();
- pthread_kill(ucs_vfs_fuse_context.thread_id, SIGUSR1);
+ if (ucs_vfs_fuse_context.thread_started) {
+ pthread_kill(ucs_vfs_fuse_context.thread_id, SIGUSR1);
+ }
}
pthread_mutex_unlock(&ucs_vfs_fuse_context.mutex);
- ret = pthread_join(ucs_vfs_fuse_context.thread_id, NULL);
- if (ret != 0) {
- ucs_warn("pthread_join(0x%lx) failed: %m",
- ucs_vfs_fuse_context.thread_id);
+ if (ucs_vfs_fuse_context.thread_started) {
+ ret = pthread_join(ucs_vfs_fuse_context.thread_id, NULL);
+ if (ret != 0) {
+ ucs_warn("pthread_join(0x%lx) failed: %m",
+ ucs_vfs_fuse_context.thread_id);
+ }
+ ucs_vfs_fuse_context.thread_started = 0;
}
signal(SIGUSR1, orig_handler);
@@ -536,11 +547,11 @@ static void ucs_vfs_fuse_atfork_child()
{
/* Reset thread context at fork, since doing inotify_rm_watch() from child
will prevent doing it later from the parent */
- ucs_vfs_fuse_context.thread_id = -1;
- ucs_vfs_fuse_context.fuse = NULL;
- ucs_vfs_fuse_context.fuse_fd = -1;
- ucs_vfs_fuse_context.inotify_fd = -1;
- ucs_vfs_fuse_context.watch_desc = -1;
+ ucs_vfs_fuse_context.thread_started = 0;
+ ucs_vfs_fuse_context.fuse = NULL;
+ ucs_vfs_fuse_context.fuse_fd = -1;
+ ucs_vfs_fuse_context.inotify_fd = -1;
+ ucs_vfs_fuse_context.watch_desc = -1;
}
void UCS_F_CTOR ucs_vfs_fuse_init()
@@ -549,12 +560,13 @@ void UCS_F_CTOR ucs_vfs_fuse_init()
pthread_atfork(NULL, NULL, ucs_vfs_fuse_atfork_child);
ucs_pthread_create(&ucs_vfs_fuse_context.thread_id,
ucs_vfs_fuse_thread_func, NULL, "fuse");
+ ucs_vfs_fuse_context.thread_started = 1;
}
}
void UCS_F_DTOR ucs_vfs_fuse_cleanup()
{
- if (ucs_vfs_fuse_context.thread_id != -1) {
+ if (ucs_vfs_fuse_context.thread_started) {
ucs_fuse_thread_stop();
}
}
@@ -0,0 +1,78 @@
--- 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 <errno.h>
#include <pwd.h>
#include <libgen.h>
+#if defined(__FreeBSD__)
+#include <sys/ucred.h>
+#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;
}
@@ -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;
@@ -0,0 +1,18 @@
--- src/uct/ib/base/ib_device.h.orig 2026-02-05 12:41:56 UTC
+++ src/uct/ib/base/ib_device.h
@@ -20,8 +20,13 @@
#include <ucs/sys/sock.h>
#include <endian.h>
-#include <linux/ip.h>
-
+#if defined(__linux__)
+# include <linux/ip.h>
+# include <linux/ipv6.h>
+#else
+# include <netinet/ip.h>
+# include <netinet/ip6.h>
+#endif
#define UCT_IB_QPN_ORDER 24 /* How many bits can be an IB QP number */
#define UCT_IB_UIDX_SHIFT 8 /* BE uidx shift */
@@ -0,0 +1,17 @@
--- src/uct/ib/ud/base/ud_iface.c.orig 2026-02-05 12:41:56 UTC
+++ src/uct/ib/ud/base/ud_iface.c
@@ -1113,7 +1113,13 @@ union ibv_gid* uct_ud_grh_get_dgid(struct ibv_grh *grh
size_t i;
/* Make sure that daddr in IPv4 resides in the last 4 bytes in GRH */
- UCS_STATIC_ASSERT((UCT_IB_GRH_LEN - (20 + offsetof(struct iphdr, daddr))) ==
+ UCS_STATIC_ASSERT((UCT_IB_GRH_LEN - (20 + offsetof(
+#if defined(__linux__)
+ struct iphdr, daddr
+#else
+ struct ip, ip_dst
+#endif
+ ))) ==
UCS_IPV4_ADDR_LEN);
/* Make sure that dgid resides in the last 16 bytes in GRH */
@@ -0,0 +1,15 @@
--- src/uct/tcp/tcp_base.c.orig 2026-02-04 09:52:46 UTC
+++ src/uct/tcp/tcp_base.c
@@ -15,8 +15,12 @@ ucs_status_t ucs_tcp_base_set_syn_cnt(int fd, int tcp_
ucs_status_t ucs_tcp_base_set_syn_cnt(int fd, int tcp_syn_cnt)
{
if (tcp_syn_cnt != UCS_ULUNITS_AUTO) {
+#if defined(__linux__)
ucs_socket_setopt(fd, IPPROTO_TCP, TCP_SYNCNT, (const void*)&tcp_syn_cnt,
sizeof(int));
+#else
+ (void)fd;
+#endif
}
/* return UCS_OK anyway since setting TCP_SYNCNT is done on best effort */
@@ -0,0 +1,75 @@
--- src/uct/tcp/tcp_net.c.orig 2026-02-04 09:52:46 UTC
+++ src/uct/tcp/tcp_net.c
@@ -12,10 +12,16 @@
#include "tcp.h"
#include <ucs/sys/string.h>
+
+#if defined(__linux__)
#include <linux/sockios.h>
#include <linux/types.h>
#include <linux/ethtool.h>
#include <linux/if_ether.h>
+#else
+# include <net/ethernet.h>
+#endif
+
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <net/if.h>
@@ -28,6 +34,7 @@ ucs_status_t uct_tcp_netif_caps(const char *if_name, d
ucs_status_t uct_tcp_netif_caps(const char *if_name, double *latency_p,
double *bandwidth_p)
{
+ #if defined(__linux__)
struct ethtool_cmd edata;
uint32_t speed_mbps;
ucs_status_t status;
@@ -104,10 +111,37 @@ ucs_status_t uct_tcp_netif_caps(const char *if_name, d
*bandwidth_p = (speed_mbps * 1e6) / 8 *
(mtu - 40) / (mtu + ll_headers); /* TCP/IP header is 40 bytes */
return UCS_OK;
+#else
+ ucs_status_t status;
+ struct ifreq ifr;
+ uint32_t speed_mbps = 1000; /* best-effort default */
+ size_t mtu = 1500; /* fallback */
+ size_t ll_headers;
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ status = ucs_netif_ioctl(if_name, SIOCGIFMTU, &ifr);
+ if (status == UCS_OK) {
+ mtu = (size_t)ifr.ifr_mtu;
+ }
+
+ /*
+ * Ethernet framing estimate:
+ * preamble(7) + SFD(1) + ethernet header + CRC + IFG(12)
+ */
+ ll_headers = 7 + 1 + ETHER_HDR_LEN + ETHER_CRC_LEN + 12;
+
+ /* Same model as Linux path */
+ *latency_p = 576.0 / (speed_mbps * 1e6) + 5.2e-6;
+ *bandwidth_p = (speed_mbps * 1e6) / 8 *
+ (mtu - 40) / (mtu + ll_headers);
+ return UCS_OK;
+#endif
}
ucs_status_t uct_tcp_netif_is_default(const char *if_name, int *result_p)
{
+#if defined(__linux__)
static const char *filename = "/proc/net/route";
in_addr_t netmask;
char name[128];
@@ -139,4 +173,9 @@ out:
out:
fclose(f);
return UCS_OK;
+#else
+ (void)if_name;
+ *result_p = 0;
+ return UCS_OK;
+#endif
}
@@ -0,0 +1,23 @@
--- test/apps/iodemo/io_demo.cc.orig 2026-02-04 09:52:46 UTC
+++ test/apps/iodemo/io_demo.cc
@@ -18,6 +18,7 @@
#include <ctime>
#include <csignal>
#include <cerrno>
+#include <random>
#include <vector>
#include <map>
#include <queue>
@@ -2999,8 +3000,10 @@ static int do_client(options_t& test_opts)
LOG << "random seed: " << test_opts.random_seed;
// randomize servers to optimize startup
- std::random_shuffle(test_opts.servers.begin(), test_opts.servers.end(),
- IoDemoRandom::urand<size_t>);
+ {
+ std::mt19937 rng(static_cast<uint32_t>(test_opts.random_seed));
+ std::shuffle(test_opts.servers.begin(), test_opts.servers.end(), rng);
+ }
UcxLog vlog(LOG_PREFIX, test_opts.verbose);
vlog << "List of servers:";
@@ -0,0 +1,43 @@
--- test/apps/iodemo/ucx_wrapper.cc.orig 2026-02-04 09:52:46 UTC
+++ test/apps/iodemo/ucx_wrapper.cc
@@ -118,10 +118,14 @@ UcxContext::UcxContext(size_t iomsg_size, double conne
_iomsg_buffer(iomsg_size), _connect_timeout(connect_timeout),
_use_am(use_am), _worker_fd(-1), _epoll_fd(-1), _client_id(client_id)
{
+#if defined(__linux__)
if (use_epoll) {
_epoll_fd = epoll_create(1);
assert(_epoll_fd >= 0);
}
+#else
+ (void)use_epoll; /* epoll is Linux-only */
+#endif
}
UcxContext::~UcxContext()
@@ -359,6 +363,7 @@ int UcxContext::is_timeout_elapsed(struct timeval cons
return ((elapsed.tv_sec + (elapsed.tv_usec * 1e-6)) > timeout);
}
+#if defined(__linux__)
ucs_status_t UcxContext::epoll_init()
{
ucs_status_t status;
@@ -414,6 +419,17 @@ bool UcxContext::progress_worker_event()
assert(ev.data.fd == _worker_fd);
return false;
}
+#else
+ucs_status_t UcxContext::epoll_init()
+{
+ return UCS_OK;
+}
+
+bool UcxContext::progress_worker_event()
+{
+ return ucp_worker_progress(_worker) != 0;
+}
+#endif
void UcxContext::progress_timed_out_conns()
{
@@ -0,0 +1,14 @@
--- test/apps/iodemo/ucx_wrapper.h.orig 2026-02-04 09:52:46 UTC
+++ test/apps/iodemo/ucx_wrapper.h
@@ -22,7 +22,11 @@
#include <string>
#include <vector>
#include <queue>
+#if defined(__linux__)
#include <sys/epoll.h>
+#else
+/* FreeBSD: no epoll; iodemo must build without epoll support */
+#endif
#define MAX_LOG_PREFIX_SIZE 64
@@ -0,0 +1,13 @@
--- test/gtest/common/test_helpers.cc.orig 2026-02-04 09:52:46 UTC
+++ test/gtest/common/test_helpers.cc
@@ -13,6 +13,10 @@
#include <ucs/config/global_opts.h>
#include <ucs/config/parser.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/wait.h>
+
#include <set>
extern "C" {
@@ -0,0 +1,10 @@
--- test/gtest/common/test_watchdog.cc.orig 2026-02-04 09:52:46 UTC
+++ test/gtest/common/test_watchdog.cc
@@ -9,6 +9,7 @@
#endif
#include <common/test.h>
+#include <signal.h>
class test_watchdog : public ucs::test {
public:
@@ -0,0 +1,22 @@
--- test/gtest/ucs/test_debug.cc.orig 2026-02-04 09:52:47 UTC
+++ test/gtest/ucs/test_debug.cc
@@ -11,6 +11,7 @@ extern "C" {
#include <ucs/sys/sys.h>
}
+#include <libgen.h>
#include <dlfcn.h>
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;
}
@@ -0,0 +1,28 @@
--- test/gtest/uct/uct_test.cc.orig 2026-02-04 09:52:47 UTC
+++ test/gtest/uct/uct_test.cc
@@ -12,6 +12,7 @@
#include <ucs/sys/sock.h>
#include <ucs/sys/string.h>
#include <common/test_helpers.h>
+#include <ucs/type/cpu_set.h>
#include <algorithm>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -31,7 +32,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<resource>&
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);
+10
View File
@@ -0,0 +1,10 @@
UCX (Unified Communication X) is a high-performance communication framework
for modern HPC and data-intensive workloads. It provides low-latency,
high-bandwidth messaging and remote-memory-access primitives across a wide
range of transports, including shared memory, TCP/IP, and RDMA-capable
interconnects such as InfiniBand and RoCE (when supported by the platform).
UCX is commonly used as a communication substrate for MPI, OpenSHMEM, and
other distributed runtimes. It exposes a set of layered APIs (UCP/UCT/UCS/UCM)
to balance portability and performance while enabling optimized transport
selection, rendezvous protocols, and progress models.
+144
View File
@@ -0,0 +1,144 @@
%%IODEMO%%bin/io_demo
bin/ucx_info
%%PERFTEST%%bin/ucx_perftest
%%PERFTEST%%bin/ucx_perftest_daemon
bin/ucx_read_profile
@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
%%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
%%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