diff options
Diffstat (limited to 'port')
-rw-r--r-- | port/atomic_pointer.h | 18 | ||||
-rw-r--r-- | port/port.h | 2 | ||||
-rw-r--r-- | port/port_example.h | 10 | ||||
-rw-r--r-- | port/port_posix.cc | 4 | ||||
-rw-r--r-- | port/port_posix.h | 33 |
5 files changed, 51 insertions, 16 deletions
diff --git a/port/atomic_pointer.h b/port/atomic_pointer.h index 35ae550..c58bffb 100644 --- a/port/atomic_pointer.h +++ b/port/atomic_pointer.h @@ -73,13 +73,21 @@ inline void MemoryBarrier() { } #define LEVELDB_HAVE_MEMORY_BARRIER -// ARM -#elif defined(ARCH_CPU_ARM_FAMILY) +// ARM Linux +#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__) typedef void (*LinuxKernelMemoryBarrierFunc)(void); -LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = - (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; +// The Linux ARM kernel provides a highly optimized device-specific memory +// barrier function at a fixed memory address that is mapped in every +// user-level process. +// +// This beats using CPU-specific instructions which are, on single-core +// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more +// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking +// shows that the extra function call cost is completely negligible on +// multi-core devices. +// inline void MemoryBarrier() { - pLinuxKernelMemoryBarrier(); + (*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)(); } #define LEVELDB_HAVE_MEMORY_BARRIER diff --git a/port/port.h b/port/port.h index 816826b..e667db4 100644 --- a/port/port.h +++ b/port/port.h @@ -14,8 +14,6 @@ # include "port/port_posix.h" #elif defined(LEVELDB_PLATFORM_CHROMIUM) # include "port/port_chromium.h" -#elif defined(LEVELDB_PLATFORM_ANDROID) -# include "port/port_android.h" #endif #endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/port/port_example.h b/port/port_example.h index 036c7d1..ab9e489 100644 --- a/port/port_example.h +++ b/port/port_example.h @@ -60,6 +60,16 @@ class CondVar { void SignallAll(); }; +// Thread-safe initialization. +// Used as follows: +// static port::OnceType init_control = LEVELDB_ONCE_INIT; +// static void Initializer() { ... do something ...; } +// ... +// port::InitOnce(&init_control, &Initializer); +typedef intptr_t OnceType; +#define LEVELDB_ONCE_INIT 0 +extern void InitOnce(port::OnceType*, void (*initializer)()); + // A type that holds a pointer that can be read or written atomically // (i.e., without word-tearing.) class AtomicPointer { diff --git a/port/port_posix.cc b/port/port_posix.cc index c44cc99..5ba127a 100644 --- a/port/port_posix.cc +++ b/port/port_posix.cc @@ -46,5 +46,9 @@ void CondVar::SignalAll() { PthreadCall("broadcast", pthread_cond_broadcast(&cv_)); } +void InitOnce(OnceType* once, void (*initializer)()) { + PthreadCall("once", pthread_once(once, initializer)); +} + } // namespace port } // namespace leveldb diff --git a/port/port_posix.h b/port/port_posix.h index 485ad10..654a4b9 100644 --- a/port/port_posix.h +++ b/port/port_posix.h @@ -7,17 +7,22 @@ #ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_ #define STORAGE_LEVELDB_PORT_PORT_POSIX_H_ +#undef PLATFORM_IS_LITTLE_ENDIAN #if defined(OS_MACOSX) #include <machine/endian.h> + #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER) + #define PLATFORM_IS_LITTLE_ENDIAN \ + (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) + #endif #elif defined(OS_SOLARIS) #include <sys/isa_defs.h> #ifdef _LITTLE_ENDIAN - #define LITTLE_ENDIAN + #define PLATFORM_IS_LITTLE_ENDIAN true #else - #define BIG_ENDIAN + #define PLATFORM_IS_LITTLE_ENDIAN false #endif #elif defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ - defined(OS_DRAGONFLYBSD) + defined(OS_DRAGONFLYBSD) || defined(OS_ANDROID) #include <sys/types.h> #include <sys/endian.h> #else @@ -31,14 +36,13 @@ #include <string> #include "port/atomic_pointer.h" -#ifdef LITTLE_ENDIAN -#define IS_LITTLE_ENDIAN true -#else -#define IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) +#ifndef PLATFORM_IS_LITTLE_ENDIAN +#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) #endif #if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\ - defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\ + defined(OS_ANDROID) // Use fread/fwrite/fflush on platforms without _unlocked variants #define fread_unlocked fread #define fwrite_unlocked fwrite @@ -51,10 +55,17 @@ #define fdatasync fsync #endif +#if defined(OS_ANDROID) && __ANDROID_API__ < 9 +// fdatasync() was only introduced in API level 9 on Android. Use fsync() +// when targetting older platforms. +#define fdatasync fsync +#endif + namespace leveldb { namespace port { -static const bool kLittleEndian = IS_LITTLE_ENDIAN; +static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN; +#undef PLATFORM_IS_LITTLE_ENDIAN class CondVar; @@ -88,6 +99,10 @@ class CondVar { Mutex* mu_; }; +typedef pthread_once_t OnceType; +#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT +extern void InitOnce(OnceType* once, void (*initializer)()); + inline bool Snappy_Compress(const char* input, size_t length, ::std::string* output) { #ifdef SNAPPY |