From: Michael Jeanson Date: Tue, 17 Nov 2020 23:08:49 +0000 (-0500) Subject: Static arch and uatomic headers X-Git-Tag: v0.13.0~51 X-Git-Url: http://git.lttng.org/?p=urcu.git;a=commitdiff_plain;h=0b1e236d1711f4f9076f73a093ece05aca00eca4 Static arch and uatomic headers Replace the somewhat hackish symlinking of architecture specific headers at configure time with compile time detection using compiler defines. This would allow sharing headers in a multi-arch environment and reduce the build system complexity. Change-Id: I4900a18dab70bb0e51d1a8500581a445acd44cdf Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- diff --git a/.gitignore b/.gitignore index e54aefd..be01a12 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -include/urcu/arch.h -include/urcu/uatomic.h tests/api.h diff --git a/configure.ac b/configure.ac index 73ab19f..82f0c46 100644 --- a/configure.ac +++ b/configure.ac @@ -21,9 +21,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 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.]) @@ -118,58 +116,17 @@ AC_CHECK_HEADERS([ \ 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() @@ -186,40 +143,6 @@ AS_IF([test "x$ARCHTYPE" = "xarm"],[ ]) ]) -# 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([[ @@ -244,7 +167,6 @@ AC_SEARCH_LIBS([clock_gettime], [rt], [ ], []) 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 @@ -377,10 +299,6 @@ AC_SUBST(AM_CPPFLAGS) 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 @@ -485,10 +403,6 @@ PPRINT_PROP_STRING([Target architecture], $host_cpu) 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) diff --git a/include/Makefile.am b/include/Makefile.am index 8f83641..3f92cc3 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,36 +1,10 @@ -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 \ @@ -41,13 +15,56 @@ EXTRA_DIST = urcu/arch/aarch64.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 \ @@ -58,5 +75,28 @@ EXTRA_DIST = urcu/arch/aarch64.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 diff --git a/include/urcu/arch.h b/include/urcu/arch.h new file mode 100644 index 0000000..fdbec3d --- /dev/null +++ b/include/urcu/arch.h @@ -0,0 +1,157 @@ +/* + * urcu/arch.h + * + * Copyright (c) 2020 Michael Jeanson + * + * 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 + +#elif (defined(__i486__) || defined(__i586__) || defined(__i686__)) + +#define URCU_ARCH_X86 1 +#include + +#elif (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)) + +#define URCU_ARCH_X86 1 +#define URCU_ARCH_AMD64 1 +#include + +#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 + +#elif (defined(__powerpc__) || defined(__powerpc) || defined(__ppc__)) + +#define URCU_ARCH_PPC 1 +#include + +#elif (defined(__powerpc64__) || defined(__ppc64__)) + +#define URCU_ARCH_PPC 1 +#define URCU_ARCH_PPC64 1 +#include + +#elif (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) + +#define URCU_ARCH_S390 1 +#include + +#elif (defined(__sparc__) || defined(__sparc) || defined(__sparc64__)) + +#define URCU_ARCH_SPARC64 1 +#include + +#elif (defined(__alpha__) || defined(__alpha)) + +#define URCU_ARCH_ALPHA 1 +#include + +#elif (defined(__ia64__) || defined(__ia64)) + +#define URCU_ARCH_IA64 1 +#include + +#elif (defined(__arm__) || defined(__arm)) + +#define URCU_ARCH_ARM 1 +#include + +#elif defined(__aarch64__) + +#define URCU_ARCH_AARCH64 1 +#include + +#elif (defined(__mips__) || defined(__mips)) + +#define URCU_ARCH_MIPS 1 +#include + +#elif (defined(__nios2__) || defined(__nios2)) + +#define URCU_ARCH_NIOS2 1 +#include + +#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 + +#elif (defined(__hppa__) || defined(__HPPA__) || defined(__hppa)) + +#define URCU_ARCH_HPPA 1 +#include + +#elif defined(__m68k__) + +#define URCU_ARCH_M68K 1 +#include + +#elif defined(__riscv) + +#define URCU_ARCH_RISCV 1 +#include + +#else +#error "Cannot build: unrecognized architecture, see ." +#endif + + +#endif /* _URCU_ARCH_H */ diff --git a/include/urcu/arch/unknown.h b/include/urcu/arch/unknown.h deleted file mode 100644 index 701575d..0000000 --- a/include/urcu/arch/unknown.h +++ /dev/null @@ -1,28 +0,0 @@ -#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 - * - * 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 */ diff --git a/include/urcu/arch/x86.h b/include/urcu/arch/x86.h index aac8ca1..744f9f9 100644 --- a/include/urcu/arch/x86.h +++ b/include/urcu/arch/x86.h @@ -33,7 +33,19 @@ extern "C" { #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") /* @@ -45,7 +57,9 @@ extern "C" { #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. diff --git a/include/urcu/config.h.in b/include/urcu/config.h.in index 7350631..38094a6 100644 --- a/include/urcu/config.h.in +++ b/include/urcu/config.h.in @@ -1,8 +1,5 @@ /* 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 @@ -11,9 +8,6 @@ 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 diff --git a/include/urcu/uatomic.h b/include/urcu/uatomic.h new file mode 100644 index 0000000..2fb5fd4 --- /dev/null +++ b/include/urcu/uatomic.h @@ -0,0 +1,58 @@ +/* + * urcu/uatomic.h + * + * Copyright (c) 2020 Michael Jeanson + * + * 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 + +#if defined(URCU_ARCH_X86) +#include +#elif defined(URCU_ARCH_PPC) +#include +#elif defined(URCU_ARCH_S390) +#include +#elif defined(URCU_ARCH_SPARC64) +#include +#elif defined(URCU_ARCH_ALPHA) +#include +#elif defined(URCU_ARCH_IA64) +#include +#elif defined(URCU_ARCH_ARM) +#include +#elif defined(URCU_ARCH_AARCH64) +#include +#elif defined(URCU_ARCH_MIPS) +#include +#elif defined(URCU_ARCH_NIOS2) +#include +#elif defined(URCU_ARCH_TILE) +#include +#elif defined(URCU_ARCH_HPPA) +#include +#elif defined(URCU_ARCH_M68K) +#include +#elif defined(URCU_ARCH_RISCV) +#include +#else +#error "Cannot build: unrecognized architecture, see ." +#endif + +#endif /* _URCU_UATOMIC_H */ diff --git a/include/urcu/uatomic/unknown.h b/include/urcu/uatomic/unknown.h deleted file mode 100644 index eb18526..0000000 --- a/include/urcu/uatomic/unknown.h +++ /dev/null @@ -1,25 +0,0 @@ -#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 */ diff --git a/include/urcu/uatomic/x86.h b/include/urcu/uatomic/x86.h index 2a4ea1c..ec71e51 100644 --- a/include/urcu/uatomic/x86.h +++ b/include/urcu/uatomic/x86.h @@ -20,6 +20,7 @@ * Boehm-Demers-Weiser conservative garbage collector. */ +#include #include #include #include @@ -517,7 +518,11 @@ void __uatomic_dec(void *addr, int len) #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); diff --git a/src/Makefile.am b/src/Makefile.am index 88ccc1f..f95b37f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,13 +10,7 @@ endif 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 @@ -63,7 +57,7 @@ pkgconfigdir = $(libdir)/pkgconfig 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 diff --git a/src/compat_arch.c b/src/compat_arch.c new file mode 100644 index 0000000..461c709 --- /dev/null +++ b/src/compat_arch.c @@ -0,0 +1,308 @@ +/* + * compat_arch.c + * + * Userspace RCU library - architecture compatibility checks + * + * Copyright (c) 2009 Mathieu Desnoyers + * + * 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 + +#if defined(URCU_ARCH_I386) + +#include +#include +#include +#include +#include + +/* + * 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 diff --git a/src/compat_arch_x86.c b/src/compat_arch_x86.c deleted file mode 100644 index 3e73f9c..0000000 --- a/src/compat_arch_x86.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * compat_arch_x86.c - * - * Userspace RCU library - x86 compatibility checks - * - * Copyright (c) 2009 Mathieu Desnoyers - * - * 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 -#include -#include -#include -#include - -/* - * 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; -} diff --git a/src/rculfhash.c b/src/rculfhash.c index 51972c8..247564b 100644 --- a/src/rculfhash.c +++ b/src/rculfhash.c @@ -467,7 +467,7 @@ unsigned long bit_reverse_ulong(unsigned long v) * 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) { @@ -483,7 +483,7 @@ 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) {