$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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