Hello community,

here is the log from the commit of package userspace-rcu for openSUSE:Factory 
checked in at 2013-11-29 12:05:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/userspace-rcu (Old)
 and      /work/SRC/openSUSE:Factory/.userspace-rcu.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "userspace-rcu"

Changes:
--------
--- /work/SRC/openSUSE:Factory/userspace-rcu/userspace-rcu.changes      
2013-09-11 13:23:34.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.userspace-rcu.new/userspace-rcu.changes 
2013-11-29 12:05:39.000000000 +0100
@@ -1,0 +2,17 @@
+Tue Nov 26 15:07:34 UTC 2013 - pgaj...@suse.com
+
+- updated to 0.8.1:
+  * tls-compat: fix comment typo
+  * Keep ABI compatible with already compiled LGPL applications
+  * Fix: tls-compat multi-lib conflict
+  * Use cross compiler for doc examples
+  * gcc warning fixes: -Wsign-compare and -Wextra
+  * Fix: urcu-qsbr: reversed logic on RCU_DEBUG
+  * Fix: urcu-bp segfault in glibc pthread_kill()
+  * Fix urcu-bp: don't move registry
+  * Fix: compat futex duplicated lock and completion
+  * Fix: i386 compat code duplicated mutex instances
+  * Fix: urcu-bp: Bulletproof RCU arena resize bug
+  * Fix: test_mutex.c uninitialized mutex
+
+-------------------------------------------------------------------

Old:
----
  userspace-rcu-0.8.0.tar.bz2
  userspace-rcu-0.8.0.tar.bz2.asc

New:
----
  userspace-rcu-0.8.1.tar.bz2
  userspace-rcu-0.8.1.tar.bz2.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ userspace-rcu.spec ++++++
--- /var/tmp/diff_new_pack.v3DpEj/_old  2013-11-29 12:05:39.000000000 +0100
+++ /var/tmp/diff_new_pack.v3DpEj/_new  2013-11-29 12:05:39.000000000 +0100
@@ -19,7 +19,7 @@
 
 
 Name:           userspace-rcu
-Version:        0.8.0
+Version:        0.8.1
 Release:        0
 %define soname      2
 Summary:        Userspace Read-Copy-Update Library

++++++ userspace-rcu-0.8.0.tar.bz2 -> userspace-rcu-0.8.1.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/ChangeLog 
new/userspace-rcu-0.8.1/ChangeLog
--- old/userspace-rcu-0.8.0/ChangeLog   2013-09-06 13:58:25.000000000 +0200
+++ new/userspace-rcu-0.8.1/ChangeLog   2013-11-12 17:08:39.000000000 +0100
@@ -1,3 +1,17 @@
+2013-11-12 Userspace RCU 0.8.1
+       * tls-compat: fix comment typo
+       * Keep ABI compatible with already compiled LGPL applications
+       * Fix: tls-compat multi-lib conflict
+       * Use cross compiler for doc examples
+       * gcc warning fixes: -Wsign-compare and -Wextra
+       * Fix: urcu-qsbr: reversed logic on RCU_DEBUG
+       * Fix: urcu-bp segfault in glibc pthread_kill()
+       * Fix urcu-bp: don't move registry
+       * Fix: compat futex duplicated lock and completion
+       * Fix: i386 compat code duplicated mutex instances
+       * Fix: urcu-bp: Bulletproof RCU arena resize bug
+       * Fix: test_mutex.c uninitialized mutex
+
 2013-09-06 Userspace RCU 0.8.0
        * Fix: hash table growth (for small tables) should be limited
        * Fix: doc/examples cross-build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/compat_arch_x86.c 
new/userspace-rcu-0.8.1/compat_arch_x86.c
--- old/userspace-rcu-0.8.0/compat_arch_x86.c   2013-05-14 16:18:25.000000000 
+0200
+++ new/userspace-rcu-0.8.1/compat_arch_x86.c   2013-11-11 23:10:16.000000000 
+0100
@@ -27,6 +27,14 @@
 #include <urcu/uatomic.h>
 
 /*
+ * Using attribute "weak" for __rcu_cas_avail and
+ * __urcu_x86_compat_mutex. Those are globally visible by the entire
+ * program, even though many shared objects may have their own version.
+ * The first version that gets loaded will be used by the entire
+ * program (executable and all shared objects).
+ */
+
+/*
  * It does not really matter if the constructor is called before using
  * the library, as long as the caller checks if __rcu_cas_avail < 0 and calls
  * compat_arch_init() explicitely if needed.
@@ -38,9 +46,11 @@
  *  1: available
  *  0: unavailable
  */
+__attribute__((weak))
 int __rcu_cas_avail = -1;
 
