From 7d413817f09b2d17b1a79ea012590609ffab5eb6 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 7 Oct 2009 23:48:37 -0400 Subject: [PATCH] Add compatibility support for older intel cpus Signed-off-by: Mathieu Desnoyers --- Makefile.am | 25 +++++++++++++++++-------- README | 20 ++++++++++++++++---- configure.ac | 29 ++++++++++++++++++++++++++--- tests/Makefile.am | 18 ++++++++++++------ urcu-pointer.c | 6 +++++- urcu/arch_ppc.h | 4 +--- urcu/arch_s390.h | 3 +-- urcu/arch_x86.h | 4 +--- urcu/uatomic_arch_ppc.h | 3 +++ urcu/uatomic_arch_s390.h | 2 ++ urcu/uatomic_arch_x86.h | 16 ++++++++++++++++ 11 files changed, 100 insertions(+), 30 deletions(-) diff --git a/Makefile.am b/Makefile.am index 623c193..f7d64f6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,29 +9,38 @@ include_HEADERS = urcu.h $(top_srcdir)/urcu-*.h nobase_dist_include_HEADERS = urcu/compiler.h urcu/hlist.h urcu/list.h urcu/rculist.h urcu/system.h nobase_nodist_include_HEADERS = urcu/arch.h urcu/uatomic_arch.h -EXTRA_DIST = $(top_srcdir)/urcu/arch_*.h $(top_srcdir)/urcu/uatomic_arch_*.h gpl-2.0.txt lgpl-2.1.txt lgpl-relicensing.txt README LICENSE +EXTRA_DIST = $(top_srcdir)/urcu/arch_*.h $(top_srcdir)/urcu/uatomic_arch_*.h \ + gpl-2.0.txt lgpl-2.1.txt lgpl-relicensing.txt \ + README LICENSE compat_arch_x86.c + +if COMPAT_ARCH +COMPAT=compat_arch_@ARCHTYPE@.c +else +COMPAT= +endif + lib_LTLIBRARIES = liburcu.la liburcu-mb.la liburcu-defer.la liburcu-qsbr.la liburcu-bp.la -liburcu_la_SOURCES = urcu.c urcu-pointer.c +liburcu_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT) -liburcu_mb_la_SOURCES = urcu.c urcu-pointer.c +liburcu_mb_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT) liburcu_mb_la_CFLAGS = -DURCU_MB -liburcu_bp_la_SOURCES = urcu-bp.c urcu-pointer.c +liburcu_bp_la_SOURCES = urcu-bp.c urcu-pointer.c $(COMPAT) -liburcu_defer_la_SOURCES = urcu-defer.c +liburcu_defer_la_SOURCES = urcu-defer.c $(COMPAT) -liburcu_qsbr_la_SOURCES = urcu-qsbr.c urcu-pointer.c +liburcu_qsbr_la_SOURCES = urcu-qsbr.c urcu-pointer.c $(COMPAT) *.h *.c: urcu/arch.h urcu/uatomic_arch.h urcu/arch.h: $(top_srcdir)/urcu/arch_@ARCHTYPE@.h - mkdir -p $(top_builddir)/urcu + $(MKDIR_P) $(top_builddir)/urcu cp -f $(top_srcdir)/urcu/arch_@ARCHTYPE@.h $(top_builddir)/urcu/arch.h urcu/uatomic_arch.h: $(top_srcdir)/urcu/uatomic_arch_@ARCHTYPE@.h - mkdir -p $(top_builddir)/urcu + $(MKDIR_P) $(top_builddir)/urcu cp -f $(top_srcdir)/urcu/uatomic_arch_@ARCHTYPE@.h $(top_builddir)/urcu/uatomic_arch.h clean-local: diff --git a/README b/README index f9437db..0f92ac6 100644 --- a/README +++ b/README @@ -9,20 +9,22 @@ BUILDING make make install - Note: Forcing 32-bit build: + Hints: Forcing 32-bit build: * CFLAGS=-m32 ./configure Forcing 64-bit build: * CFLAGS=-m64 ./configure + Forcing a 32-bit build with down to 386 compatibility: + * CFLAGS=-m32 ./configure --target=i386-pc-linux-gnu + ARCHITECTURES SUPPORTED ----------------------- -Currently, x86 (only P6+), x86 64, PowerPC 32/64 and S390 are +Currently, x86 (i386, i486, i586, i686), x86 64, PowerPC 32/64 and S390 are supported. The current use of sys_futex() makes it Linux-dependent, although this portability limitation might go away in a near future by using the pthread -cond vars. Also, the restriction against i386, i486 and Pentium might go away if -we integrate some of glibc runtime CPU-detection tests. +cond vars. QUICK START GUIDE ----------------- @@ -136,3 +138,13 @@ Usage of DEBUG_YIELD DEBUG_YIELD is used to add random delays in the code for testing purposes. + +SMP support + + By default the library is configured to use synchronization primitives + adequate for SMP systems. On uniprocessor systems, support for SMP + systems can be disabled with: + + ./configure --disable-smp-support + + theoretically yielding slightly better performance. diff --git a/configure.ac b/configure.ac index 4d0cbec..422b11b 100644 --- a/configure.ac +++ b/configure.ac @@ -4,8 +4,12 @@ AC_INIT([userspace-rcu], [0.2.3-alpha], [mathieu dot desnoyers at polymtl dot ca]) AC_CONFIG_AUX_DIR([config]) +AC_CANONICAL_TARGET +AC_CANONICAL_HOST AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip]) AC_CONFIG_SRCDIR([urcu.h]) + +AH_TEMPLATE([CONFIG_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.]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. @@ -24,12 +28,15 @@ AC_FUNC_MMAP AC_CHECK_FUNCS([bzero gettimeofday munmap strtoul]) # Find arch type -case $host_cpu in +case $target_cpu in + i386) ARCHTYPE="x86"; SUBARCHTYPE="x86compat" ;; + i486) ARCHTYPE="x86"; SUBARCHTYPE="x86compat" ;; + i586) ARCHTYPE="x86"; SUBARCHTYPE="x86compat" ;; + i686) ARCHTYPE="x86"; SUBARCHTYPE="x86compat" ;; x86_64) ARCHTYPE="x86";; - i586) ARCHTYPE="x86" ;; - i686) ARCHTYPE="x86" ;; powerpc) ARCHTYPE="ppc" ;; ppc64) ARCHTYPE="ppc" ;; + powerpc64) ARCHTYPE="ppc" ;; ppc) ARCHTYPE="ppc" ;; s390) ARCHTYPE="s390" ;; s390x) ARCHTYPE="s390" ;; @@ -40,9 +47,25 @@ if test "$ARCHTYPE" = "unknown"; then AC_MSG_ERROR([Unable to detect the architecture.]) fi AC_SUBST(ARCHTYPE) +AC_SUBST(SUBARCHTYPE) AM_CONDITIONAL([GCC_API], [test "x$ARCHTYPE" != xx86 -a "x$ARCHTYPE" != xppc]) +AM_CONDITIONAL([COMPAT_ARCH], [test "x$SUBARCHTYPE" == xx86compat ]) + +AC_ARG_ENABLE([smp-support], [ --disable-smp-support Disable SMP support. Warning: only use this + on uniprocessor systems. [[default=enabled]]], [def_smp_support=$enableval], [def_smp_support="yes"]) + +[ +if test "$def_smp_support" = "no"; then + echo "SMP support disabled." +else +] + AC_DEFINE([CONFIG_SMP], [1]) +[ + echo "SMP support enabled." +fi +] AC_CONFIG_FILES([ Makefile diff --git a/tests/Makefile.am b/tests/Makefile.am index b1be5b1..983ee67 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,15 +13,21 @@ noinst_PROGRAMS = test_urcu test_urcu_dynamic_link test_urcu_timing \ noinst_HEADERS = rcutorture.h -URCU_SIGNAL=$(top_builddir)/urcu.c $(top_builddir)/urcu-pointer.c +if COMPAT_ARCH +COMPAT=$(top_builddir)/compat_arch_@ARCHTYPE@.c +else +COMPAT= +endif + +URCU_SIGNAL=$(top_builddir)/urcu.c $(top_builddir)/urcu-pointer.c $(COMPAT) # URCU_SIGNAL_YIELD uses urcu.c but -DDEBUG_YIELD must be defined -URCU_SIGNAL_YIELD=$(top_builddir)/urcu.c $(top_builddir)/urcu-pointer.c +URCU_SIGNAL_YIELD=$(top_builddir)/urcu.c $(top_builddir)/urcu-pointer.c $(COMPAT) # URCU_MB uses urcu.c but -DURCU_MB must be defined -URCU_MB=$(top_builddir)/urcu.c $(top_builddir)/urcu-pointer.c -URCU_BP=$(top_builddir)/urcu-bp.c $(top_builddir)/urcu-pointer.c -URCU_QSBR=$(top_builddir)/urcu-qsbr.c $(top_builddir)/urcu-pointer.c +URCU_MB=$(top_builddir)/urcu.c $(top_builddir)/urcu-pointer.c $(COMPAT) +URCU_BP=$(top_builddir)/urcu-bp.c $(top_builddir)/urcu-pointer.c $(COMPAT) +URCU_QSBR=$(top_builddir)/urcu-qsbr.c $(top_builddir)/urcu-pointer.c $(COMPAT) # -DURCU_MB must be defined -URCU_MB_DEFER=$(top_builddir)/urcu.c $(top_builddir)/urcu-defer.c $(top_builddir)/urcu-pointer.c +URCU_MB_DEFER=$(top_builddir)/urcu.c $(top_builddir)/urcu-defer.c $(top_builddir)/urcu-pointer.c $(COMPAT) if GCC_API diff --git a/urcu-pointer.c b/urcu-pointer.c index da8b1ea..79ee72a 100644 --- a/urcu-pointer.c +++ b/urcu-pointer.c @@ -50,5 +50,9 @@ void *rcu_xchg_pointer_sym(void **p, void *v) void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new) { wmb(); - return uatomic_cmpxchg(p, old, _new); + if (likely(URCU_CAS_AVAIL())) + return uatomic_cmpxchg(p, old, _new); + + /* Compatibility for i386. Old-timer. */ + return compat_uatomic_cmpxchg(p, old, _new); } diff --git a/urcu/arch_ppc.h b/urcu/arch_ppc.h index edd1139..40a4359 100644 --- a/urcu/arch_ppc.h +++ b/urcu/arch_ppc.h @@ -23,6 +23,7 @@ */ #include +#include "config.h" #define CONFIG_HAVE_FENCE 1 #define CONFIG_HAVE_MEM_COHERENCY @@ -53,9 +54,6 @@ #define rmc() barrier() #define wmc() barrier() -/* Assume SMP machine, given we don't have this information */ -#define CONFIG_SMP 1 - #ifdef CONFIG_SMP #define smp_mb() mb() #define smp_rmb() rmb() diff --git a/urcu/arch_s390.h b/urcu/arch_s390.h index 7171768..1a43c6c 100644 --- a/urcu/arch_s390.h +++ b/urcu/arch_s390.h @@ -29,10 +29,9 @@ */ #include +#include "config.h" #define CONFIG_HAVE_MEM_COHERENCY -/* Assume SMP machine, given we don't have this information */ -#define CONFIG_SMP 1 #ifndef BITS_PER_LONG #define BITS_PER_LONG (__SIZEOF_LONG__ * 8) diff --git a/urcu/arch_x86.h b/urcu/arch_x86.h index 66b27d5..806878e 100644 --- a/urcu/arch_x86.h +++ b/urcu/arch_x86.h @@ -23,6 +23,7 @@ */ #include +#include "config.h" /* Assume P4 or newer */ #define CONFIG_HAVE_FENCE 1 @@ -63,9 +64,6 @@ #define rmc() barrier() #define wmc() barrier() -/* Assume SMP machine, given we don't have this information */ -#define CONFIG_SMP 1 - #ifdef CONFIG_SMP #define smp_mb() mb() #define smp_rmb() rmb() diff --git a/urcu/uatomic_arch_ppc.h b/urcu/uatomic_arch_ppc.h index 40de9ff..68b5faa 100644 --- a/urcu/uatomic_arch_ppc.h +++ b/urcu/uatomic_arch_ppc.h @@ -228,4 +228,7 @@ unsigned long _uatomic_add_return(void *addr, unsigned long val, #define uatomic_inc(addr) uatomic_add((addr), 1) #define uatomic_dec(addr) uatomic_add((addr), -1) +#define URCU_CAS_AVAIL() 1 +#define compat_uatomic_cmpxchg(ptr, old, _new) uatomic_cmpxchg(ptr, old, _new) + #endif /* _URCU_ARCH_UATOMIC_PPC_H */ diff --git a/urcu/uatomic_arch_s390.h b/urcu/uatomic_arch_s390.h index 917dbf2..b37e5f0 100644 --- a/urcu/uatomic_arch_s390.h +++ b/urcu/uatomic_arch_s390.h @@ -217,4 +217,6 @@ unsigned long _uatomic_cmpxchg(void *addr, unsigned long old, (unsigned long)(new), \ sizeof(*(addr))) +#define URCU_CAS_AVAIL() 1 + #endif /* _URCU_ARCH_ATOMIC_S390_H */ diff --git a/urcu/uatomic_arch_x86.h b/urcu/uatomic_arch_x86.h index 43de9e6..fccea8e 100644 --- a/urcu/uatomic_arch_x86.h +++ b/urcu/uatomic_arch_x86.h @@ -397,4 +397,20 @@ void _uatomic_dec(void *addr, int len) #define uatomic_dec(addr) (_uatomic_dec((addr), sizeof(*(addr)))) +#if (BITS_PER_LONG == 64) +#define URCU_CAS_AVAIL() 1 +#define compat_uatomic_cmpxchg(ptr, old, _new) uatomic_cmpxchg(ptr, old, _new) +#else +extern int __urcu_cas_avail; +#define URCU_CAS_AVAIL() __urcu_cas_avail + +extern unsigned long _compat_uatomic_cmpxchg(void *addr, unsigned long old, + unsigned long _new, int len); + +#define compat_uatomic_cmpxchg(addr, old, _new) \ + ((__typeof__(*(addr))) _uatomic_cmpxchg((addr), (unsigned long)(old),\ + (unsigned long)(_new), \ + sizeof(*(addr)))) +#endif + #endif /* _URCU_ARCH_UATOMIC_X86_H */ -- 2.34.1