diff --git a/barriers.h b/barriers.h new file mode 100644 index 00000000..8ceae6a5 --- /dev/null +++ b/barriers.h @@ -0,0 +1,137 @@ +/***************************************************************************** + * Properly compiler/memory/coherence barriers + * in the most portable way for ReOpenLDAP project. + * + * Feedback and comments are welcome. + * https://gist.github.com/leo-yuriev/ba186a6bf5cf3a27bae7 */ + +#if defined(__mips) && defined(__linux) + /* Only MIPS has explicit cache control */ +# include +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define MDB_INLINE __inline +#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ +# include +# if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# pragma intrinsic(__mf) +# elif defined(__i386__) || defined(__x86_64__) +# pragma intrinsic(_mm_mfence) +# endif +# define MDB_INLINE __inline +#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) +# include +# define MDB_INLINE inline +#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) \ + && (defined(HP_IA64) || defined(__ia64)) +# include +# define MDB_INLINE +#elif defined(__IBMC__) && defined(__powerpc) +# include +# define MDB_INLINE +#elif defined(_AIX) +# include +# include +# define MDB_INLINE +#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) +# include +# include +# define MDB_INLINE +#elif defined(__MWERKS__) + /* CodeWarrior - troubles ? */ +# pragma gcc_extensions +# define MDB_INLINE +#elif defined(__SNC__) + /* Sony PS3 - troubles ? */ +# define MDB_INLINE +#else +# define MDB_INLINE +#endif + +#if defined(__i386__) || defined(__x86_64__) \ + || defined(_M_AMD64) || defined(_M_IX86) \ + || defined(__i386) || defined(__amd64) \ + || defined(i386) || defined(__x86_64) \ + || defined(_AMD64_) || defined(_M_X64) +# define MDB_CACHE_IS_COHERENT 1 +#elif defined(__hppa) || defined(__hppa__) +# define MDB_CACHE_IS_COHERENT 1 +#endif + +#ifndef MDB_CACHE_IS_COHERENT +# define MDB_CACHE_IS_COHERENT 0 +#endif + +#define MDB_BARRIER_COMPILER 0 +#define MDB_BARRIER_MEMORY 1 + +static MDB_INLINE void mdb_barrier(int type) { +#if defined(__clang__) + __asm__ __volatile__ ("" ::: "memory"); + if (type > MDB_BARRIER_COMPILER) +# if __has_extension(c_atomic) || __has_extension(cxx_atomic) + __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); +# else + __sync_synchronize(); +# endif +#elif defined(__GNUC__) + __asm__ __volatile__ ("" ::: "memory"); + if (type > MDB_BARRIER_COMPILER) +# if defined(__ATOMIC_SEQ_CST) + __atomic_thread_fence(__ATOMIC_SEQ_CST); +# else + __sync_synchronize(); +# endif +#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ + __memory_barrier(); + if (type > MDB_BARRIER_COMPILER) +# if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) + __mf(); +# elif defined(__i386__) || defined(__x86_64__) + _mm_mfence(); +# else +# error "Unknown target for Intel Compiler, please report to us." +# endif +#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) + __compiler_barrier(); + if (type > MDB_BARRIER_COMPILER) + __machine_rw_barrier(); +#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) \ + && (defined(HP_IA64) || defined(__ia64)) + _Asm_sched_fence(/* LY: no-arg meaning 'all expect ALU', e.g. 0x3D3D */); + if (type > MDB_BARRIER_COMPILER) + _Asm_mf(); +#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) \ + || defined(__ppc64__) || defined(__powerpc64__) + __fence(); + if (type > MDB_BARRIER_COMPILER) + __lwsync(); +#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) + __PAL_DRAINA(); /* LY: excessive ? */ + __MB(); +#else +# error "Could not guess the kind of compiler, please report to us." +#endif +} + +#define mdb_compiler_barrier() \ + mdb_barrier(MDB_BARRIER_COMPILER) +#define mdb_memory_barrier() \ + mdb_barrier(MDB_BARRIER_MEMORY) +#define mdb_coherent_barrier() \ + mdb_barrier(MDB_CACHE_IS_COHERENT ? MDB_BARRIER_COMPILER : MDB_BARRIER_MEMORY) + +static MDB_INLINE void mdb_invalidate_cache(void *addr, int nbytes) { + mdb_coherent_barrier(); +#if defined(__mips) && defined(__linux) + /* MIPS has cache coherency issues. + * Note: for any nbytes >= on-chip cache size, entire is flushed. */ + cacheflush(addr, nbytes, DCACHE); +#elif defined(_M_MRX000) || defined(_MIPS_) +# error "Sorry, cacheflush() for MIPS not implemented" +#else + /* LY: assume no mmap/dcache issues. */ +#endif +} + diff --git a/mdb.c b/mdb.c index 82c52d39..1b19574f 100644 --- a/mdb.c +++ b/mdb.c @@ -33,12 +33,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "../../include/reopenldap.h" - #ifndef MDB_DEBUG # define MDB_DEBUG 0 #endif +#include "reopen.h" +#include "barriers.h" + #include #include #include @@ -49,145 +50,6 @@ #endif #include -/***************************************************************************** - * Properly compiler/memory/coherence barriers - * in the most portable way for ReOpenLDAP project. - * - * Feedback and comments are welcome. - * https://gist.github.com/leo-yuriev/ba186a6bf5cf3a27bae7 */ - -#if defined(__mips) && defined(__linux) - /* Only MIPS has explicit cache control */ -# include -#endif - -#if defined(__GNUC__) || defined(__clang__) -# define MDB_INLINE __inline -#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ -# include -# if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) -# pragma intrinsic(__mf) -# elif defined(__i386__) || defined(__x86_64__) -# pragma intrinsic(_mm_mfence) -# endif -# define MDB_INLINE __inline -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) -# include -# define MDB_INLINE inline -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) \ - && (defined(HP_IA64) || defined(__ia64)) -# include -# define MDB_INLINE -#elif defined(__IBMC__) && defined(__powerpc) -# include -# define MDB_INLINE -#elif defined(_AIX) -# include -# include -# define MDB_INLINE -#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) -# include -# include -# define MDB_INLINE -#elif defined(__MWERKS__) - /* CodeWarrior - troubles ? */ -# pragma gcc_extensions -# define MDB_INLINE -#elif defined(__SNC__) - /* Sony PS3 - troubles ? */ -# define MDB_INLINE -#else -# define MDB_INLINE -#endif - -#if defined(__i386__) || defined(__x86_64__) \ - || defined(_M_AMD64) || defined(_M_IX86) \ - || defined(__i386) || defined(__amd64) \ - || defined(i386) || defined(__x86_64) \ - || defined(_AMD64_) || defined(_M_X64) -# define MDB_CACHE_IS_COHERENT 1 -#elif defined(__hppa) || defined(__hppa__) -# define MDB_CACHE_IS_COHERENT 1 -#endif - -#ifndef MDB_CACHE_IS_COHERENT -# define MDB_CACHE_IS_COHERENT 0 -#endif - -#define MDB_BARRIER_COMPILER 0 -#define MDB_BARRIER_MEMORY 1 - -static MDB_INLINE void mdb_barrier(int type) { -#if defined(__clang__) - __asm__ __volatile__ ("" ::: "memory"); - if (type > MDB_BARRIER_COMPILER) -# if __has_extension(c_atomic) || __has_extension(cxx_atomic) - __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); -# else - __sync_synchronize(); -# endif -#elif defined(__GNUC__) - __asm__ __volatile__ ("" ::: "memory"); - if (type > MDB_BARRIER_COMPILER) -# if defined(__ATOMIC_SEQ_CST) - __atomic_thread_fence(__ATOMIC_SEQ_CST); -# else - __sync_synchronize(); -# endif -#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ - __memory_barrier(); - if (type > MDB_BARRIER_COMPILER) -# if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) - __mf(); -# elif defined(__i386__) || defined(__x86_64__) - _mm_mfence(); -# else -# error "Unknown target for Intel Compiler, please report to us." -# endif -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) - __compiler_barrier(); - if (type > MDB_BARRIER_COMPILER) - __machine_rw_barrier(); -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) \ - && (defined(HP_IA64) || defined(__ia64)) - _Asm_sched_fence(/* LY: no-arg meaning 'all expect ALU', e.g. 0x3D3D */); - if (type > MDB_BARRIER_COMPILER) - _Asm_mf(); -#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) \ - || defined(__ppc64__) || defined(__powerpc64__) - __fence(); - if (type > MDB_BARRIER_COMPILER) - __lwsync(); -#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) - __PAL_DRAINA(); /* LY: excessive ? */ - __MB(); -#else -# error "Could not guess the kind of compiler, please report to us." -#endif -} - -#define mdb_compiler_barrier() \ - mdb_barrier(MDB_BARRIER_COMPILER) -#define mdb_memory_barrier() \ - mdb_barrier(MDB_BARRIER_MEMORY) -#define mdb_coherent_barrier() \ - mdb_barrier(MDB_CACHE_IS_COHERENT ? MDB_BARRIER_COMPILER : MDB_BARRIER_MEMORY) - -static MDB_INLINE void mdb_invalidate_cache(void *addr, int nbytes) { - mdb_coherent_barrier(); -#if defined(__mips) && defined(__linux) - /* MIPS has cache coherency issues. - * Note: for any nbytes >= on-chip cache size, entire is flushed. */ - cacheflush(addr, nbytes, DCACHE); -#elif defined(_M_MRX000) || defined(_MIPS_) -# error "Sorry, cacheflush() for MIPS not implemented" -#else - /* LY: assume no mmap/dcache issues. */ -#endif -} - -/*****************************************************************************/ - #include #include #include diff --git a/reopen.h b/reopen.h new file mode 100644 index 00000000..31f2eb30 --- /dev/null +++ b/reopen.h @@ -0,0 +1,219 @@ +/* + Copyright (c) 2015 Leonid Yuriev . + Copyright (c) 2015 Peter-Service R&D LLC. + + This file is part of ReOpenLDAP. + + ReOpenLDAP is free software; you can redistribute it and/or modify it under + the terms of the GNU Affero General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ReOpenLDAP 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/* LY: Please do not ask us for Windows support, just never! + * But you can make a fork for Windows, or become maintainer for FreeBSD... */ +#ifndef __gnu_linux__ +# error "ReOpenLDAP branch supports only GNU Linux" +#endif + +#ifndef _REOPEN_H +#define _REOPEN_H + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#ifdef HAVE_ANSIDECL_H +# include +#endif + +#ifndef __has_attribute +# define __has_attribute(x) (0) +#endif + +#if !defined(GCC_VERSION) && defined(__GNUC__) +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#endif /* GCC_VERSION */ + +#ifndef ALLOW_UNUSED +# ifdef ATTRIBUTE_UNUSED +# define ALLOW_UNUSED ATTRIBUTE_UNUSED +# elif defined(GCC_VERSION) && (GCC_VERSION >= 3004) +# define ALLOW_UNUSED __attribute__((__unused__)) +# elif __has_attribute(__unused__) +# define ALLOW_UNUSED __attribute__((__unused__)) +# elif __has_attribute(unused) +# define ALLOW_UNUSED __attribute__((unused)) +# else +# define ALLOW_UNUSED +# endif +#endif /* ALLOW_UNUSED */ + +#if !defined(__thread) && (defined(_MSC_VER) || defined(__DMC__)) +# define __thread __declspec(thread) +#endif + +#ifndef __forceinline +# if defined(__GNUC__) || defined(__clang__) +# define __forceinline __inline __attribute__((always_inline)) +# elif ! defined(_MSC_VER) +# define __forceinline +# endif +#endif /* __forceinline */ + +#ifndef __must_check_result +# if defined(__GNUC__) || defined(__clang__) +# define __must_check_result __attribute__((warn_unused_result)) +# else +# define __must_check_result +# endif +#endif /* __must_check_result */ + +#ifndef __hot +# if defined(__GNUC__) && !defined(__clang__) +# define __hot __attribute__((hot, optimize("O3"))) +# else +# define __hot +# endif +#endif /* __hot */ + +#ifndef __cold +# if defined(__GNUC__) && !defined(__clang__) +# define __cold __attribute__((cold, optimize("Os"))) +# else +# define __cold +# endif +#endif /* __cold */ + +#ifndef __flatten +# if defined(__GNUC__) || defined(__clang__) +# define __flatten __attribute__((flatten)) +# else +# define __flatten +# endif +#endif /* __flatten */ + +#ifndef __aligned +# if defined(__GNUC__) || defined(__clang__) +# define __aligned(N) __attribute__((aligned(N))) +# elif defined(__MSC_VER) +# define __aligned(N) __declspec(align(N)) +# else +# define __aligned(N) +# endif +#endif /* __align */ + +#ifndef __noreturn +# if defined(__GNUC__) || defined(__clang__) +# define __noreturn __attribute__((noreturn)) +# else +# define __noreturn +# endif +#endif + +#ifndef __nothrow +# if defined(__GNUC__) || defined(__clang__) +# define __nothrow __attribute__((nothrow)) +# else +# define __nothrow +# endif +#endif + +#ifndef CACHELINE_SIZE +# if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define CACHELINE_SIZE 128 +# else +# define CACHELINE_SIZE 64 +# endif +#endif + +#ifndef __cache_aligned +# define __cache_aligned __aligned(CACHELINE_SIZE) +#endif + +#ifndef likely +# if defined(__GNUC__) || defined(__clang__) +# ifdef __cplusplus + /* LY: workaround for "pretty" boost */ + static __inline __attribute__((always_inline)) + bool likely(bool cond) { return __builtin_expect(cond, 1); } +# else +# define likely(cond) __builtin_expect(!!(cond), 1) +# endif +# else +# define likely(x) (x) +# endif +#endif /* likely */ + +#ifndef unlikely +# if defined(__GNUC__) || defined(__clang__) +# ifdef __cplusplus + /* LY: workaround for "pretty" boost */ + static __inline __attribute__((always_inline)) + bool unlikely(bool cond) { return __builtin_expect(cond, 0); } +# else +# define unlikely(cond) __builtin_expect(!!(cond), 0) +# endif +# else +# define unlikely(x) (x) +# endif +#endif /* unlikely */ + +#ifndef __extern_C +# ifdef __cplusplus +# define __extern_C extern "C" +# else +# define __extern_C +# endif +#endif + +#ifndef __noop +# define __noop() do {} while (0) +#endif + +/* -------------------------------------------------------------------------- */ + +#include + +/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 3.1 */ +__extern_C void __assert_fail( + const char* assertion, + const char* file, + unsigned line, + const char* function) __nothrow __noreturn; + +/* -------------------------------------------------------------------------- */ + +#if defined(HAVE_VALGRIND) || defined(USE_VALGRIND) + /* Get debugging help from Valgrind */ +# include +# ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE + /* LY: available since Valgrind 3.10 */ +# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# endif +#else +# define VALGRIND_CREATE_MEMPOOL(h,r,z) +# define VALGRIND_DESTROY_MEMPOOL(h) +# define VALGRIND_MEMPOOL_TRIM(h,a,s) +# define VALGRIND_MEMPOOL_ALLOC(h,a,s) +# define VALGRIND_MEMPOOL_FREE(h,a) +# define VALGRIND_MEMPOOL_CHANGE(h,a,b,s) +# define VALGRIND_MAKE_MEM_NOACCESS(a,s) +# define VALGRIND_MAKE_MEM_DEFINED(a,s) +# define VALGRIND_MAKE_MEM_UNDEFINED(a,s) +# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,s) (0) +# define VALGRIND_CHECK_MEM_IS_DEFINED(a,s) (0) +#endif /* ! USE_VALGRIND */ + +#endif /* _REOPEN_H */