-static pthread_mutex_t compat_mutex = PTHREAD_MUTEX_INITIALIZER;
+__attribute__((weak))
+pthread_mutex_t __urcu_x86_compat_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 /*
  * get_eflags/set_eflags/compare_and_swap_is_available imported from glibc
@@ -84,7 +94,7 @@
        assert(!ret);
        ret = pthread_sigmask(SIG_BLOCK, &newmask, oldmask);
        assert(!ret);
-       ret = pthread_mutex_lock(&compat_mutex);
+       ret = pthread_mutex_lock(&__urcu_x86_compat_mutex);
        assert(!ret);
 }
 
@@ -92,7 +102,7 @@
 {
        int ret;
 
-       ret = pthread_mutex_unlock(&compat_mutex);
+       ret = pthread_mutex_unlock(&__urcu_x86_compat_mutex);
        assert(!ret);
        ret = pthread_sigmask(SIG_SETMASK, oldmask, NULL);
        assert(!ret);
@@ -103,7 +113,7 @@
        sigset_t mask;
        unsigned long result;
 
-       mutex_lock_signal_save(&compat_mutex, &mask);
+       mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
        switch (len) {
        case 1:
                *(unsigned char *)addr = (unsigned char)_new;
@@ -125,7 +135,7 @@
                result = 0;
                __asm__ __volatile__("ud2");
        }
-       mutex_lock_signal_restore(&compat_mutex, &mask);
+       mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
        return result;
 }
 
@@ -134,7 +144,7 @@
        sigset_t mask;
        unsigned long retval;
 
-       mutex_lock_signal_save(&compat_mutex, &mask);
+       mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
        switch (len) {
        case 1:
                retval = *(unsigned char *)addr;
@@ -156,7 +166,7 @@
                retval = 0;     /* silence gcc warnings */
                __asm__ __volatile__("ud2");
        }
-       mutex_lock_signal_restore(&compat_mutex, &mask);
+       mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
        return retval;
 }
 
@@ -166,7 +176,7 @@
        unsigned long retval;
        sigset_t mask;
 
-       mutex_lock_signal_save(&compat_mutex, &mask);
+       mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
        switch (len) {
        case 1:
        {
@@ -200,7 +210,7 @@
                retval = 0;     /* silence gcc warnings */
                __asm__ __volatile__("ud2");
        }
-       mutex_lock_signal_restore(&compat_mutex, &mask);
+       mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
        return retval;
 }
 
@@ -208,7 +218,7 @@
 {
        sigset_t mask;
 
-       mutex_lock_signal_save(&compat_mutex, &mask);
+       mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
        switch (len) {
        case 1:
                *(unsigned char *)addr |= (unsigned char)v;
@@ -226,14 +236,14 @@
                 */
                __asm__ __volatile__("ud2");
        }
-       mutex_lock_signal_restore(&compat_mutex, &mask);
+       mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
 }
 
 void _compat_uatomic_and(void *addr, unsigned long v, int len)
 {
        sigset_t mask;
 
-       mutex_lock_signal_save(&compat_mutex, &mask);
+       mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
        switch (len) {
        case 1:
                *(unsigned char *)addr &= (unsigned char)v;
@@ -251,7 +261,7 @@
                 */
                __asm__ __volatile__("ud2");
        }
-       mutex_lock_signal_restore(&compat_mutex, &mask);
+       mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
 }
 
 unsigned long _compat_uatomic_add_return(void *addr, unsigned long v, int len)
@@ -259,7 +269,7 @@
        sigset_t mask;
        unsigned long result;
 
-       mutex_lock_signal_save(&compat_mutex, &mask);
+       mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
        switch (len) {
        case 1:
                *(unsigned char *)addr += (unsigned char)v;
@@ -281,7 +291,7 @@
                result = 0;     /* silence gcc warnings */
                __asm__ __volatile__("ud2");
        }
-       mutex_lock_signal_restore(&compat_mutex, &mask);
+       mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
        return result;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/compat_futex.c 
new/userspace-rcu-0.8.1/compat_futex.c
--- old/userspace-rcu-0.8.0/compat_futex.c      2013-07-04 21:33:07.000000000 
+0200
+++ new/userspace-rcu-0.8.1/compat_futex.c      2013-11-11 23:10:16.000000000 
+0100
@@ -31,8 +31,18 @@
 #include <urcu/arch.h>
 #include <urcu/futex.h>
 
-static pthread_mutex_t compat_futex_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t compat_futex_cond = PTHREAD_COND_INITIALIZER;
+/*
+ * Using attribute "weak" for __urcu_compat_futex_lock and
+ * __urcu_compat_futex_cond. Those are globally visible by the entire
+ * program, even though many shared objects may have their own version.
+ * The first version that gets loaded will be used by the entire program
+ * (executable and all shared objects).
+ */
+
+__attribute__((weak))
+pthread_mutex_t __urcu_compat_futex_lock = PTHREAD_MUTEX_INITIALIZER;
+__attribute__((weak))
+pthread_cond_t __urcu_compat_futex_cond = PTHREAD_COND_INITIALIZER;
 
 /*
  * _NOT SIGNAL-SAFE_. pthread_cond is not signal-safe anyway. Though.
@@ -58,22 +68,22 @@
         */
        cmm_smp_mb();
 
