Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85020 - in trunk: boost/log/detail libs/log/src
From: andrey.semashev_at_[hidden]
Date: 2013-07-12 16:24:42


Author: andysem
Date: 2013-07-12 16:24:42 EDT (Fri, 12 Jul 2013)
New Revision: 85020
URL: http://svn.boost.org/trac/boost/changeset/85020

Log:
Refactored aligned memory allocation. Added support for Android. Fixes #8815.

Added:
   trunk/boost/log/detail/malloc_aligned.hpp (contents, props changed)
Text files modified:
   trunk/boost/log/detail/malloc_aligned.hpp | 134 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/log/src/light_rw_mutex.cpp | 21 +----
   trunk/libs/log/src/threadsafe_queue.cpp | 66 +------------------
   3 files changed, 145 insertions(+), 76 deletions(-)

Added: trunk/boost/log/detail/malloc_aligned.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/log/detail/malloc_aligned.hpp 2013-07-12 16:24:42 EDT (Fri, 12 Jul 2013) (r85020)
@@ -0,0 +1,134 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file malloc_aligned.hpp
+ * \author Andrey Semashev
+ * \date 12.07.2013
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_MALLOC_ALIGNED_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_MALLOC_ALIGNED_HPP_INCLUDED_
+
+#include <cstddef>
+#include <cstdlib>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/log/detail/config.hpp>
+
+// MSVC has its own _aligned_malloc and _aligned_free functions.
+// But MinGW doesn't declare these aligned memory allocation routines for MSVC 6 runtime.
+#if defined(BOOST_WINDOWS) && !(defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0700)
+#include <malloc.h>
+#define BOOST_LOG_HAS_MSVC_ALIGNED_MALLOC 1
+#endif
+
+#if defined(BOOST_HAS_UNISTD_H)
+#include <unistd.h> // _POSIX_VERSION
+#endif
+
+#if defined(__APPLE__) || defined(__APPLE_CC__) || defined(macintosh)
+#include <AvailabilityMacros.h>
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
+// Mac OS X 10.6 and later have posix_memalign
+#define BOOST_LOG_HAS_POSIX_MEMALIGN 1
+#endif
+#elif defined(__ANDROID__)
+// Android NDK (up to release 8e, at least) doesn't have posix_memalign despite it defines POSIX macros as if it does.
+// But we can use memalign() with free() on this platform.
+#include <malloc.h>
+#define BOOST_LOG_HAS_FREEABLE_MEMALIGN 1
+#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L)) || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))
+// Solaris 10 does not have posix_memalign. Solaris 11 and later seem to have it.
+#if !(defined(sun) || defined(__sun)) || defined(__SunOS_5_11) || defined(__SunOS_5_12)
+#define BOOST_LOG_HAS_POSIX_MEMALIGN 1
+#endif
+#endif
+
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_CPU_CACHE_LINE_SIZE
+//! The macro defines the CPU cache line size for the target architecture. This is mostly used for optimization.
+#define BOOST_LOG_CPU_CACHE_LINE_SIZE 64
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+/*!
+ * Allocates uninitialized aligned memory. Memory alignment must be a power of 2 and a multiple of sizeof(void*).
+ * The implementation may impose an upper bound of the alignment as well.
+ */
+inline void* malloc_aligned(std::size_t size, uint32_t alignment)
+{
+#if defined(BOOST_LOG_HAS_POSIX_MEMALIGN)
+ void* p = NULL;
+ if (posix_memalign(&p, alignment, size) != 0)
+ return NULL;
+ return p;
+#elif defined(BOOST_LOG_HAS_FREEABLE_MEMALIGN)
+ return memalign(alignment, size);
+#elif defined(BOOST_LOG_HAS_MSVC_ALIGNED_MALLOC)
+ return _aligned_malloc(size, alignment);
+#else
+ BOOST_ASSERT(alignment >= sizeof(void*));
+ void* p = std::malloc(size + alignment);
+ if (p)
+ {
+ unsigned char* q = static_cast< unsigned char* >(p) + alignment;
+#if defined(BOOST_HAS_INTPTR_T)
+ q = (unsigned char*)((uintptr_t)q & (~(uintptr_t)(alignment - 1u)));
+#else
+ q -= ((std::size_t)q & (std::size_t)(alignment - 1u));
+#endif
+ // Here we assume that the system allocator aligns to 4 bytes at the very least.
+ // Therefore we will always have at least 4 bytes before the aligned pointer.
+ const uint32_t diff = q - static_cast< unsigned char* >(p);
+ p = q;
+ *reinterpret_cast< uint32_t* >(q - 4u) = diff;
+ }
+ return p;
+#endif
+}
+
+/*!
+ * Frees memory allocated with \c malloc_aligned.
+ */
+inline void free_aligned(void* p)
+{
+#if defined(BOOST_LOG_HAS_POSIX_MEMALIGN) || defined(BOOST_LOG_HAS_FREEABLE_MEMALIGN)
+ free(p);
+#elif defined(BOOST_LOG_HAS_MSVC_ALIGNED_MALLOC)
+ _aligned_free(p);
+#else
+ if (p)
+ {
+ unsigned char* const q = static_cast< unsigned char* >(p);
+ const uint32_t diff = *reinterpret_cast< uint32_t* >(q - 4u);
+ std::free(q - diff);
+ }
+#endif
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_MALLOC_ALIGNED_HPP_INCLUDED_

Modified: trunk/libs/log/src/light_rw_mutex.cpp
==============================================================================
--- trunk/libs/log/src/light_rw_mutex.cpp Fri Jul 12 14:28:17 2013 (r85019)
+++ trunk/libs/log/src/light_rw_mutex.cpp 2013-07-12 16:24:42 EDT (Fri, 12 Jul 2013) (r85020)
@@ -25,20 +25,13 @@
 #include <boost/assert.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <boost/log/utility/once_block.hpp>
+#include <boost/log/detail/malloc_aligned.hpp>
 
 #include "windows_version.hpp"
 #include <windows.h>
-#include <malloc.h>
 
 #include <boost/log/detail/header.hpp>
 
-#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0700
-// MinGW doesn't declare aligned memory allocation routines for MSVC 6 runtime
-inline void* _aligned_malloc(size_t size, size_t) { return malloc(size); }
-inline void _aligned_free(void* p) { free(p); }
-#endif
-
-
 namespace boost {
 
 BOOST_LOG_OPEN_NAMESPACE
@@ -67,17 +60,15 @@
     // To avoid cache line aliasing we do aligned memory allocation here
     enum
     {
- // Cache line size on x86
- cache_line_size = 64,
         // Allocation size is the minimum number of cache lines to accommodate shared_mutex
         size =
             (
- sizeof(shared_mutex) / cache_line_size
- + ((sizeof(shared_mutex) % cache_line_size) != 0)
+ sizeof(shared_mutex) / BOOST_LOG_CPU_CACHE_LINE_SIZE
+ + ((sizeof(shared_mutex) % BOOST_LOG_CPU_CACHE_LINE_SIZE) != 0)
             )
- * cache_line_size
+ * BOOST_LOG_CPU_CACHE_LINE_SIZE
     };
- mtx->p = _aligned_malloc(size, cache_line_size);
+ mtx->p = malloc_aligned(size, BOOST_LOG_CPU_CACHE_LINE_SIZE);
     BOOST_ASSERT(mtx->p != NULL);
     new (mtx->p) shared_mutex();
 }
@@ -85,7 +76,7 @@
 void __stdcall DeinitializeSharedMutex(mutex_impl* mtx)
 {
     static_cast< shared_mutex* >(mtx->p)->~shared_mutex();
- _aligned_free(mtx->p);
+ free_aligned(mtx->p);
     mtx->p = NULL;
 }
 

Modified: trunk/libs/log/src/threadsafe_queue.cpp
==============================================================================
--- trunk/libs/log/src/threadsafe_queue.cpp Fri Jul 12 14:28:17 2013 (r85019)
+++ trunk/libs/log/src/threadsafe_queue.cpp 2013-07-12 16:24:42 EDT (Fri, 12 Jul 2013) (r85020)
@@ -25,44 +25,14 @@
 
 #ifndef BOOST_LOG_NO_THREADS
 
-#include <stdlib.h>
 #include <new>
 #include <boost/assert.hpp>
-#include <boost/static_assert.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/type_traits/alignment_of.hpp>
 #include <boost/log/detail/spin_mutex.hpp>
 #include <boost/log/detail/locks.hpp>
 #include <boost/log/detail/alignas.hpp>
-
-#if defined(BOOST_HAS_UNISTD_H)
-#include <unistd.h> // _POSIX_VERSION
-#endif
-
-#if defined(BOOST_HAS_STDINT_H)
-#include <stdint.h> // uintptr_t
-#else
-// MSVC defines integer types here
-#include <stddef.h> // uintptr_t
-#endif
-
-#if defined(__APPLE__) || defined(__APPLE_CC__) || defined(macintosh)
-#include <AvailabilityMacros.h>
-#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
-// Mac OS X 10.6 and later have posix_memalign
-#define BOOST_LOG_HAS_POSIX_MEMALIGN 1
-#endif
-#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L)) || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))
-// Solaris 10 does not have posix_memalign. Solaris 11 and later seem to have it.
-#if !(defined(sun) || defined(__sun)) || defined(__SunOS_5_11) || defined(__SunOS_5_12)
-#define BOOST_LOG_HAS_POSIX_MEMALIGN 1
-#endif
-#endif
-
-#if defined(BOOST_WINDOWS)
-#include <malloc.h> // _aligned_malloc, _aligned_free
-#endif
-
+#include <boost/log/detail/malloc_aligned.hpp>
 #include <boost/log/detail/header.hpp>
 
 namespace boost {
@@ -81,9 +51,9 @@
 
     /*!
      * A structure that contains a pointer to the node and the associated mutex.
- * The alignment below allows to eliminate false sharing, it should be not less than CPU cache line size (which is assumed to be 64 bytes in most cases).
+ * The alignment below allows to eliminate false sharing, it should not be less than CPU cache line size.
      */
- struct BOOST_LOG_ALIGNAS(64) pointer
+ struct BOOST_LOG_ALIGNAS(BOOST_LOG_CPU_CACHE_LINE_SIZE) pointer
     {
         //! Pointer to the either end of the queue
         node_base* node;
@@ -168,41 +138,15 @@
 
 BOOST_LOG_API void* threadsafe_queue_impl::operator new (std::size_t size)
 {
- void* p = NULL;
-
-#if defined(BOOST_LOG_HAS_POSIX_MEMALIGN)
- if (posix_memalign(&p, 64, size) || !p)
- BOOST_THROW_EXCEPTION(std::bad_alloc());
- return p;
-#elif defined(BOOST_WINDOWS)
- p = _aligned_malloc(size, 64);
- if (!p)
- BOOST_THROW_EXCEPTION(std::bad_alloc());
-#else
- p = malloc(size + 64);
+ void* p = malloc_aligned(size, BOOST_LOG_CPU_CACHE_LINE_SIZE);
     if (!p)
         BOOST_THROW_EXCEPTION(std::bad_alloc());
- unsigned char* q = static_cast< unsigned char* >(p) + 64;
- q = (unsigned char*)((uintptr_t)q & (~(uintptr_t)63));
- const unsigned char diff = q - static_cast< unsigned char* >(p);
- p = q;
- *--q = diff;
-#endif
-
     return p;
 }
 
 BOOST_LOG_API void threadsafe_queue_impl::operator delete (void* p, std::size_t)
 {
-#if defined(BOOST_LOG_HAS_POSIX_MEMALIGN)
- free(p);
-#elif defined(BOOST_WINDOWS)
- _aligned_free(p);
-#else
- unsigned char* q = static_cast< unsigned char* >(p);
- const unsigned char diff = *--q;
- free(static_cast< unsigned char* >(p) - diff);
-#endif
+ free_aligned(p);
 }
 
 } // namespace aux


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk