STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
aligned_alloc.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/common/aligned_alloc.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002 Roman Dementiev <[email protected]>
7  * Copyright (C) 2009 Andreas Beckmann <[email protected]>
8  *
9  * Distributed under the Boost Software License, Version 1.0.
10  * (See accompanying file LICENSE_1_0.txt or copy at
11  * http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
14 #ifndef STXXL_COMMON_ALIGNED_ALLOC_HEADER
15 #define STXXL_COMMON_ALIGNED_ALLOC_HEADER
16 
17 #include <cstdlib>
18 #include <cassert>
19 #include <stxxl/bits/verbose.h>
21 
22 
23 #ifndef STXXL_VERBOSE_ALIGNED_ALLOC
24 #define STXXL_VERBOSE_ALIGNED_ALLOC STXXL_VERBOSE2
25 #endif
26 
28 
29 template <typename must_be_int>
31  static bool may_use_realloc;
32 };
33 
34 template <typename must_be_int>
36 
37 // meta_info_size > 0 is needed for array allocations that have overhead
38 //
39 // meta_info
40 // aligned begin of data unallocated behind data
41 // v v v
42 // ----===============#MMMM========================------
43 // ^ ^^ ^
44 // buffer result result+m_i_size+size
45 // pointer to buffer
46 // (---) unallocated, (===) allocated memory
47 
48 template <size_t ALIGNMENT>
49 inline void * aligned_alloc(size_t size, size_t meta_info_size = 0)
50 {
51  STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), size = " << size << ", meta info size = " << meta_info_size);
52 #if !defined(STXXL_WASTE_MORE_MEMORY_FOR_IMPROVED_ACCESS_AFTER_ALLOCATED_MEMORY_CHECKS)
53  // malloc()/realloc() variant that frees the unused amount of memory
54  // after the data area of size 'size'. realloc() from valgrind does not
55  // preserve the old memory area when shrinking, so out-of-bounds
56  // accesses can't be detected easily.
57  // Overhead: about ALIGNMENT bytes.
58  size_t alloc_size = ALIGNMENT + sizeof(char*) + meta_info_size + size;
59  char* buffer = (char*)std::malloc(alloc_size);
60 #else
61  // More space consuming and memory fragmenting variant using
62  // posix_memalign() instead of malloc()/realloc(). Ensures that the end
63  // of the data area (of size 'size') will match the end of the allocated
64  // block, so no corrections are neccessary and
65  // access-behind-allocated-memory problems can be easily detected by
66  // valgrind. Usually produces an extra memory fragment of about
67  // ALIGNMENT bytes.
68  // Overhead: about 2 * ALIGNMENT bytes.
69  size_t alloc_size = ALIGNMENT * div_ceil(sizeof(char*) + meta_info_size, ALIGNMENT) + size;
70  char* buffer;
71  if (posix_memalign((void**)&buffer, ALIGNMENT, alloc_size) != 0)
72  throw std::bad_alloc();
73 #endif
74  if (buffer == NULL)
75  throw std::bad_alloc();
76  #ifdef STXXL_ALIGNED_CALLOC
77  memset(buffer, 0, alloc_size);
78  #endif
79  char* reserve_buffer = buffer + sizeof(char*) + meta_info_size;
80  char* result = reserve_buffer + ALIGNMENT -
81  (((unsigned_type)reserve_buffer) % (ALIGNMENT)) - meta_info_size;
82  STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">() address " << (void*)result << " lost " << (result - buffer) << " bytes");
83  //-tb: check that there is space for one char* before the "result" pointer
84  // delivered to the user. this char* is set below to the beginning of the
85  // allocated area.
86  assert(long(result - buffer) >= long(sizeof(char*)));
87 
88  // free unused memory behind the data area
89  // so access behind the requested size can be recognized
90  size_t realloc_size = (result - buffer) + meta_info_size + size;
91  if (realloc_size < alloc_size && aligned_alloc_settings<int>::may_use_realloc) {
92  char* realloced = (char*)std::realloc(buffer, realloc_size);
93  if (buffer != realloced) {
94  // hmm, realloc does move the memory block around while shrinking,
95  // might run under valgrind, so disable realloc and retry
96  STXXL_ERRMSG("stxxl::aligned_alloc: disabling realloc()");
97  std::free(realloced);
99  return aligned_alloc<ALIGNMENT>(size, meta_info_size);
100  }
101  assert(result + size <= buffer + realloc_size);
102  }
103 
104  *(((char**)result) - 1) = buffer;
105  STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), allocated at " << (void*)buffer << " returning " << (void*)result);
106  STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_alloc<" << ALIGNMENT <<
107  ">(size = " << size << ", meta info size = " << meta_info_size <<
108  ") => buffer = " << (void*)buffer << ", ptr = " << (void*)result);
109 
110  return result;
111 }
112 
113 template <size_t ALIGNMENT>
114 inline void
115 aligned_dealloc(void* ptr)
116 {
117  if (!ptr)
118  return;
119  char* buffer = *(((char**)ptr) - 1);
120  STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_dealloc<" << ALIGNMENT << ">(), ptr = " << ptr << ", buffer = " << (void*)buffer);
121  std::free(buffer);
122 }
123 
125 
126 #endif // !STXXL_COMMON_ALIGNED_ALLOC_HEADER
127 // vim: et:ts=4:sw=4
#define STXXL_VERBOSE2(x)
Definition: verbose.h:107
#define STXXL_VERBOSE_ALIGNED_ALLOC
Definition: aligned_alloc.h:24
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_ERRMSG(x)
Definition: verbose.h:79
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
void * aligned_alloc(size_t size, size_t meta_info_size=0)
Definition: aligned_alloc.h:49
compat::remove_const< Integral >::type div_ceil(Integral __n, Integral2 __d)
Definition: utils.h:200
void aligned_dealloc(void *ptr)
#define STXXL_END_NAMESPACE
Definition: namespace.h:17