-       ret = pthread_mutex_lock(&compat_futex_lock);
+       ret = pthread_mutex_lock(&__urcu_compat_futex_lock);
        assert(!ret);
        switch (op) {
        case FUTEX_WAIT:
                if (*uaddr != val)
                        goto end;
-               pthread_cond_wait(&compat_futex_cond, &compat_futex_lock);
+               pthread_cond_wait(&__urcu_compat_futex_cond, 
&__urcu_compat_futex_lock);
                break;
        case FUTEX_WAKE:
-               pthread_cond_broadcast(&compat_futex_cond);
+               pthread_cond_broadcast(&__urcu_compat_futex_cond);
                break;
        default:
                gret = -EINVAL;
        }
 end:
-       ret = pthread_mutex_unlock(&compat_futex_lock);
+       ret = pthread_mutex_unlock(&__urcu_compat_futex_lock);
        assert(!ret);
        return gret;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/configure 
new/userspace-rcu-0.8.1/configure
--- old/userspace-rcu-0.8.0/configure   2013-09-04 16:01:42.000000000 +0200
+++ new/userspace-rcu-0.8.1/configure   2013-11-12 17:09:25.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for userspace-rcu 0.8.0.
+# Generated by GNU Autoconf 2.69 for userspace-rcu 0.8.1.
 #
 # Report bugs to <mathieu dot desnoyers at efficios dot com>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='userspace-rcu'
 PACKAGE_TARNAME='userspace-rcu'
-PACKAGE_VERSION='0.8.0'
-PACKAGE_STRING='userspace-rcu 0.8.0'
+PACKAGE_VERSION='0.8.1'
+PACKAGE_STRING='userspace-rcu 0.8.1'
 PACKAGE_BUGREPORT='mathieu dot desnoyers at efficios dot com'
 PACKAGE_URL=''
 
