Stxxl  1.4.0
include/stxxl/bits/common/aligned_alloc.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  include/stxxl/bits/common/aligned_alloc.h
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2002 Roman Dementiev <dementiev@mpi-sb.mpg.de>
00007  *  Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00008  *
00009  *  Distributed under the Boost Software License, Version 1.0.
00010  *  (See accompanying file LICENSE_1_0.txt or copy at
00011  *  http://www.boost.org/LICENSE_1_0.txt)
00012  **************************************************************************/
00013 
00014 #ifndef STXXL_ALIGNED_ALLOC
00015 #define STXXL_ALIGNED_ALLOC
00016 
00017 #include <cstdlib>
00018 #include <cassert>
00019 #include <stxxl/bits/verbose.h>
00020 #include <stxxl/bits/common/utils.h>
00021 
00022 
00023 #ifndef STXXL_VERBOSE_ALIGNED_ALLOC
00024 #define STXXL_VERBOSE_ALIGNED_ALLOC STXXL_VERBOSE2
00025 #endif
00026 
00027 __STXXL_BEGIN_NAMESPACE
00028 
00029 template <typename must_be_int>
00030 struct aligned_alloc_settings {
00031     static bool may_use_realloc;
00032 };
00033 
00034 template <typename must_be_int>
00035 bool aligned_alloc_settings<must_be_int>::may_use_realloc = true;
00036 
00037 // meta_info_size > 0 is needed for array allocations that have overhead
00038 //
00039 //                      meta_info
00040 //                          aligned begin of data   unallocated behind data
00041 //                      v   v                       v
00042 //  ----===============#MMMM========================------
00043 //      ^              ^^                           ^
00044 //      buffer          result                      result+m_i_size+size
00045 //                     pointer to buffer
00046 // (---) unallocated, (===) allocated memory
00047 
00048 template <size_t ALIGNMENT>
00049 inline void * aligned_alloc(size_t size, size_t meta_info_size = 0)
00050 {
00051     STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), size = " << size << ", meta info size = " << meta_info_size);
00052 #if !defined(STXXL_WASTE_MORE_MEMORY_FOR_IMPROVED_ACCESS_AFTER_ALLOCATED_MEMORY_CHECKS)
00053     // malloc()/realloc() variant that frees the unused amount of memory
00054     // after the data area of size 'size'. realloc() from valgrind does not
00055     // preserve the old memory area when shrinking, so out-of-bounds
00056     // accesses can't be detected easily.
00057     // Overhead: about ALIGNMENT bytes.
00058     size_t alloc_size = ALIGNMENT + sizeof(char *) + meta_info_size + size;
00059     char * buffer = (char *)std::malloc(alloc_size);
00060 #else
00061     // More space consuming and memory fragmenting variant using
00062     // posix_memalign() instead of malloc()/realloc(). Ensures that the end
00063     // of the data area (of size 'size') will match the end of the allocated
00064     // block, so no corrections are neccessary and
00065     // access-behind-allocated-memory problems can be easily detected by
00066     // valgrind. Usually produces an extra memory fragment of about
00067     // ALIGNMENT bytes.
00068     // Overhead: about 2 * ALIGNMENT bytes.
00069     size_t alloc_size = ALIGNMENT * div_ceil(sizeof(char *) + meta_info_size, ALIGNMENT) + size;
00070     char * buffer;
00071     if (posix_memalign((void **)&buffer, ALIGNMENT, alloc_size) != 0)
00072         throw std::bad_alloc();
00073 #endif
00074     if (buffer == NULL)
00075         throw std::bad_alloc();
00076     #ifdef STXXL_ALIGNED_CALLOC
00077     memset(buffer, 0, alloc_size);
00078     #endif
00079     char * reserve_buffer = buffer + sizeof(char *) + meta_info_size;
00080     char * result = reserve_buffer + ALIGNMENT -
00081                     (((unsigned long)reserve_buffer) % (ALIGNMENT)) - meta_info_size;
00082     STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">() address " << (void *)result << " lost " << (result - buffer) << " bytes");
00083     assert(long(result - buffer) >= long(sizeof(char *)));
00084 
00085     // free unused memory behind the data area
00086     // so access behind the requested size can be recognized
00087     size_t realloc_size = (result - buffer) + meta_info_size + size;
00088     if (realloc_size < alloc_size && aligned_alloc_settings<int>::may_use_realloc) {
00089         char * realloced = (char *)std::realloc(buffer, realloc_size);
00090         if (buffer != realloced) {
00091             // hmm, realloc does move the memory block around while shrinking,
00092             // might run under valgrind, so disable realloc and retry
00093             STXXL_ERRMSG("stxxl::aligned_alloc: disabling realloc()");
00094             std::free(realloced);
00095             aligned_alloc_settings<int>::may_use_realloc = false;
00096             return aligned_alloc<ALIGNMENT>(size, meta_info_size);
00097         }
00098         assert(result + size <= buffer + realloc_size);
00099     }
00100 
00101     *(((char **)result) - 1) = buffer;
00102     STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), allocated at " << (void *)buffer << " returning " << (void *)result);
00103     STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_alloc<" << ALIGNMENT <<
00104                                 ">(size = " << size << ", meta info size = " << meta_info_size <<
00105                                 ") => buffer = " << (void *)buffer << ", ptr = " << (void *)result);
00106 
00107     return result;
00108 }
00109 
00110 template <size_t ALIGNMENT>
00111 inline void
00112 aligned_dealloc(void * ptr)
00113 {
00114     if (!ptr)
00115         return;
00116     char * buffer = *(((char **)ptr) - 1);
00117     STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_dealloc<" << ALIGNMENT << ">(), ptr = " << ptr << ", buffer = " << (void *)buffer);
00118     std::free(buffer);
00119 }
00120 
00121 __STXXL_END_NAMESPACE
00122 
00123 #endif // !STXXL_ALIGNED_ALLOC
00124 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines