STXXL  1.4-dev
 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 #ifndef STXXL_VERBOSE_ALIGNED_ALLOC
23 #define STXXL_VERBOSE_ALIGNED_ALLOC STXXL_VERBOSE2
24 #endif
25 
27 
28 template <typename MustBeInt>
30  static bool may_use_realloc;
31 };
32 
33 template <typename MustBeInt>
35 
36 // meta_info_size > 0 is needed for array allocations that have overhead
37 //
38 // meta_info
39 // aligned begin of data unallocated behind data
40 // v v v
41 // ----===============#MMMM========================------
42 // ^ ^^ ^
43 // buffer result result+m_i_size+size
44 // pointer to buffer
45 // (---) unallocated, (===) allocated memory
46 
47 template <size_t Alignment>
48 inline void * aligned_alloc(size_t size, size_t meta_info_size = 0)
49 {
50  STXXL_VERBOSE2("stxxl::aligned_alloc<" << Alignment << ">(), size = " << size << ", meta info size = " << meta_info_size);
51 #if !defined(STXXL_WASTE_MORE_MEMORY_FOR_IMPROVED_ACCESS_AFTER_ALLOCATED_MEMORY_CHECKS)
52  // malloc()/realloc() variant that frees the unused amount of memory
53  // after the data area of size 'size'. realloc() from valgrind does not
54  // preserve the old memory area when shrinking, so out-of-bounds
55  // accesses can't be detected easily.
56  // Overhead: about Alignment bytes.
57  size_t alloc_size = Alignment + sizeof(char*) + meta_info_size + size;
58  char* buffer = (char*)std::malloc(alloc_size);
59 #else
60  // More space consuming and memory fragmenting variant using
61  // posix_memalign() instead of malloc()/realloc(). Ensures that the end
62  // of the data area (of size 'size') will match the end of the allocated
63  // block, so no corrections are neccessary and
64  // access-behind-allocated-memory problems can be easily detected by
65  // valgrind. Usually produces an extra memory fragment of about
66  // Alignment bytes.
67  // Overhead: about 2 * Alignment bytes.
68  size_t alloc_size = Alignment * div_ceil(sizeof(char*) + meta_info_size, Alignment) + size;
69  char* buffer;
70  if (posix_memalign((void**)&buffer, Alignment, alloc_size) != 0)
71  throw std::bad_alloc();
72 #endif
73  if (buffer == NULL)
74  throw std::bad_alloc();
75  #ifdef STXXL_ALIGNED_CALLOC
76  memset(buffer, 0, alloc_size);
77  #endif
78  char* reserve_buffer = buffer + sizeof(char*) + meta_info_size;
79  char* result = reserve_buffer + Alignment -
80  (((unsigned_type)reserve_buffer) % (Alignment)) - meta_info_size;
81  STXXL_VERBOSE2("stxxl::aligned_alloc<" << Alignment << ">() address " << (void*)result << " lost " << (result - buffer) << " bytes");
82  //-tb: check that there is space for one char* before the "result" pointer
83  // delivered to the user. this char* is set below to the beginning of the
84  // allocated area.
85  assert(long(result - buffer) >= long(sizeof(char*)));
86 
87  // free unused memory behind the data area
88  // so access behind the requested size can be recognized
89  size_t realloc_size = (result - buffer) + meta_info_size + size;
90  if (realloc_size < alloc_size && aligned_alloc_settings<int>::may_use_realloc) {
91  char* realloced = (char*)std::realloc(buffer, realloc_size);
92  if (buffer != realloced) {
93  // hmm, realloc does move the memory block around while shrinking,
94  // might run under valgrind, so disable realloc and retry
95  STXXL_ERRMSG("stxxl::aligned_alloc: disabling realloc()");
96  std::free(realloced);
98  return aligned_alloc<Alignment>(size, meta_info_size);
99  }
100  assert(result + size <= buffer + realloc_size);
101  }
102 
103  *(((char**)result) - 1) = buffer;
105  "stxxl::aligned_alloc<" << Alignment << ">(), allocated at " <<
106  (void*)buffer << " returning " << (void*)result);
108  "stxxl::aligned_alloc<" << Alignment <<
109  ">(size = " << size << ", meta info size = " << meta_info_size <<
110  ") => buffer = " << (void*)buffer << ", ptr = " << (void*)result);
111 
112  return result;
113 }
114 
115 template <size_t Alignment>
116 inline void
117 aligned_dealloc(void* ptr)
118 {
119  if (!ptr)
120  return;
121  char* buffer = *(((char**)ptr) - 1);
122  STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_dealloc<" << Alignment << ">(), ptr = " << ptr << ", buffer = " << (void*)buffer);
123  std::free(buffer);
124 }
125 
127 
128 #endif // !STXXL_COMMON_ALIGNED_ALLOC_HEADER
129 // vim: et:ts=4:sw=4
void * malloc(size_t size)
compat::remove_const< Integral >::type div_ceil(Integral n, Integral2 d)
Definition: utils.h:199
void * realloc(void *ptr, size_t size)
#define STXXL_VERBOSE2(x)
Definition: verbose.h:121
#define STXXL_VERBOSE_ALIGNED_ALLOC
Definition: aligned_alloc.h:23
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void free(void *ptr)
#define STXXL_ERRMSG(x)
Definition: verbose.h:94
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:64
void * aligned_alloc(size_t size, size_t meta_info_size=0)
Definition: aligned_alloc.h:48
void aligned_dealloc(void *ptr)
#define STXXL_END_NAMESPACE
Definition: namespace.h:17