Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package userspace-rcu for openSUSE:Factory checked in at 2026-10-24 22:03:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/userspace-rcu (Old) and /work/SRC/openSUSE:Factory/.userspace-rcu.new.2252680 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "userspace-rcu" Sat Oct 24 22:03:30 2026 rev:24 rq:1388102 version:0.15.7 Changes: -------- --- /work/SRC/openSUSE:Factory/userspace-rcu/userspace-rcu.changes 2026-03-27 06:52:14.872751372 +0100 +++ /work/SRC/openSUSE:Factory/.userspace-rcu.new.2252680/userspace-rcu.changes 2026-10-24 22:03:31.898856259 +0200 @@ -1,0 +2,15 @@ +Fri Oct 23 08:27:47 UTC 2026 - Dirk Müller <[email protected]> + +- update to 0.15.7: + * call-rcu worker: set CPU affinity on first non-empty dequeue + * Fix: leaky wfcq tests + * Fix: test_build.c: Test output mismatch + * Fix: workqueue leaks mutexes on FreeBSD + * Fix: call-rcu leaks mutexes on FreeBSD + * call_rcu: pin per-CPU worker at thread startup + * urcu-pointer: Add rcu_dereference_sym2() taking the pointer + address + * urcu-pointer: Fix missing memory ordering in + rcu_dereference_sym() + +------------------------------------------------------------------- Old: ---- userspace-rcu-0.15.6.tar.bz2 userspace-rcu-0.15.6.tar.bz2.asc New: ---- userspace-rcu-0.15.7.tar.bz2 userspace-rcu-0.15.7.tar.bz2.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ userspace-rcu.spec ++++++ --- /var/tmp/diff_new_pack.PeAMAd/_old 2026-10-24 22:03:32.646887485 +0200 +++ /var/tmp/diff_new_pack.PeAMAd/_new 2026-10-24 22:03:32.648887569 +0200 @@ -20,7 +20,7 @@ %define soname 8 Name: userspace-rcu -Version: 0.15.6 +Version: 0.15.7 Release: 0 Summary: Userspace Read-Copy-Update Library License: GPL-2.0-or-later AND LGPL-2.1-or-later AND MIT AND GPL-3.0-or-later ++++++ userspace-rcu-0.15.6.tar.bz2 -> userspace-rcu-0.15.7.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/ChangeLog new/userspace-rcu-0.15.7/ChangeLog --- old/userspace-rcu-0.15.6/ChangeLog 2026-01-26 15:24:09.000000000 +0100 +++ new/userspace-rcu-0.15.7/ChangeLog 2026-09-11 16:25:44.000000000 +0200 @@ -2,6 +2,16 @@ # # SPDX-License-Identifier: CC-BY-4.0 +2026-09-11 Userspace RCU 0.15.7 + * call-rcu worker: set CPU affinity on first non-empty dequeue + * Fix: leaky wfcq tests + * Fix: test_build.c: Test output mismatch + * Fix: workqueue leaks mutexes on FreeBSD + * Fix: call-rcu leaks mutexes on FreeBSD + * call_rcu: pin per-CPU worker at thread startup + * urcu-pointer: Add rcu_dereference_sym2() taking the pointer address + * urcu-pointer: Fix missing memory ordering in rcu_dereference_sym() + 2026-01-26 Userspace RCU 0.15.6 * urcu-mb: Add missing TSAN annotation to _urcu_mb_read_lock_update * lfstack: Coding style cleanup diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/configure new/userspace-rcu-0.15.7/configure --- old/userspace-rcu-0.15.6/configure 2026-01-26 15:24:27.000000000 +0100 +++ new/userspace-rcu-0.15.7/configure 2026-09-11 16:26:49.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for userspace-rcu 0.15.6. +# Generated by GNU Autoconf 2.71 for userspace-rcu 0.15.7. # # Report bugs to <mathieu dot desnoyers at efficios dot com>. # @@ -621,8 +621,8 @@ # Identity of this package. PACKAGE_NAME='userspace-rcu' PACKAGE_TARNAME='userspace-rcu' -PACKAGE_VERSION='0.15.6' -PACKAGE_STRING='userspace-rcu 0.15.6' +PACKAGE_VERSION='0.15.7' +PACKAGE_STRING='userspace-rcu 0.15.7' PACKAGE_BUGREPORT='mathieu dot desnoyers at efficios dot com' PACKAGE_URL='http://liburcu.org/' @@ -1398,7 +1398,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures userspace-rcu 0.15.6 to adapt to many kinds of systems. +\`configure' configures userspace-rcu 0.15.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1470,7 +1470,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of userspace-rcu 0.15.6:";; + short | recursive ) echo "Configuration of userspace-rcu 0.15.7:";; esac cat <<\_ACEOF @@ -1607,7 +1607,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -userspace-rcu configure 0.15.6 +userspace-rcu configure 0.15.7 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2224,7 +2224,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by userspace-rcu $as_me 0.15.6, which was +It was created by userspace-rcu $as_me 0.15.7, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3844,7 +3844,7 @@ # Define the identity of the package. PACKAGE='userspace-rcu' - VERSION='0.15.6' + VERSION='0.15.7' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -21069,7 +21069,7 @@ ## ## # Library versions for libtool -URCU_LIBRARY_VERSION=9:0:1 +URCU_LIBRARY_VERSION=10:0:2 @@ -21633,7 +21633,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by userspace-rcu $as_me 0.15.6, which was +This file was extended by userspace-rcu $as_me 0.15.7, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21702,7 +21702,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -userspace-rcu config.status 0.15.6 +userspace-rcu config.status 0.15.7 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/configure.ac new/userspace-rcu-0.15.7/configure.ac --- old/userspace-rcu-0.15.6/configure.ac 2026-01-26 15:24:17.000000000 +0100 +++ new/userspace-rcu-0.15.7/configure.ac 2026-09-11 16:25:51.000000000 +0200 @@ -7,16 +7,16 @@ # Project version information m4_define([urcu_version_major], [0]) m4_define([urcu_version_minor], [15]) -m4_define([urcu_version_patch], [6]) +m4_define([urcu_version_patch], [7]) m4_define([urcu_version_dev_stage], []) m4_define([urcu_version], urcu_version_major[.]urcu_version_minor[.]urcu_version_patch[]urcu_version_dev_stage) # Library version information of "liburcu" # Following the numbering scheme proposed by libtool for the library version # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -m4_define([urcu_lib_version_current], [9]) +m4_define([urcu_lib_version_current], [10]) m4_define([urcu_lib_version_revision], [0]) -m4_define([urcu_lib_version_age], [1]) +m4_define([urcu_lib_version_age], [2]) m4_define([urcu_lib_version], urcu_lib_version_current[:]urcu_lib_version_revision[:]urcu_lib_version_age) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/include/urcu/compiler.h new/userspace-rcu-0.15.7/include/urcu/compiler.h --- old/userspace-rcu-0.15.6/include/urcu/compiler.h 2025-12-14 04:05:09.000000000 +0100 +++ new/userspace-rcu-0.15.7/include/urcu/compiler.h 2026-09-11 16:25:10.000000000 +0200 @@ -150,7 +150,18 @@ #define __rcu #ifdef __cplusplus -#define URCU_FORCE_CAST(_type, arg) (reinterpret_cast<typename std::remove_cv<_type>::type>(arg)) +/* + * Force a cast between pointer types, matching the C "(type) arg" behavior of + * disregarding any cv-qualifier on the source. Stripping the source qualifiers + * is required e.g. for rcu_dereference() of a const-qualified pointer lvalue, + * where &(p) has type "T * const *" and must be passed as "void **": a plain + * reinterpret_cast cannot cast away that inner const. All users of this macro + * cast between (object) pointer types. + */ +#define URCU_FORCE_CAST(_type, arg) \ + (reinterpret_cast<typename std::remove_cv<_type>::type>( \ + const_cast<void *>( \ + reinterpret_cast<const volatile void *>(arg)))) #else #define URCU_FORCE_CAST(type, arg) ((type) (arg)) #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/include/urcu/pointer.h new/userspace-rcu-0.15.7/include/urcu/pointer.h --- old/userspace-rcu-0.15.6/include/urcu/pointer.h 2025-12-11 19:50:10.000000000 +0100 +++ new/userspace-rcu-0.15.7/include/urcu/pointer.h 2026-09-11 16:25:10.000000000 +0200 @@ -50,12 +50,22 @@ #else /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */ +/* + * rcu_dereference_sym() (taking the pointer by value) is kept exported for + * ABI compatibility only: the load of the RCU-protected pointer happened in + * the caller as a racy plain access, losing the memory_order_consume + * ordering. New code passes the address of the pointer to + * rcu_dereference_sym2() so the consume load is performed on the shared + * location itself. As with the inlined _rcu_dereference(), @p must be an + * lvalue. + */ extern void *rcu_dereference_sym(void *p); +extern void *rcu_dereference_sym2(void **p); #define rcu_dereference(p) \ __extension__ \ ({ \ __typeof__(p) _________p1 = URCU_FORCE_CAST(__typeof__(p), \ - rcu_dereference_sym(URCU_FORCE_CAST(void *, p))); \ + rcu_dereference_sym2(URCU_FORCE_CAST(void **, &(p)))); \ (_________p1); \ }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/src/urcu-call-rcu-impl.h new/userspace-rcu-0.15.7/src/urcu-call-rcu-impl.h --- old/userspace-rcu-0.15.6/src/urcu-call-rcu-impl.h 2025-12-14 04:05:09.000000000 +0100 +++ new/userspace-rcu-0.15.7/src/urcu-call-rcu-impl.h 2026-09-11 16:25:10.000000000 +0200 @@ -53,6 +53,7 @@ pthread_t tid; int cpu_affinity; unsigned long gp_count; + bool affinity_init; struct cds_list_head list; } __attribute__((__aligned__(CAA_CACHE_LINE_SIZE))); @@ -191,17 +192,13 @@ */ #ifdef HAVE_SCHED_SETAFFINITY static -int set_thread_cpu_affinity(struct call_rcu_data *crdp) +int do_set_thread_cpu_affinity(struct call_rcu_data *crdp) { cpu_set_t mask; int ret; if (crdp->cpu_affinity < 0) return 0; - if (++crdp->gp_count & SET_AFFINITY_CHECK_PERIOD_MASK) - return 0; - if (urcu_sched_getcpu() == crdp->cpu_affinity) - return 0; CPU_ZERO(&mask); CPU_SET(crdp->cpu_affinity, &mask); @@ -218,8 +215,33 @@ } return ret; } + +static +int set_thread_cpu_affinity(struct call_rcu_data *crdp) +{ + if (crdp->cpu_affinity < 0) + return 0; + crdp->gp_count++; + /* Force setting the affinity if it was not already initialized. */ + if (!crdp->affinity_init) { + crdp->affinity_init = true; + } else { + /* Rate-limit the migration-recovery re-pin in the work loop. */ + if (crdp->gp_count & SET_AFFINITY_CHECK_PERIOD_MASK) + return 0; + /* Only set affinity if we happen to be running on the wrong CPU. */ + if (urcu_sched_getcpu() == crdp->cpu_affinity) + return 0; + } + return do_set_thread_cpu_affinity(crdp); +} #else static +int do_set_thread_cpu_affinity(struct call_rcu_data *crdp __attribute__((__unused__))) +{ + return 0; +} +static int set_thread_cpu_affinity(struct call_rcu_data *crdp __attribute__((__unused__))) { return 0; @@ -318,9 +340,6 @@ struct call_rcu_data *crdp = (struct call_rcu_data *) arg; int rt = !!(uatomic_load(&crdp->flags) & URCU_CALL_RCU_RT); - if (set_thread_cpu_affinity(crdp)) - urcu_die(errno); - /* * If callbacks take a read-side lock, we need to be registered. */ @@ -333,14 +352,11 @@ cmm_smp_mb(); } for (;;) { - struct cds_wfcq_head cbs_tmp_head; + struct __cds_wfcq_head cbs_tmp_head; struct cds_wfcq_tail cbs_tmp_tail; struct cds_wfcq_node *cbs, *cbs_tmp_n; enum cds_wfcq_ret splice_ret; - if (set_thread_cpu_affinity(crdp)) - urcu_die(errno); - if (uatomic_load(&crdp->flags) & URCU_CALL_RCU_PAUSE) { /* * Pause requested. Become quiescent: remove @@ -358,12 +374,14 @@ rcu_register_thread(); } - cds_wfcq_init(&cbs_tmp_head, &cbs_tmp_tail); + __cds_wfcq_init(&cbs_tmp_head, &cbs_tmp_tail); splice_ret = __cds_wfcq_splice_blocking(&cbs_tmp_head, &cbs_tmp_tail, &crdp->cbs_head, &crdp->cbs_tail); urcu_posix_assert(splice_ret != CDS_WFCQ_RET_WOULDBLOCK); urcu_posix_assert(splice_ret != CDS_WFCQ_RET_DEST_NON_EMPTY); if (splice_ret != CDS_WFCQ_RET_SRC_EMPTY) { + if (set_thread_cpu_affinity(crdp)) + urcu_die(errno); synchronize_rcu(); cbcount = 0; __cds_wfcq_for_each_blocking_safe(&cbs_tmp_head, @@ -436,6 +454,7 @@ cds_list_add(&crdp->list, &call_rcu_data_list); crdp->cpu_affinity = cpu_affinity; crdp->gp_count = 0; + crdp->affinity_init = false; rcu_set_pointer(crdpp, crdp); ret = sigfillset(&newmask); @@ -796,6 +815,7 @@ if (ret) urcu_die(ret); } + cds_wfcq_destroy(&crdp->cbs_head, &crdp->cbs_tail); free(crdp); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/src/urcu-pointer.c new/userspace-rcu-0.15.7/src/urcu-pointer.c --- old/userspace-rcu-0.15.6/src/urcu-pointer.c 2025-12-11 19:50:10.000000000 +0100 +++ new/userspace-rcu-0.15.7/src/urcu-pointer.c 2026-09-11 16:25:10.000000000 +0200 @@ -17,9 +17,54 @@ extern void synchronize_rcu(void); +/* + * Kept for ABI compatibility with code built against liburcu releases that + * emitted calls to this symbol. + * + * This wrapper receives the RCU-protected pointer by *value*: the load of + * the pointer therefore already happened in the caller as a plain + * (non-atomic) access, before this function is even entered. As a result + * the compiler may have broken the address dependency between the pointer + * load and its later dereference (e.g. through value speculation, or LTO + * inlining of this trivial wrapper), which lets a weakly-ordered CPU + * reorder the dependent access ahead of the pointer load and observe + * pre-publication data, defeating the memory_order_consume guarantee of + * rcu_dereference(). + * + * Issue a full barrier to order the caller's pointer load (sequenced + * before this call) before any dependent access performed after this + * function returns, restoring the publication ordering regardless of + * whether the dependency survived. This is unneeded on x86 (TSO): the + * hardware preserves load-to-load and load-to-store ordering, so the + * pointer load is already ordered before any dependent access, and the + * bug cannot manifest. (TSO permits only store-to-load reordering, which + * is irrelevant here since the pointer access is a load.) Elide the + * barrier there to avoid penalising the common case. Note that the plain + * load itself stays in the caller, so it remains a data race reported by + * ThreadSanitizer. + * + * New code emitted by the rcu_dereference() macro calls + * rcu_dereference_sym2() instead, which receives the address of the + * pointer and performs the consume load on the shared location itself, + * avoiding both the ordering and the data-race problems. + */ void *rcu_dereference_sym(void *p) { - return _rcu_dereference(p); +#ifndef URCU_ARCH_X86 + cmm_smp_mb(); +#endif + return p; +} + +/* + * Receives the address of the RCU-protected pointer, so the + * memory_order_consume load is performed on the actual shared location + * rather than on a local copy. This preserves the dependency-ordering + * guarantee and is free of the data race affecting rcu_dereference_sym(). + */ +void *rcu_dereference_sym2(void **p) +{ + return _rcu_dereference(*p); } void *rcu_set_pointer_sym(void **p, void *v) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/src/workqueue.c new/userspace-rcu-0.15.7/src/workqueue.c --- old/userspace-rcu-0.15.6/src/workqueue.c 2025-12-14 04:05:09.000000000 +0100 +++ new/userspace-rcu-0.15.7/src/workqueue.c 2026-09-11 16:25:10.000000000 +0200 @@ -175,7 +175,7 @@ cmm_smp_mb(); } for (;;) { - struct cds_wfcq_head cbs_tmp_head; + struct __cds_wfcq_head cbs_tmp_head; struct cds_wfcq_tail cbs_tmp_tail; struct cds_wfcq_node *cbs, *cbs_tmp_n; enum cds_wfcq_ret splice_ret; @@ -202,7 +202,7 @@ workqueue->worker_after_resume_fct(workqueue, workqueue->priv); } - cds_wfcq_init(&cbs_tmp_head, &cbs_tmp_tail); + __cds_wfcq_init(&cbs_tmp_head, &cbs_tmp_tail); splice_ret = __cds_wfcq_splice_blocking(&cbs_tmp_head, &cbs_tmp_tail, &workqueue->cbs_head, &workqueue->cbs_tail); urcu_posix_assert(splice_ret != CDS_WFCQ_RET_WOULDBLOCK); @@ -343,6 +343,7 @@ urcu_die(errno); } urcu_posix_assert(cds_wfcq_empty(&workqueue->cbs_head, &workqueue->cbs_tail)); + cds_wfcq_destroy(&workqueue->cbs_head, &workqueue->cbs_tail); free(workqueue); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/userspace-rcu-0.15.6/tests/unit/test_build.c new/userspace-rcu-0.15.7/tests/unit/test_build.c --- old/userspace-rcu-0.15.6/tests/unit/test_build.c 2025-12-11 19:50:10.000000000 +0100 +++ new/userspace-rcu-0.15.7/tests/unit/test_build.c 2026-09-11 16:25:10.000000000 +0200 @@ -66,7 +66,7 @@ struct cds_wfs_stack s; cds_wfs_init(&s); - ok(cds_wfs_empty(&s), "cds_lfs_empty"); + ok(cds_wfs_empty(&s), "cds_wfs_empty"); } static void test_wfcqueue(void) @@ -76,6 +76,7 @@ cds_wfcq_init(&head, &tail); ok(cds_wfcq_empty(&head, &tail), "cds_wfcq_empty"); + cds_wfcq_destroy(&head, &tail); } static
