summaryrefslogtreecommitdiff
path: root/port
diff options
context:
space:
mode:
authorSanjay Ghemawat <sanjay@google.com>2012-05-30 09:45:46 -0700
committerSanjay Ghemawat <sanjay@google.com>2012-05-30 09:45:46 -0700
commit075a35a6d390167b77b687e067dd0ba593e7f624 (patch)
treeef3c793819e0a7fcfbb15fa591948709ec1e8533 /port
parent85584d497e7b354853b72f450683d59fcf6b9c5c (diff)
downloadleveldb-075a35a6d390167b77b687e067dd0ba593e7f624.tar.gz
Remove static initializer; fix endian-ness detection; fix build on
various platforms; improve android port speed. Avoid static initializer by using a new portability interface for thread-safe lazy initialization. Custom ports will need to be extended to implement InitOnce/OnceType/LEVELDB_ONCE_INIT. Fix endian-ness detection (fixes Powerpc builds). Build related fixes: - Support platforms that have unversioned shared libraries. - Fix IOS build rules. Android improvements - Speed up atomic pointers - Share more code with port_posix. Do not spin in a tight loop attempting compactions if the file system is inaccessible (e.g., if kerberos tickets have expired or if it is out of space).
Diffstat (limited to 'port')
-rw-r--r--port/atomic_pointer.h18
-rw-r--r--port/port.h2
-rw-r--r--port/port_example.h10
-rw-r--r--port/port_posix.cc4
-rw-r--r--port/port_posix.h33
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