1 // functions for aligned memory allocation
2 // Copyright (C) 2009 Tim Blechmann
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef UTILITIES_MALLOC_ALIGNED_HPP
20 #define UTILITIES_MALLOC_ALIGNED_HPP
25 #include <boost/noncopyable.hpp>
28 #include <xmmintrin.h>
29 #elif defined(HAVE_TBB)
30 #include <tbb/cache_aligned_allocator.h>
37 #include "function_attributes.h"
41 #if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
42 /* we have posix_memalign */
44 /* memory alignment constraints:
46 * - 16 byte for SSE operations
47 * - the cache lines size of modern x86 cpus is 64 bytes (pentium-m, pentium 4, core, k8)
49 const int malloc_memory_alignment
= 64;
51 inline void* MALLOC
malloc_aligned(std::size_t nbytes
)
54 int status
= posix_memalign(&ret
, malloc_memory_alignment
, nbytes
);
61 inline void free_aligned(void *ptr
)
66 #elif defined(__APPLE__)
68 const int malloc_memory_alignment
= 64;
70 /* apple's malloc implementation returns 16-byte aligned chunks */
71 inline void* MALLOC
malloc_aligned(std::size_t nbytes
)
73 return malloc(nbytes
);
76 inline void free_aligned(void *ptr
)
82 #elif defined(__SSE2__)
84 const int malloc_memory_alignment
= 64;
86 inline void* MALLOC
malloc_aligned(std::size_t nbytes
)
88 return _mm_malloc(nbytes
, malloc_memory_alignment
);
91 inline void free_aligned(void *ptr
)
96 #elif defined(_MSC_VER)
98 const int malloc_memory_alignment
= 64;
100 inline void* MALLOC
malloc_aligned(std::size_t nbytes
)
102 return _aligned_malloc(nbytes
, malloc_memory_alignment
);
105 inline void free_aligned(void *ptr
)
110 #elif defined(HAVE_TBB)
112 inline void* MALLOC
malloc_aligned(std::size_t nbytes
)
114 tbb::cache_aligned_allocator
<void*> ca_alloc
;
115 return static_cast<void*>(ca_alloc
.allocate(nbytes
));
118 inline void free_aligned(void *ptr
)
120 tbb::cache_aligned_allocator
<void*> ca_alloc
;
121 ca_alloc
.deallocate(static_cast<void**>(ptr
), 0);
126 /* on other systems, we use the aligned memory allocation taken
127 * from thomas grill's implementation for pd */
128 #define VECTORALIGNMENT 128
129 inline void* MALLOC
malloc_aligned(std::size_t nbytes
)
131 void* vec
= malloc(nbytes
+ (VECTORALIGNMENT
/8-1) + sizeof(void *));
134 /* get alignment of first possible signal vector byte */
135 long alignment
= ((long)vec
+sizeof(void *))&(VECTORALIGNMENT
/8-1);
136 /* calculate aligned pointer */
137 void *ret
= (unsigned char *)vec
+sizeof(void *)+(alignment
== 0?0:VECTORALIGNMENT
/8-alignment
);
138 /* save original memory location */
139 *(void **)((unsigned char *)ret
-sizeof(void *)) = vec
;
145 inline void free_aligned(void *ptr
)
150 /* get original memory location */
151 void *ori
= *(void **)((unsigned char *)ptr
-sizeof(void *));
155 #undef VECTORALIGNMENT
159 inline void * calloc_aligned(std::size_t nbytes
)
161 void * ret
= malloc_aligned(nbytes
);
163 std::memset(ret
, 0, nbytes
);
167 template <typename T
>
168 T
* malloc_aligned(std::size_t n
)
170 return static_cast<T
*>(malloc_aligned(n
* sizeof(T
)));
173 template <typename T
>
174 T
* calloc_aligned(std::size_t n
)
176 return static_cast<T
*>(calloc_aligned(n
* sizeof(T
)));
180 /** aligned allocator. uses malloc_aligned and free_aligned internally
183 class aligned_allocator
186 typedef std::size_t size_type
;
187 typedef std::ptrdiff_t difference_type
;
189 typedef const T
* const_pointer
;
190 typedef T
& reference
;
191 typedef const T
& const_reference
;
192 typedef T value_type
;
194 template <class U
> struct rebind
196 typedef aligned_allocator
<U
> other
;
199 aligned_allocator(void)
203 aligned_allocator(aligned_allocator
<U
> const & rhs
)
206 pointer
address(reference x
) const
211 const_pointer
address(const_reference x
) const
216 pointer
allocate(size_type n
, const void* hint
= 0)
218 pointer ret
= malloc_aligned
<T
>(n
);
220 throw std::bad_alloc();
224 void deallocate(pointer p
, size_type n
)
226 return free_aligned(p
);
229 size_type
max_size() const throw()
231 return size_type(-1) / sizeof(T
);
234 void construct(pointer p
, const T
& val
= T())
239 void destroy(pointer p
)
246 template<typename T
, typename U
>
247 bool operator==( aligned_allocator
<T
> const& left
, aligned_allocator
<U
> const& right
)
249 return !(left
!= right
);
252 template<typename T
, typename U
>
253 bool operator!=( aligned_allocator
<T
> const& left
, aligned_allocator
<U
> const& right
)
259 /** smart-pointer, freeing the managed pointer via free_aligned */
260 template<class T
, bool managed
= true>
261 class aligned_storage_ptr
264 explicit aligned_storage_ptr(T
* p
= 0):
268 ~aligned_storage_ptr(void)
274 void reset(T
* p
= 0)
281 T
& operator*() const
286 T
* operator->() const
296 aligned_storage_ptr
& operator=(T
* p
)
302 operator bool() const
307 void swap(aligned_storage_ptr
& b
)
318 } /* namespace nova */
320 #endif /* UTILITIES_MALLOC_ALIGNED_HPP */