-include/urcu/arch.h
-include/urcu/uatomic.h
tests/api.h
AC_REQUIRE_AUX_FILE([tap-driver.sh])
AH_TEMPLATE([CONFIG_RCU_SMP], [Enable SMP support. With SMP support enabled, uniprocessors are also supported. With SMP support disabled, UP systems work fine, but the behavior of SMP systems is undefined.])
-AH_TEMPLATE([CONFIG_RCU_HAVE_FENCE], [Defined when on a system that has memory fence instructions.])
AH_TEMPLATE([CONFIG_RCU_HAVE_FUTEX], [Defined when on a system with futex support.])
-AH_TEMPLATE([CONFIG_RCU_COMPAT_ARCH], [Compatibility mode for i386 which lacks cmpxchg instruction.])
AH_TEMPLATE([CONFIG_RCU_ARM_HAVE_DMB], [Use the dmb instruction if available for use on ARM.])
AH_TEMPLATE([CONFIG_RCU_TLS], [TLS provided by the compiler.])
AH_TEMPLATE([CONFIG_RCU_HAVE_CLOCK_GETTIME], [clock_gettime() is detected.])
sys/time.h \
])
-# Find arch type
-AS_CASE([$host_cpu],
- [k1om], [ARCHTYPE="x86"],
- [i386], [ARCHTYPE="x86" && SUBARCHTYPE="x86compat"],
- [i486], [ARCHTYPE="x86"],
- [i586], [ARCHTYPE="x86"],
- [i686], [ARCHTYPE="x86"],
- [amd64], [ARCHTYPE="x86"],
- [x86_64], [ARCHTYPE="x86"],
- [powerpc], [ARCHTYPE="ppc"],
- [ppc64], [ARCHTYPE="ppc"],
- [powerpc64], [ARCHTYPE="ppc"],
- [powerpc64le], [ARCHTYPE="ppc"],
- [ppc], [ARCHTYPE="ppc"],
- [s390], [ARCHTYPE="s390"],
- [s390x], [ARCHTYPE="s390"],
- [sparc], [ARCHTYPE="sparc64"],
- [sparc64], [ARCHTYPE="sparc64"],
- [alpha*], [ARCHTYPE="alpha"],
- [ia64], [ARCHTYPE="ia64"],
- [arm*], [ARCHTYPE="arm"],
- [aarch64*], [ARCHTYPE="aarch64"],
- [mips*], [ARCHTYPE="mips"],
- [nios2*], [ARCHTYPE="nios2"],
- [tile*], [ARCHTYPE="tile"],
- [hppa*], [ARCHTYPE="hppa"],
- [m68k], [ARCHTYPE="m68k"],
- [riscv*], [ARCHTYPE="riscv"],
- [ARCHTYPE="unknown"]
-)
-
AS_CASE([$host],[*-cygwin*],
[AM_CONDITIONAL(USE_CYGWIN, true)],
[AM_CONDITIONAL(USE_CYGWIN, false)]
)
-AC_SUBST(ARCHTYPE)
-AC_SUBST(SUBARCHTYPE)
-
-UATOMICSRC=include/urcu/uatomic/$ARCHTYPE.h
-ARCHSRC=include/urcu/arch/$ARCHTYPE.h
-
-AS_IF([test "x$SUBARCHTYPE" = xx86compat],[
- AC_DEFINE([CONFIG_RCU_COMPAT_ARCH], [1])
-])
-
AS_IF([test "$host_cpu" = "armv7l"],[
AM_CFLAGS="$AM_CFLAGS -mcpu=cortex-a9 -mtune=cortex-a9 -O1"
])
# ARM-specific checks
-AS_IF([test "x$ARCHTYPE" = "xarm"],[
+AS_CASE([$host_cpu], [arm*], [
AC_MSG_CHECKING([for dmb instruction])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
int main()
])
])
-# Tile-specific checks
-AS_IF([echo "$host_cpu" | grep "^tile"],[
- AC_MSG_CHECKING([for Tile architecture type])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- #ifndef __tilegx__
- #error
- #endif
- ]])
- ],[
- AC_MSG_RESULT([ok])
- ],[
- AC_MSG_FAILURE([URCU has only been tested on the TileGx architecture. For other Tile* architectures, please run the tests first and report the results to the maintainer so that proper support can be added.])
- ])
-])
-
-# x86-specific checks
-AS_IF([test "x$ARCHTYPE" = "xx86"],[
- AC_MSG_CHECKING([if architecture really supports the mfence instruction])
- #For now, using lock; addl compatibility mode even for i686, because the
- #Pentium III is seen as a i686, but lacks mfence instruction.
- #Only using fence for x86_64.
- #
- #k1om is the name for the Intel MIC family (Xeon Phi). It is an x86_64
- #variant but lacks fence instructions.
- AS_IF([test "x$host_cpu" != "xi386" -a "x$host_cpu" != "xi486" -a "x$host_cpu" != "xi586" -a "x$host_cpu" != "xi686" -a "x$host_vendor" != "xk1om" -a "x$host_cpu" != "xk1om"],[
- AC_MSG_RESULT([yes])
- AC_DEFINE([CONFIG_RCU_HAVE_FENCE], [1])
- config_rcu_have_fence=yes
- ],[
- AC_MSG_RESULT([no])
- config_rcu_have_fence=no
- ])
-])
-
# Check if sys_futex() is available
AC_MSG_CHECKING([for sys_futex()])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
], [])
AM_CONDITIONAL([COMPAT_FUTEX], [test "x$compat_futex_test" = "x1"])
-AM_CONDITIONAL([COMPAT_ARCH], [test "x$SUBARCHTYPE" = "xx86compat"])
AM_CONDITIONAL([NO_SHARED], [test "x$enable_shared" = "xno"])
# smp-support configure option
AM_CFLAGS="-Wall -Wextra -Wno-unused-parameter $AM_CFLAGS"
AC_SUBST(AM_CFLAGS)
-AC_CONFIG_LINKS([
- include/urcu/arch.h:$ARCHSRC
- include/urcu/uatomic.h:$UATOMICSRC
-])
AC_CONFIG_FILES([
Makefile
doc/Makefile
test "x$def_smp_support" = "xyes" && value=1 || value=0
PPRINT_PROP_BOOL([SMP support], $value)
-# Memory fence support available
-test "x$config_rcu_have_fence" = "xyes" && value=1 || value=0
-PPRINT_PROP_BOOL([Memory fence instructions], $value)
-
# Futex support available
test "x$compat_futex_test" = "x0" && value=1 || value=0
PPRINT_PROP_BOOL([Futex support], $value)
-nobase_dist_include_HEADERS = urcu/compiler.h urcu/hlist.h urcu/list.h \
- urcu/rculist.h urcu/rcuhlist.h urcu/system.h urcu/futex.h \
- urcu/uatomic/generic.h urcu/arch/generic.h urcu/wfstack.h \
- urcu/wfqueue.h urcu/rculfstack.h urcu/rculfqueue.h \
- urcu/ref.h urcu/cds.h urcu/urcu_ref.h urcu/urcu-futex.h \
- urcu/uatomic_arch.h urcu/rculfhash.h urcu/wfcqueue.h \
- urcu/lfstack.h urcu/syscall-compat.h \
- urcu/map/urcu-bp.h urcu/map/urcu.h urcu/map/urcu-qsbr.h \
- urcu/map/clear.h urcu/map/urcu-mb.h urcu/map/urcu-memb.h \
- urcu/map/urcu-signal.h \
- urcu/static/lfstack.h urcu/static/rculfqueue.h \
- urcu/static/rculfstack.h urcu/static/urcu-bp.h \
- urcu/static/urcu.h urcu/static/pointer.h \
- urcu/static/urcu-qsbr.h urcu/static/wfcqueue.h \
- urcu/static/wfqueue.h urcu/static/wfstack.h \
- urcu/static/urcu-mb.h urcu/static/urcu-memb.h \
- urcu/static/urcu-signal.h urcu/static/urcu-signal-nr.h \
- urcu/static/urcu-common.h \
- urcu/tls-compat.h urcu/debug.h urcu/urcu.h urcu/urcu-bp.h \
- urcu/call-rcu.h urcu/defer.h \
- urcu/pointer.h urcu/urcu-qsbr.h urcu/flavor.h \
- urcu/urcu-mb.h urcu/urcu-memb.h urcu/urcu-signal.h \
- urcu.h urcu-bp.h urcu-call-rcu.h urcu-defer.h \
- urcu-pointer.h urcu-qsbr.h urcu-flavor.h
-
-# Don't distribute generated headers
-nobase_nodist_include_HEADERS = urcu/arch.h urcu/uatomic.h urcu/config.h
-
-EXTRA_DIST = urcu/arch/aarch64.h \
+nobase_include_HEADERS = \
+ urcu/arch/aarch64.h \
urcu/arch/alpha.h \
urcu/arch/arm.h \
urcu/arch/gcc.h \
urcu/arch/generic.h \
+ urcu/arch.h \
urcu/arch/hppa.h \
urcu/arch/ia64.h \
urcu/arch/m68k.h \
urcu/arch/s390.h \
urcu/arch/sparc64.h \
urcu/arch/tile.h \
- urcu/arch/unknown.h \
urcu/arch/x86.h \
+ urcu/call-rcu.h \
+ urcu/cds.h \
+ urcu/compiler.h \
+ urcu/debug.h \
+ urcu/defer.h \
+ urcu/flavor.h \
+ urcu/futex.h \
+ urcu/hlist.h \
+ urcu/lfstack.h \
+ urcu/list.h \
+ urcu/map/clear.h \
+ urcu/map/urcu-bp.h \
+ urcu/map/urcu.h \
+ urcu/map/urcu-mb.h \
+ urcu/map/urcu-memb.h \
+ urcu/map/urcu-qsbr.h \
+ urcu/map/urcu-signal.h \
+ urcu/pointer.h \
+ urcu/rcuhlist.h \
+ urcu/rculfhash.h \
+ urcu/rculfqueue.h \
+ urcu/rculfstack.h \
+ urcu/rculist.h \
+ urcu/ref.h \
+ urcu/static/lfstack.h \
+ urcu/static/pointer.h \
+ urcu/static/rculfqueue.h \
+ urcu/static/rculfstack.h \
+ urcu/static/urcu-bp.h \
+ urcu/static/urcu-common.h \
+ urcu/static/urcu.h \
+ urcu/static/urcu-mb.h \
+ urcu/static/urcu-memb.h \
+ urcu/static/urcu-qsbr.h \
+ urcu/static/urcu-signal.h \
+ urcu/static/urcu-signal-nr.h \
+ urcu/static/wfcqueue.h \
+ urcu/static/wfqueue.h \
+ urcu/static/wfstack.h \
+ urcu/syscall-compat.h \
+ urcu/system.h \
+ urcu/tls-compat.h \
urcu/uatomic/aarch64.h \
urcu/uatomic/alpha.h \
+ urcu/uatomic_arch.h \
urcu/uatomic/arm.h \
urcu/uatomic/gcc.h \
urcu/uatomic/generic.h \
+ urcu/uatomic.h \
urcu/uatomic/hppa.h \
urcu/uatomic/ia64.h \
urcu/uatomic/m68k.h \
urcu/uatomic/s390.h \
urcu/uatomic/sparc64.h \
urcu/uatomic/tile.h \
- urcu/uatomic/unknown.h \
- urcu/uatomic/x86.h
+ urcu/uatomic/x86.h \
+ urcu/urcu-bp.h \
+ urcu/urcu-futex.h \
+ urcu/urcu.h \
+ urcu/urcu-mb.h \
+ urcu/urcu-memb.h \
+ urcu/urcu-qsbr.h \
+ urcu/urcu_ref.h \
+ urcu/urcu-signal.h \
+ urcu/wfcqueue.h \
+ urcu/wfqueue.h \
+ urcu/wfstack.h
+
+# Don't distribute generated headers
+nobase_nodist_include_HEADERS = urcu/config.h
+
+# Non 'urcu/' prefixed compat headers
+include_HEADERS = \
+ urcu-qsbr.h \
+ urcu-bp.h \
+ urcu-call-rcu.h \
+ urcu-defer.h \
+ urcu-flavor.h \
+ urcu.h \
+ urcu-pointer.h
--- /dev/null
+/*
+ * urcu/arch.h
+ *
+ * Copyright (c) 2020 Michael Jeanson <michael.jeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _URCU_ARCH_H
+#define _URCU_ARCH_H
+
+/*
+ * Architecture detection using compiler defines.
+ *
+ * The following defines are used internally for architecture specific code.
+ *
+ * URCU_ARCH_X86 : All x86 variants 32 and 64 bits
+ * URCU_ARCH_I386 : Specific to the i386
+ * URCU_ARCH_AMD64 : All 64 bits x86 variants
+ * URCU_ARCH_K1OM : Specific to the Xeon Phi / MIC
+ *
+ * URCU_ARCH_PPC : All PowerPC variants 32 and 64 bits
+ * URCU_ARCH_PPC64 : Specific to 64 bits variants
+ *
+ * URCU_ARCH_S390 : All IBM s390 / s390x variants
+ *
+ * URCU_ARCH_SPARC64 : All Sun SPARC variants
+ *
+ * URCU_ARCH_ALPHA : All DEC Alpha variants
+ * URCU_ARCH_IA64 : All Intel Itanium variants
+ * URCU_ARCH_ARM : All ARM 32 bits variants
+ * URCU_ARCH_AARCH64 : All ARM 64 bits variants
+ * URCU_ARCH_MIPS : All MIPS variants
+ * URCU_ARCH_NIOS2 : All Intel / Altera NIOS II variants
+ * URCU_ARCH_TILE : All Tilera TILE variants
+ * URCU_ARCH_HPPA : All HP PA-RISC variants
+ * URCU_ARCH_M68K : All Motorola 68000 variants
+ * URCU_ARCH_RISCV : All RISC-V variants
+ */
+#if (defined(__i386__) || defined(__i386))
+
+#define URCU_ARCH_X86 1
+#define URCU_ARCH_I386 1
+#include <urcu/arch/x86.h>
+
+#elif (defined(__i486__) || defined(__i586__) || defined(__i686__))
+
+#define URCU_ARCH_X86 1
+#include <urcu/arch/x86.h>
+
+#elif (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64))
+
+#define URCU_ARCH_X86 1
+#define URCU_ARCH_AMD64 1
+#include <urcu/arch/x86.h>
+
+#elif (defined(__INTEL_OFFLOAD) || defined(__TARGET_ARCH_MIC) || defined(__MIC__))
+
+#define URCU_ARCH_X86 1
+#define URCU_ARCH_AMD64 1
+#define URCU_ARCH_K1OM 1
+#include <urcu/arch/x86.h>
+
+#elif (defined(__powerpc__) || defined(__powerpc) || defined(__ppc__))
+
+#define URCU_ARCH_PPC 1
+#include <urcu/arch/ppc.h>
+
+#elif (defined(__powerpc64__) || defined(__ppc64__))
+
+#define URCU_ARCH_PPC 1
+#define URCU_ARCH_PPC64 1
+#include <urcu/arch/ppc.h>
+
+#elif (defined(__s390__) || defined(__s390x__) || defined(__zarch__))
+
+#define URCU_ARCH_S390 1
+#include <urcu/arch/s390.h>
+
+#elif (defined(__sparc__) || defined(__sparc) || defined(__sparc64__))
+
+#define URCU_ARCH_SPARC64 1
+#include <urcu/arch/sparc64.h>
+
+#elif (defined(__alpha__) || defined(__alpha))
+
+#define URCU_ARCH_ALPHA 1
+#include <urcu/arch/alpha.h>
+
+#elif (defined(__ia64__) || defined(__ia64))
+
+#define URCU_ARCH_IA64 1
+#include <urcu/arch/ia64.h>
+
+#elif (defined(__arm__) || defined(__arm))
+
+#define URCU_ARCH_ARM 1
+#include <urcu/arch/arm.h>
+
+#elif defined(__aarch64__)
+
+#define URCU_ARCH_AARCH64 1
+#include <urcu/arch/aarch64.h>
+
+#elif (defined(__mips__) || defined(__mips))
+
+#define URCU_ARCH_MIPS 1
+#include <urcu/arch/mips.h>
+
+#elif (defined(__nios2__) || defined(__nios2))
+
+#define URCU_ARCH_NIOS2 1
+#include <urcu/arch/nios2.h>
+
+#elif defined(__tilegx__)
+/*
+ * URCU has only been tested on the TileGx architecture. For other Tile*
+ * architectures, please run the tests first and report the results to the
+ * maintainer so that proper support can be added.
+ */
+
+#define URCU_ARCH_TILE 1
+#include <urcu/arch/tile.h>
+
+#elif (defined(__hppa__) || defined(__HPPA__) || defined(__hppa))
+
+#define URCU_ARCH_HPPA 1
+#include <urcu/arch/hppa.h>
+
+#elif defined(__m68k__)
+
+#define URCU_ARCH_M68K 1
+#include <urcu/arch/m68k.h>
+
+#elif defined(__riscv)
+
+#define URCU_ARCH_RISCV 1
+#include <urcu/arch/riscv.h>
+
+#else
+#error "Cannot build: unrecognized architecture, see <urcu/arch.h>."
+#endif
+
+
+#endif /* _URCU_ARCH_H */
+++ /dev/null
-#ifndef _URCU_ARCH_UNKNOWN_H
-#define _URCU_ARCH_UNKNOWN_H
-
-/*
- * arch_unknown.h: #error to prevent build on unknown architectures.
- *
- * Copyright (c) 2010 Paul E. McKenney, IBM Corporation.
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* See configure.ac for the list of recognized architectures. */
-#error "Cannot build: unrecognized architecture detected."
-
-#endif /* _URCU_ARCH_UNKNOWN_H */
#define CAA_CACHE_LINE_SIZE 128
-#ifdef CONFIG_RCU_HAVE_FENCE
+/*
+ * For now, using lock; addl compatibility mode even for i686, because the
+ * Pentium III is seen as a i686, but lacks mfence instruction. Only using
+ * fence for x86_64.
+ *
+ * k1om (__MIC__) is the name for the Intel MIC family (Xeon Phi). It is an
+ * x86_64 variant but lacks fence instructions.
+ */
+#if (defined(URCU_ARCH_AMD64) && !defined(URCU_ARCH_K1OM))
+
+/* For backwards compat */
+#define CONFIG_RCU_HAVE_FENCE 1
+
#define cmm_mb() __asm__ __volatile__ ("mfence":::"memory")
/*
#define cmm_wmb() __asm__ __volatile__ ("sfence"::: "memory")
#define cmm_smp_rmb() cmm_barrier()
#define cmm_smp_wmb() cmm_barrier()
+
#else
+
/*
* We leave smp_rmb/smp_wmb as full barriers for processors that do not have
* fence instructions.
/* urcu/config.h.in. Manually generated for control over the contained defs. */
-/* Defined when on a system that has memory fence instructions. */
-#undef CONFIG_RCU_HAVE_FENCE
-
/* Defined when on a system with futex support. */
#undef CONFIG_RCU_HAVE_FUTEX
behavior of SMP systems is undefined. */
#undef CONFIG_RCU_SMP
-/* Compatibility mode for i386 which lacks cmpxchg instruction. */
-#undef CONFIG_RCU_COMPAT_ARCH
-
/* Use the dmb instruction is available for use on ARM. */
#undef CONFIG_RCU_ARM_HAVE_DMB
--- /dev/null
+/*
+ * urcu/uatomic.h
+ *
+ * Copyright (c) 2020 Michael Jeanson <michael.jeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _URCU_UATOMIC_H
+#define _URCU_UATOMIC_H
+
+#include <urcu/arch.h>
+
+#if defined(URCU_ARCH_X86)
+#include <urcu/uatomic/x86.h>
+#elif defined(URCU_ARCH_PPC)
+#include <urcu/uatomic/ppc.h>
+#elif defined(URCU_ARCH_S390)
+#include <urcu/uatomic/s390.h>
+#elif defined(URCU_ARCH_SPARC64)
+#include <urcu/uatomic/sparc64.h>
+#elif defined(URCU_ARCH_ALPHA)
+#include <urcu/uatomic/alpha.h>
+#elif defined(URCU_ARCH_IA64)
+#include <urcu/uatomic/ia64.h>
+#elif defined(URCU_ARCH_ARM)
+#include <urcu/uatomic/arm.h>
+#elif defined(URCU_ARCH_AARCH64)
+#include <urcu/uatomic/aarch64.h>
+#elif defined(URCU_ARCH_MIPS)
+#include <urcu/uatomic/mips.h>
+#elif defined(URCU_ARCH_NIOS2)
+#include <urcu/uatomic/nios2.h>
+#elif defined(URCU_ARCH_TILE)
+#include <urcu/uatomic/tile.h>
+#elif defined(URCU_ARCH_HPPA)
+#include <urcu/uatomic/hppa.h>
+#elif defined(URCU_ARCH_M68K)
+#include <urcu/uatomic/m68k.h>
+#elif defined(URCU_ARCH_RISCV)
+#include <urcu/uatomic/riscv.h>
+#else
+#error "Cannot build: unrecognized architecture, see <urcu/arch.h>."
+#endif
+
+#endif /* _URCU_UATOMIC_H */
+++ /dev/null
-#ifndef _URCU_ARCH_UATOMIC_UNKNOWN_H
-#define _URCU_ARCH_UATOMIC_UNKNOWN_H
-
-/*
- * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
- * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
- * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
- * Copyright (c) 2009 Mathieu Desnoyers
- * Copyright (c) 2010 Paul E. McKenney, IBM Corporation
- * (Adapted from uatomic_arch_ppc.h)
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose, provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- */
-
-/* See configure.ac for the list of recognized architectures. */
-#error "Cannot build: unrecognized architecture detected."
-
-#endif /* _URCU_ARCH_UATOMIC_UNKNOWN_H */
* Boehm-Demers-Weiser conservative garbage collector.
*/
+#include <urcu/arch.h>
#include <urcu/config.h>
#include <urcu/compiler.h>
#include <urcu/system.h>
#define _uatomic_dec(addr) (__uatomic_dec((addr), sizeof(*(addr))))
-#if ((CAA_BITS_PER_LONG != 64) && defined(CONFIG_RCU_COMPAT_ARCH))
+#if ((CAA_BITS_PER_LONG != 64) && defined(URCU_ARCH_I386))
+
+/* For backwards compat */
+#define CONFIG_RCU_COMPAT_ARCH 1
+
extern int __rcu_cas_avail;
extern int __rcu_cas_init(void);
dist_noinst_HEADERS = urcu-die.h urcu-wait.h compat-getcpu.h \
compat-rand.h urcu-utils.h
-if COMPAT_ARCH
-COMPAT=compat_arch_@ARCHTYPE@.c
-else
-COMPAT=
-endif
-
-COMPAT+=compat_futex.c
+COMPAT = compat_arch.c compat_futex.c
RCULFHASH = rculfhash.c rculfhash-mm-order.c rculfhash-mm-chunk.c \
rculfhash-mm-mmap.c
pkgconfig_DATA = liburcu-cds.pc liburcu.pc liburcu-bp.pc liburcu-qsbr.pc \
liburcu-signal.pc liburcu-mb.pc
-EXTRA_DIST = compat_arch_x86.c \
+EXTRA_DIST = \
urcu-call-rcu-impl.h \
urcu-defer-impl.h \
rculfhash-internal.h
--- /dev/null
+/*
+ * compat_arch.c
+ *
+ * Userspace RCU library - architecture compatibility checks
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <urcu/arch.h>
+
+#if defined(URCU_ARCH_I386)
+
+#include <stdio.h>
+#include <pthread.h>
+#include <signal.h>
+#include <assert.h>
+#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.
+ */
+int __attribute__((constructor)) __rcu_cas_init(void);
+
+/*
+ * -1: unknown
+ * 1: available
+ * 0: unavailable
+ */
+__attribute__((weak))
+int __rcu_cas_avail = -1;
+
+__attribute__((weak))
+pthread_mutex_t __urcu_x86_compat_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * get_eflags/set_eflags/compare_and_swap_is_available imported from glibc
+ * 2.3.5. linuxthreads/sysdeps/i386/pt-machine.h.
+ */
+
+static int get_eflags (void)
+{
+ int res;
+ __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : );
+ return res;
+}
+
+static void set_eflags (int newflags)
+{
+ __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc");
+}
+
+static int compare_and_swap_is_available (void)
+{
+ int oldflags = get_eflags ();
+ int changed;
+ /* Flip AC bit in EFLAGS. */
+ set_eflags (oldflags ^ 0x40000);
+ /* See if bit changed. */
+ changed = (get_eflags () ^ oldflags) & 0x40000;
+ /* Restore EFLAGS. */
+ set_eflags (oldflags);
+ /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
+ Otherwise, it's a 486 or above and it has cmpxchg. */
+ return changed != 0;
+}
+
+static void mutex_lock_signal_save(pthread_mutex_t *mutex, sigset_t *oldmask)
+{
+ sigset_t newmask;
+ int ret;
+
+ /* Disable signals */
+ ret = sigfillset(&newmask);
+ assert(!ret);
+ ret = pthread_sigmask(SIG_BLOCK, &newmask, oldmask);
+ assert(!ret);
+ ret = pthread_mutex_lock(&__urcu_x86_compat_mutex);
+ assert(!ret);
+}
+
+static void mutex_lock_signal_restore(pthread_mutex_t *mutex, sigset_t *oldmask)
+{
+ int ret;
+
+ ret = pthread_mutex_unlock(&__urcu_x86_compat_mutex);
+ assert(!ret);
+ ret = pthread_sigmask(SIG_SETMASK, oldmask, NULL);
+ assert(!ret);
+}
+
+unsigned long _compat_uatomic_set(void *addr, unsigned long _new, int len)
+{
+ sigset_t mask;
+ unsigned long result;
+
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ *(unsigned char *)addr = (unsigned char)_new;
+ result = *(unsigned char *)addr;
+ break;
+ case 2:
+ *(unsigned short *)addr = (unsigned short)_new;
+ result = *(unsigned short *)addr;
+ break;
+ case 4:
+ *(unsigned int *)addr = (unsigned int)_new;
+ result = *(unsigned int *)addr;
+ break;
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ result = 0;
+ __asm__ __volatile__("ud2");
+ }
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
+ return result;
+}
+
+unsigned long _compat_uatomic_xchg(void *addr, unsigned long _new, int len)
+{
+ sigset_t mask;
+ unsigned long retval;
+
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ retval = *(unsigned char *)addr;
+ *(unsigned char *)addr = (unsigned char)_new;
+ break;
+ case 2:
+ retval = *(unsigned short *)addr;
+ *(unsigned short *)addr = (unsigned short)_new;
+ break;
+ case 4:
+ retval = *(unsigned int *)addr;
+ *(unsigned int *)addr = (unsigned int)_new;
+ break;
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ retval = 0; /* silence gcc warnings */
+ __asm__ __volatile__("ud2");
+ }
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
+ return retval;
+}
+
+unsigned long _compat_uatomic_cmpxchg(void *addr, unsigned long old,
+ unsigned long _new, int len)
+{
+ unsigned long retval;
+ sigset_t mask;
+
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ {
+ unsigned char result = *(unsigned char *)addr;
+ if (result == (unsigned char)old)
+ *(unsigned char *)addr = (unsigned char)_new;
+ retval = result;
+ break;
+ }
+ case 2:
+ {
+ unsigned short result = *(unsigned short *)addr;
+ if (result == (unsigned short)old)
+ *(unsigned short *)addr = (unsigned short)_new;
+ retval = result;
+ break;
+ }
+ case 4:
+ {
+ unsigned int result = *(unsigned int *)addr;
+ if (result == (unsigned int)old)
+ *(unsigned int *)addr = (unsigned int)_new;
+ retval = result;
+ break;
+ }
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ retval = 0; /* silence gcc warnings */
+ __asm__ __volatile__("ud2");
+ }
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
+ return retval;
+}
+
+void _compat_uatomic_or(void *addr, unsigned long v, int len)
+{
+ sigset_t mask;
+
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ *(unsigned char *)addr |= (unsigned char)v;
+ break;
+ case 2:
+ *(unsigned short *)addr |= (unsigned short)v;
+ break;
+ case 4:
+ *(unsigned int *)addr |= (unsigned int)v;
+ break;
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ __asm__ __volatile__("ud2");
+ }
+ 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(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ *(unsigned char *)addr &= (unsigned char)v;
+ break;
+ case 2:
+ *(unsigned short *)addr &= (unsigned short)v;
+ break;
+ case 4:
+ *(unsigned int *)addr &= (unsigned int)v;
+ break;
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ __asm__ __volatile__("ud2");
+ }
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
+}
+
+unsigned long _compat_uatomic_add_return(void *addr, unsigned long v, int len)
+{
+ sigset_t mask;
+ unsigned long result;
+
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ *(unsigned char *)addr += (unsigned char)v;
+ result = *(unsigned char *)addr;
+ break;
+ case 2:
+ *(unsigned short *)addr += (unsigned short)v;
+ result = *(unsigned short *)addr;
+ break;
+ case 4:
+ *(unsigned int *)addr += (unsigned int)v;
+ result = *(unsigned int *)addr;
+ break;
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ result = 0; /* silence gcc warnings */
+ __asm__ __volatile__("ud2");
+ }
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
+ return result;
+}
+
+int __rcu_cas_init(void)
+{
+ if (__rcu_cas_avail < 0)
+ __rcu_cas_avail = compare_and_swap_is_available();
+ return __rcu_cas_avail;
+}
+#endif
+++ /dev/null
-/*
- * compat_arch_x86.c
- *
- * Userspace RCU library - x86 compatibility checks
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdio.h>
-#include <pthread.h>
-#include <signal.h>
-#include <assert.h>
-#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.
- */
-int __attribute__((constructor)) __rcu_cas_init(void);
-
-/*
- * -1: unknown
- * 1: available
- * 0: unavailable
- */
-__attribute__((weak))
-int __rcu_cas_avail = -1;
-
-__attribute__((weak))
-pthread_mutex_t __urcu_x86_compat_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/*
- * get_eflags/set_eflags/compare_and_swap_is_available imported from glibc
- * 2.3.5. linuxthreads/sysdeps/i386/pt-machine.h.
- */
-
-static int get_eflags (void)
-{
- int res;
- __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : );
- return res;
-}
-
-static void set_eflags (int newflags)
-{
- __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc");
-}
-
-static int compare_and_swap_is_available (void)
-{
- int oldflags = get_eflags ();
- int changed;
- /* Flip AC bit in EFLAGS. */
- set_eflags (oldflags ^ 0x40000);
- /* See if bit changed. */
- changed = (get_eflags () ^ oldflags) & 0x40000;
- /* Restore EFLAGS. */
- set_eflags (oldflags);
- /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
- Otherwise, it's a 486 or above and it has cmpxchg. */
- return changed != 0;
-}
-
-static void mutex_lock_signal_save(pthread_mutex_t *mutex, sigset_t *oldmask)
-{
- sigset_t newmask;
- int ret;
-
- /* Disable signals */
- ret = sigfillset(&newmask);
- assert(!ret);
- ret = pthread_sigmask(SIG_BLOCK, &newmask, oldmask);
- assert(!ret);
- ret = pthread_mutex_lock(&__urcu_x86_compat_mutex);
- assert(!ret);
-}
-
-static void mutex_lock_signal_restore(pthread_mutex_t *mutex, sigset_t *oldmask)
-{
- int ret;
-
- ret = pthread_mutex_unlock(&__urcu_x86_compat_mutex);
- assert(!ret);
- ret = pthread_sigmask(SIG_SETMASK, oldmask, NULL);
- assert(!ret);
-}
-
-unsigned long _compat_uatomic_set(void *addr, unsigned long _new, int len)
-{
- sigset_t mask;
- unsigned long result;
-
- mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
- switch (len) {
- case 1:
- *(unsigned char *)addr = (unsigned char)_new;
- result = *(unsigned char *)addr;
- break;
- case 2:
- *(unsigned short *)addr = (unsigned short)_new;
- result = *(unsigned short *)addr;
- break;
- case 4:
- *(unsigned int *)addr = (unsigned int)_new;
- result = *(unsigned int *)addr;
- break;
- default:
- /*
- * generate an illegal instruction. Cannot catch this with
- * linker tricks when optimizations are disabled.
- */
- result = 0;
- __asm__ __volatile__("ud2");
- }
- mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
- return result;
-}
-
-unsigned long _compat_uatomic_xchg(void *addr, unsigned long _new, int len)
-{
- sigset_t mask;
- unsigned long retval;
-
- mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
- switch (len) {
- case 1:
- retval = *(unsigned char *)addr;
- *(unsigned char *)addr = (unsigned char)_new;
- break;
- case 2:
- retval = *(unsigned short *)addr;
- *(unsigned short *)addr = (unsigned short)_new;
- break;
- case 4:
- retval = *(unsigned int *)addr;
- *(unsigned int *)addr = (unsigned int)_new;
- break;
- default:
- /*
- * generate an illegal instruction. Cannot catch this with
- * linker tricks when optimizations are disabled.
- */
- retval = 0; /* silence gcc warnings */
- __asm__ __volatile__("ud2");
- }
- mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
- return retval;
-}
-
-unsigned long _compat_uatomic_cmpxchg(void *addr, unsigned long old,
- unsigned long _new, int len)
-{
- unsigned long retval;
- sigset_t mask;
-
- mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
- switch (len) {
- case 1:
- {
- unsigned char result = *(unsigned char *)addr;
- if (result == (unsigned char)old)
- *(unsigned char *)addr = (unsigned char)_new;
- retval = result;
- break;
- }
- case 2:
- {
- unsigned short result = *(unsigned short *)addr;
- if (result == (unsigned short)old)
- *(unsigned short *)addr = (unsigned short)_new;
- retval = result;
- break;
- }
- case 4:
- {
- unsigned int result = *(unsigned int *)addr;
- if (result == (unsigned int)old)
- *(unsigned int *)addr = (unsigned int)_new;
- retval = result;
- break;
- }
- default:
- /*
- * generate an illegal instruction. Cannot catch this with
- * linker tricks when optimizations are disabled.
- */
- retval = 0; /* silence gcc warnings */
- __asm__ __volatile__("ud2");
- }
- mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
- return retval;
-}
-
-void _compat_uatomic_or(void *addr, unsigned long v, int len)
-{
- sigset_t mask;
-
- mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
- switch (len) {
- case 1:
- *(unsigned char *)addr |= (unsigned char)v;
- break;
- case 2:
- *(unsigned short *)addr |= (unsigned short)v;
- break;
- case 4:
- *(unsigned int *)addr |= (unsigned int)v;
- break;
- default:
- /*
- * generate an illegal instruction. Cannot catch this with
- * linker tricks when optimizations are disabled.
- */
- __asm__ __volatile__("ud2");
- }
- 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(&__urcu_x86_compat_mutex, &mask);
- switch (len) {
- case 1:
- *(unsigned char *)addr &= (unsigned char)v;
- break;
- case 2:
- *(unsigned short *)addr &= (unsigned short)v;
- break;
- case 4:
- *(unsigned int *)addr &= (unsigned int)v;
- break;
- default:
- /*
- * generate an illegal instruction. Cannot catch this with
- * linker tricks when optimizations are disabled.
- */
- __asm__ __volatile__("ud2");
- }
- mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
-}
-
-unsigned long _compat_uatomic_add_return(void *addr, unsigned long v, int len)
-{
- sigset_t mask;
- unsigned long result;
-
- mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
- switch (len) {
- case 1:
- *(unsigned char *)addr += (unsigned char)v;
- result = *(unsigned char *)addr;
- break;
- case 2:
- *(unsigned short *)addr += (unsigned short)v;
- result = *(unsigned short *)addr;
- break;
- case 4:
- *(unsigned int *)addr += (unsigned int)v;
- result = *(unsigned int *)addr;
- break;
- default:
- /*
- * generate an illegal instruction. Cannot catch this with
- * linker tricks when optimizations are disabled.
- */
- result = 0; /* silence gcc warnings */
- __asm__ __volatile__("ud2");
- }
- mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
- return result;
-}
-
-int __rcu_cas_init(void)
-{
- if (__rcu_cas_avail < 0)
- __rcu_cas_avail = compare_and_swap_is_available();
- return __rcu_cas_avail;
-}
* Returns 0 if no bit is set, else returns the position of the most
* significant bit (from 1 to 32 on 32-bit, from 1 to 64 on 64-bit).
*/
-#if defined(__i386) || defined(__x86_64)
+#if defined(URCU_ARCH_X86)
static inline
unsigned int fls_u32(uint32_t x)
{
#define HAS_FLS_U32
#endif
-#if defined(__x86_64)
+#if defined(URCU_ARCH_AMD64)
static inline
unsigned int fls_u64(uint64_t x)
{