@@ -1326,7 +1326,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.8.0 to adapt to many kinds of systems.
+\`configure' configures userspace-rcu 0.8.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1397,7 +1397,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of userspace-rcu 0.8.0:";;
+     short | recursive ) echo "Configuration of userspace-rcu 0.8.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1504,7 +1504,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-userspace-rcu configure 0.8.0
+userspace-rcu configure 0.8.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1927,7 +1927,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.8.0, which was
+It was created by userspace-rcu $as_me 0.8.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2863,7 +2863,7 @@
 
 # Define the identity of the package.
  PACKAGE='userspace-rcu'
- VERSION='0.8.0'
+ VERSION='0.8.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13588,7 +13588,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.8.0, which was
+This file was extended by userspace-rcu $as_me 0.8.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13658,7 +13658,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-userspace-rcu config.status 0.8.0
+userspace-rcu config.status 0.8.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/configure.ac 
new/userspace-rcu-0.8.1/configure.ac
--- old/userspace-rcu-0.8.0/configure.ac        2013-09-04 16:01:34.000000000 
+0200
+++ new/userspace-rcu-0.8.1/configure.ac        2013-11-12 17:07:29.000000000 
+0100
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 
-AC_INIT([userspace-rcu],[0.8.0],[mathieu dot desnoyers at efficios dot com])
+AC_INIT([userspace-rcu],[0.8.1],[mathieu dot desnoyers at efficios dot com])
 
 # Following the numbering scheme proposed by libtool for the library version
 # 
http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/userspace-rcu-0.8.0/doc/examples/Makefile.examples.template 
new/userspace-rcu-0.8.1/doc/examples/Makefile.examples.template
--- old/userspace-rcu-0.8.0/doc/examples/Makefile.examples.template     
2013-08-30 20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/doc/examples/Makefile.examples.template     
2013-11-11 23:10:16.000000000 +0100
@@ -11,7 +11,9 @@
 #
 # This makefile is purposefully kept simple to support GNU and BSD make.
 
+ifndef CC
 CC = gcc
+endif
 CFLAGS = -g -O2 -Wall
 
 all: $(BINARY)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/tests/benchmark/test_mutex.c 
new/userspace-rcu-0.8.1/tests/benchmark/test_mutex.c
--- old/userspace-rcu-0.8.0/tests/benchmark/test_mutex.c        2013-08-30 
20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/tests/benchmark/test_mutex.c        2013-11-11 
23:10:16.000000000 +0100
@@ -52,7 +52,7 @@
        int a;
 };
 
-static pthread_mutex_t lock;
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 
 static volatile int test_go, test_stop;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/tests/benchmark/test_urcu_hash.c 
new/userspace-rcu-0.8.1/tests/benchmark/test_urcu_hash.c
--- old/userspace-rcu-0.8.0/tests/benchmark/test_urcu_hash.c    2013-08-30 
20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/tests/benchmark/test_urcu_hash.c    2013-11-12 
17:06:57.000000000 +0100
@@ -82,13 +82,13 @@
        return test_hash_cb[test_choice].populate_hash;
 }
 
-DEFINE_URCU_TLS(unsigned int, rand_lookup);
-DEFINE_URCU_TLS(unsigned long, nr_add);
-DEFINE_URCU_TLS(unsigned long, nr_addexist);
-DEFINE_URCU_TLS(unsigned long, nr_del);
-DEFINE_URCU_TLS(unsigned long, nr_delnoent);
-DEFINE_URCU_TLS(unsigned long, lookup_fail);
-DEFINE_URCU_TLS(unsigned long, lookup_ok);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rand_lookup);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_add);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_addexist);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_del);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_delnoent);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, lookup_fail);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, lookup_ok);
 
 struct cds_lfht *test_ht;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/urcu/compiler.h 
new/userspace-rcu-0.8.1/urcu/compiler.h
--- old/userspace-rcu-0.8.0/urcu/compiler.h     2013-08-30 20:25:20.000000000 
+0200
+++ new/userspace-rcu-0.8.1/urcu/compiler.h     2013-11-11 23:10:16.000000000 
+0100
@@ -86,10 +86,15 @@
 #define URCU_FORCE_CAST(type, arg)     ((type) (arg))
 #endif
 
-#define caa_is_signed_type(type)       (((type) (-1)) < 0)
+#define caa_is_signed_type(type)       ((type) -1 < (type) 0)
 
-#define caa_cast_long_keep_sign(v)     \
-       (caa_is_signed_type(__typeof__(v)) ? (long) (v) : (unsigned long) (v))
+/*
+ * Sign-extend to long if needed, and output type is unsigned long.
+ */
+#define caa_cast_long_keep_sign(v)             \
+       (caa_is_signed_type(__typeof__(v)) ?    \
+               (unsigned long) (long) (v) :    \
+               (unsigned long) (v))
 
 #if defined (__GNUC__) \
        && ((__GNUC_MAJOR__ == 4) && (__GNUC_MINOR__ >= 5)      \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/urcu/tls-compat.h 
new/userspace-rcu-0.8.1/urcu/tls-compat.h
--- old/userspace-rcu-0.8.0/urcu/tls-compat.h   2013-08-30 20:25:20.000000000 
+0200
+++ new/userspace-rcu-0.8.1/urcu/tls-compat.h   2013-11-12 17:06:57.000000000 
+0100
@@ -70,10 +70,22 @@
 # define DEFINE_URCU_TLS(type, name)   \
        CONFIG_RCU_TLS type name
 
+# define __DEFINE_URCU_TLS_GLOBAL(type, name)  \
+       CONFIG_RCU_TLS type name
+
 # define URCU_TLS(name)                (name)
 
 #else /* #ifndef CONFIG_RCU_TLS */
 
+/*
+ * The *_1() macros ensure macro parameters are expanded.
+ *
+ * __DEFINE_URCU_TLS_GLOBAL and __URCU_TLS_CALL exist for the sole
+ * purpose of notifying applications compiled against non-fixed 0.7 and
+ * 0.8 userspace RCU headers and using multiple flavors concurrently to
+ * recompile against fixed userspace RCU headers.
+ */
+
 # include <pthread.h>
 
 struct urcu_tls {
@@ -82,15 +94,24 @@
        int init_done;
 };
 
+# define DECLARE_URCU_TLS_1(type, name)                                \
+       type *__tls_access2_ ## name(void)
+
 # define DECLARE_URCU_TLS(type, name)                          \
-       type *__tls_access_ ## name(void)
+       DECLARE_URCU_TLS_1(type, name)
 
 /*
  * Note: we don't free memory at process exit, since it will be dealt
  * with by the OS.
  */
-# define DEFINE_URCU_TLS(type, name)                           \
-       type *__tls_access_ ## name(void)                       \
+# define __URCU_TLS_CALL_1(name)                               \
+       __tls_access2_ ## name
+
+# define __URCU_TLS_CALL(name)                                 \
+       __URCU_TLS_CALL_1(name)
+
+# define DEFINE_URCU_TLS_1(type, name)                         \
+       type *__tls_access2_ ## name(void)                      \
        {                                                       \
                static struct urcu_tls __tls_ ## name = {       \
                        .init_mutex = PTHREAD_MUTEX_INITIALIZER,\
@@ -118,7 +139,34 @@
                return __tls_p;                                 \
        }
 
-# define URCU_TLS(name)                (*__tls_access_ ## name())
+/*
+ * Define with and without macro expansion to handle erroneous callers.
+ * Trigger an abort() if the caller application uses the clashing symbol
+ * if a weak symbol is overridden.
+ */
+# define __DEFINE_URCU_TLS_GLOBAL(type, name)                  \
+       DEFINE_URCU_TLS_1(type, name)                           \
+       int __urcu_tls_symbol_refcount_ ## name __attribute__((weak)); \
+       static __attribute__((constructor))                     \
+       void __urcu_tls_inc_refcount_ ## name(void)             \
+       {                                                       \
+               __urcu_tls_symbol_refcount_ ## name++;          \
+       }                                                       \
+       type *__tls_access_ ## name(void)                       \
+       {                                                       \
+               if (__urcu_tls_symbol_refcount_ ## name > 1) {  \
+                       fprintf(stderr, "Error: Userspace RCU symbol clash for 
multiple concurrent flavors. Please upgrade liburcu libraries and headers, then 
recompile your application.\n"); \
+                       abort();                                \
+               }                                               \
+               return __URCU_TLS_CALL(name)();                 \
+       }
+
+# define DEFINE_URCU_TLS(type, name)                           \
+       DEFINE_URCU_TLS_1(type, name)
+
+# define URCU_TLS_1(name)      (*__tls_access2_ ## name())
+
+# define URCU_TLS(name)                URCU_TLS_1(name)
 
 #endif /* #else #ifndef CONFIG_RCU_TLS */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/urcu-bp.c 
new/userspace-rcu-0.8.1/urcu-bp.c
--- old/userspace-rcu-0.8.0/urcu-bp.c   2013-08-30 20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/urcu-bp.c   2013-11-12 17:06:57.000000000 +0100
@@ -66,47 +66,46 @@
 #define MREMAP_FIXED   2
 
 /*
- * mremap wrapper for non-Linux systems. Maps a RW, anonymous private mapping.
+ * mremap wrapper for non-Linux systems not allowing MAYMOVE.
  * This is not generic.
 */
 static
 void *mremap_wrapper(void *old_address, size_t old_size,
                size_t new_size, int flags)
 {
-       void *new_address;
+       assert(!(flags & MREMAP_MAYMOVE));
 
-       assert(flags & MREMAP_MAYMOVE);
-       assert(!(flags & MREMAP_FIXED));
-       new_address = mmap(old_address, new_size,
-                          PROT_READ | PROT_WRITE,
-                          MAP_ANONYMOUS | MAP_PRIVATE,
-                          -1, 0);
-       if (new_address == MAP_FAILED)
-               return MAP_FAILED;
-       if (old_address) {
-               memcpy(new_address, old_address, old_size);
-               munmap(old_address, old_size);
-       }
-       return new_address;
+       return MAP_FAILED;
 }
 #endif
 
 /* Sleep delay in us */
 #define RCU_SLEEP_DELAY                1000
-#define ARENA_INIT_ALLOC       16
+#define INIT_NR_THREADS                8
+#define ARENA_INIT_ALLOC               \
+       sizeof(struct registry_chunk)   \
+       + INIT_NR_THREADS * sizeof(struct rcu_reader)
 
 /*
  * Active attempts to check for reader Q.S. before calling sleep().
  */
 #define RCU_QS_ACTIVE_ATTEMPTS 100
 
+static
+void __attribute__((constructor)) rcu_bp_init(void);
+static
 void __attribute__((destructor)) rcu_bp_exit(void);
 
 static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
 
+static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
+static int initialized;
+
+static pthread_key_t urcu_bp_key;
+
 #ifdef DEBUG_YIELD
 unsigned int rcu_yield_active;
-DEFINE_URCU_TLS(unsigned int, rcu_rand_yield);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rcu_rand_yield);
 #endif
 
 struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT };
@@ -115,23 +114,28 @@
  * Pointer to registry elements. Written to only by each individual reader. 
Read
  * by both the reader and the writers.
  */
-DEFINE_URCU_TLS(struct rcu_reader *, rcu_reader);
+__DEFINE_URCU_TLS_GLOBAL(struct rcu_reader *, rcu_reader);
 
 static CDS_LIST_HEAD(registry);
 
+struct registry_chunk {
+       size_t data_len;                /* data length */
+       size_t used;                    /* amount of data used */
+       struct cds_list_head node;      /* chunk_list node */
+       char data[];
+};
+
 struct registry_arena {
-       void *p;
-       size_t len;
-       size_t used;
+       struct cds_list_head chunk_list;
 };
 
-static struct registry_arena registry_arena;
+static struct registry_arena registry_arena = {
+       .chunk_list = CDS_LIST_HEAD_INIT(registry_arena.chunk_list),
+};
 
 /* Saved fork signal mask, protected by rcu_gp_lock */
 static sigset_t saved_fork_signal_mask;
 
-static void rcu_gc_registry(void);
-
 static void mutex_lock(pthread_mutex_t *mutex)
 {
        int ret;
@@ -228,9 +232,6 @@
        /* Write new ptr before changing the qparity */
        cmm_smp_mb();
 
-       /* Remove old registry elements */
-       rcu_gc_registry();
-
        /*
         * Wait for readers to observe original parity or be quiescent.
         */
@@ -301,82 +302,165 @@
 }
 
 /*
- * only grow for now.
+ * Only grow for now. If empty, allocate a ARENA_INIT_ALLOC sized chunk.
+ * Else, try expanding the last chunk. If this fails, allocate a new
+ * chunk twice as big as the last chunk.
+ * Memory used by chunks _never_ moves. A chunk could theoretically be
+ * freed when all "used" slots are released, but we don't do it at this
+ * point.
  */
-static void resize_arena(struct registry_arena *arena, size_t len)
+static
+void expand_arena(struct registry_arena *arena)
 {
-       void *new_arena;
+       struct registry_chunk *new_chunk, *last_chunk;
+       size_t old_chunk_len, new_chunk_len;
 
-       if (!arena->p)
-               new_arena = mmap(arena->p, len,
-                                PROT_READ | PROT_WRITE,
-                                MAP_ANONYMOUS | MAP_PRIVATE,
-                                -1, 0);
-       else
-               new_arena = mremap_wrapper(arena->p, arena->len,
-                                       len, MREMAP_MAYMOVE);
-       assert(new_arena != MAP_FAILED);
+       /* No chunk. */
+       if (cds_list_empty(&arena->chunk_list)) {
+               assert(ARENA_INIT_ALLOC >=
+                       sizeof(struct registry_chunk)
+                       + sizeof(struct rcu_reader));
+               new_chunk_len = ARENA_INIT_ALLOC;
+               new_chunk = mmap(NULL, new_chunk_len,
+                       PROT_READ | PROT_WRITE,
+                       MAP_ANONYMOUS | MAP_PRIVATE,
+                       -1, 0);
+               if (new_chunk == MAP_FAILED)
+                       abort();
+               bzero(new_chunk, new_chunk_len);
+               new_chunk->data_len =
+                       new_chunk_len - sizeof(struct registry_chunk);
+               cds_list_add_tail(&new_chunk->node, &arena->chunk_list);
+               return;         /* We're done. */
+       }
 
-       /*
-        * re-used the same region ?
-        */
-       if (new_arena == arena->p)
-               return;
+       /* Try expanding last chunk. */
+       last_chunk = cds_list_entry(arena->chunk_list.prev,
+               struct registry_chunk, node);
+       old_chunk_len =
+               last_chunk->data_len + sizeof(struct registry_chunk);
+       new_chunk_len = old_chunk_len << 1;
+
+       /* Don't allow memory mapping to move, just expand. */
+       new_chunk = mremap_wrapper(last_chunk, old_chunk_len,
+               new_chunk_len, 0);
+       if (new_chunk != MAP_FAILED) {
+               /* Should not have moved. */
+               assert(new_chunk == last_chunk);
+               bzero((char *) last_chunk + old_chunk_len,
+                       new_chunk_len - old_chunk_len);
+               last_chunk->data_len =
+                       new_chunk_len - sizeof(struct registry_chunk);
+               return;         /* We're done. */
+       }
 
-       bzero(new_arena + arena->len, len - arena->len);
-       arena->p = new_arena;
+       /* Remap did not succeed, we need to add a new chunk. */
+       new_chunk = mmap(NULL, new_chunk_len,
+               PROT_READ | PROT_WRITE,
+               MAP_ANONYMOUS | MAP_PRIVATE,
+               -1, 0);
+       if (new_chunk == MAP_FAILED)
+               abort();
+       bzero(new_chunk, new_chunk_len);
+       new_chunk->data_len =
+               new_chunk_len - sizeof(struct registry_chunk);
+       cds_list_add_tail(&new_chunk->node, &arena->chunk_list);
 }
 
-/* Called with signals off and mutex locked */
-static void add_thread(void)
+static
+struct rcu_reader *arena_alloc(struct registry_arena *arena)
 {
+       struct registry_chunk *chunk;
        struct rcu_reader *rcu_reader_reg;
+       int expand_done = 0;    /* Only allow to expand once per alloc */
+       size_t len = sizeof(struct rcu_reader);
 
-       if (registry_arena.len
-           < registry_arena.used + sizeof(struct rcu_reader))
-               resize_arena(&registry_arena,
-               caa_max(registry_arena.len << 1, ARENA_INIT_ALLOC));
-       /*
-        * Find a free spot.
-        */
-       for (rcu_reader_reg = registry_arena.p;
-            (void *)rcu_reader_reg < registry_arena.p + registry_arena.len;
-            rcu_reader_reg++) {
-               if (!rcu_reader_reg->alloc)
-                       break;
+retry:
+       cds_list_for_each_entry(chunk, &arena->chunk_list, node) {
+               if (chunk->data_len - chunk->used < len)
+                       continue;
+               /* Find spot */
+               for (rcu_reader_reg = (struct rcu_reader *) &chunk->data[0];
+                               rcu_reader_reg < (struct rcu_reader *) 
&chunk->data[chunk->data_len];
+                               rcu_reader_reg++) {
+                       if (!rcu_reader_reg->alloc) {
+                               rcu_reader_reg->alloc = 1;
+                               chunk->used += len;
+                               return rcu_reader_reg;
+                       }
+               }
+       }
+
+       if (!expand_done) {
+               expand_arena(arena);
+               expand_done = 1;
+               goto retry;
        }
-       rcu_reader_reg->alloc = 1;
-       registry_arena.used += sizeof(struct rcu_reader);
+
+       return NULL;
+}
+
+/* Called with signals off and mutex locked */
+static
+void add_thread(void)
+{
+       struct rcu_reader *rcu_reader_reg;
+       int ret;
+
+       rcu_reader_reg = arena_alloc(&registry_arena);
+       if (!rcu_reader_reg)
+               abort();
+       ret = pthread_setspecific(urcu_bp_key, rcu_reader_reg);
+       if (ret)
+               abort();
 
        /* Add to registry */
        rcu_reader_reg->tid = pthread_self();
        assert(rcu_reader_reg->ctr == 0);
        cds_list_add(&rcu_reader_reg->node, &registry);
+       /*
+        * Reader threads are pointing to the reader registry. This is
+        * why its memory should never be relocated.
+        */
        URCU_TLS(rcu_reader) = rcu_reader_reg;
 }
 
-/* Called with signals off and mutex locked */
-static void rcu_gc_registry(void)
+/* Called with mutex locked */
+static
+void cleanup_thread(struct registry_chunk *chunk,
+               struct rcu_reader *rcu_reader_reg)
 {
-       struct rcu_reader *rcu_reader_reg;
-       pthread_t tid;
-       int ret;
+       rcu_reader_reg->ctr = 0;
+       cds_list_del(&rcu_reader_reg->node);
+       rcu_reader_reg->tid = 0;
+       rcu_reader_reg->alloc = 0;
+       chunk->used -= sizeof(struct rcu_reader);
+}
+
+static
+struct registry_chunk *find_chunk(struct rcu_reader *rcu_reader_reg)
+{
+       struct registry_chunk *chunk;
 
-       for (rcu_reader_reg = registry_arena.p;
-            (void *)rcu_reader_reg < registry_arena.p + registry_arena.len;
-            rcu_reader_reg++) {
-               if (!rcu_reader_reg->alloc)
+       cds_list_for_each_entry(chunk, &registry_arena.chunk_list, node) {
+               if (rcu_reader_reg < (struct rcu_reader *) &chunk->data[0])
                        continue;
-               tid = rcu_reader_reg->tid;
-               ret = pthread_kill(tid, 0);
-               assert(ret != EINVAL);
-               if (ret == ESRCH) {
-                       cds_list_del(&rcu_reader_reg->node);
-                       rcu_reader_reg->ctr = 0;
-                       rcu_reader_reg->alloc = 0;
-                       registry_arena.used -= sizeof(struct rcu_reader);
-               }
+               if (rcu_reader_reg >= (struct rcu_reader *) 
&chunk->data[chunk->data_len])
+                       continue;
+               return chunk;
        }
+       return NULL;
+}
+
+/* Called with signals off and mutex locked */
+static
+void remove_thread(void)
+{
+       struct rcu_reader *rcu_reader_reg;
+
+       rcu_reader_reg = URCU_TLS(rcu_reader);
+       cleanup_thread(find_chunk(rcu_reader_reg), rcu_reader_reg);
+       URCU_TLS(rcu_reader) = NULL;
 }
 
 /* Disable signals, take mutex, add to registry */
@@ -386,28 +470,95 @@
        int ret;
 
        ret = sigfillset(&newmask);
-       assert(!ret);
+       if (ret)
+               abort();
        ret = pthread_sigmask(SIG_BLOCK, &newmask, &oldmask);
-       assert(!ret);
+       if (ret)
+               abort();
 
        /*
         * Check if a signal concurrently registered our thread since
-        * the check in rcu_read_lock(). */
+        * the check in rcu_read_lock().
+        */
        if (URCU_TLS(rcu_reader))
                goto end;
 
+       /*
+        * Take care of early registration before urcu_bp constructor.
+        */
+       rcu_bp_init();
+
        mutex_lock(&rcu_gp_lock);
        add_thread();
        mutex_unlock(&rcu_gp_lock);
 end:
        ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
-       assert(!ret);
+       if (ret)
+               abort();
+}
+
+/* Disable signals, take mutex, remove from registry */
+static
+void rcu_bp_unregister(void)
+{
+       sigset_t newmask, oldmask;
+       int ret;
+
+       ret = sigfillset(&newmask);
+       if (ret)
+               abort();
+       ret = pthread_sigmask(SIG_BLOCK, &newmask, &oldmask);
+       if (ret)
+               abort();
+
+       mutex_lock(&rcu_gp_lock);
+       remove_thread();
+       mutex_unlock(&rcu_gp_lock);
+       ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
+       if (ret)
+               abort();
 }
 
+/*
+ * Remove thread from the registry when it exits, and flag it as
+ * destroyed so garbage collection can take care of it.
+ */
+static
+void urcu_bp_thread_exit_notifier(void *rcu_key)
+{
+       assert(rcu_key == URCU_TLS(rcu_reader));
+       rcu_bp_unregister();
+}
+
+static
+void rcu_bp_init(void)
+{
+       mutex_lock(&init_lock);
+       if (!initialized) {
+               int ret;
+
+               ret = pthread_key_create(&urcu_bp_key,
+                               urcu_bp_thread_exit_notifier);
+               if (ret)
+                       abort();
+               initialized = 1;
+       }
+       mutex_unlock(&init_lock);
+}
+
+static
 void rcu_bp_exit(void)
 {
-       if (registry_arena.p)
-               munmap(registry_arena.p, registry_arena.len);
+       struct registry_chunk *chunk, *tmp;
+       int ret;
+
+       cds_list_for_each_entry_safe(chunk, tmp,
+                       &registry_arena.chunk_list, node) {
+               munmap(chunk, chunk->data_len + sizeof(struct registry_chunk));
+       }
+       ret = pthread_key_delete(urcu_bp_key);
+       if (ret)
+               abort();
 }
 
 /*
@@ -439,12 +590,35 @@
        assert(!ret);
 }
 
+/*
+ * Prune all entries from registry except our own thread. Fits the Linux
+ * fork behavior. Called with rcu_gp_lock held.
+ */
+static
+void urcu_bp_prune_registry(void)
+{
+       struct registry_chunk *chunk;
+       struct rcu_reader *rcu_reader_reg;
+
+       cds_list_for_each_entry(chunk, &registry_arena.chunk_list, node) {
+               for (rcu_reader_reg = (struct rcu_reader *) &chunk->data[0];
+                               rcu_reader_reg < (struct rcu_reader *) 
&chunk->data[chunk->data_len];
+                               rcu_reader_reg++) {
+                       if (!rcu_reader_reg->alloc)
+                               continue;
+                       if (rcu_reader_reg->tid == pthread_self())
+                               continue;
+                       cleanup_thread(chunk, rcu_reader_reg);
+               }
+       }
+}
+
 void rcu_bp_after_fork_child(void)
 {
        sigset_t oldmask;
        int ret;
 
-       rcu_gc_registry();
+       urcu_bp_prune_registry();
        oldmask = saved_fork_signal_mask;
        mutex_unlock(&rcu_gp_lock);
        ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/urcu-qsbr.c 
new/userspace-rcu-0.8.1/urcu-qsbr.c
--- old/userspace-rcu-0.8.0/urcu-qsbr.c 2013-08-30 20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/urcu-qsbr.c 2013-11-12 17:06:57.000000000 +0100
@@ -64,11 +64,11 @@
  * Written to only by each individual reader. Read by both the reader and the
  * writers.
  */
-DEFINE_URCU_TLS(struct rcu_reader, rcu_reader);
+__DEFINE_URCU_TLS_GLOBAL(struct rcu_reader, rcu_reader);
 
 #ifdef DEBUG_YIELD
 unsigned int rcu_yield_active;
-DEFINE_URCU_TLS(unsigned int, rcu_rand_yield);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rcu_rand_yield);
 #endif
 
 static CDS_LIST_HEAD(registry);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/urcu-qsbr.h 
new/userspace-rcu-0.8.1/urcu-qsbr.h
--- old/userspace-rcu-0.8.0/urcu-qsbr.h 2013-08-30 20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/urcu-qsbr.h 2013-11-11 23:10:16.000000000 +0100
@@ -91,7 +91,7 @@
  * library debugging & tracing features we could come up with.
  */
 
-#if (!defined(BUILD_QSBR_LIB) && defined(RCU_DEBUG))
+#if (!defined(BUILD_QSBR_LIB) && !defined(RCU_DEBUG))
 
 static inline void rcu_read_lock(void)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/userspace-rcu-0.8.0/urcu.c 
new/userspace-rcu-0.8.1/urcu.c
--- old/userspace-rcu-0.8.0/urcu.c      2013-08-30 20:25:20.000000000 +0200
+++ new/userspace-rcu-0.8.1/urcu.c      2013-11-12 17:06:57.000000000 +0100
@@ -107,11 +107,11 @@
  * Written to only by each individual reader. Read by both the reader and the
  * writers.
  */
-DEFINE_URCU_TLS(struct rcu_reader, rcu_reader);
+__DEFINE_URCU_TLS_GLOBAL(struct rcu_reader, rcu_reader);
 
 #ifdef DEBUG_YIELD
 unsigned int rcu_yield_active;
-DEFINE_URCU_TLS(unsigned int, rcu_rand_yield);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rcu_rand_yield);
 #endif
 
 static CDS_LIST_HEAD(registry);


-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to