Line data Source code
1 : /* Copyright (C) 2010 Wildfire Games.
2 : *
3 : * Permission is hereby granted, free of charge, to any person obtaining
4 : * a copy of this software and associated documentation files (the
5 : * "Software"), to deal in the Software without restriction, including
6 : * without limitation the rights to use, copy, modify, merge, publish,
7 : * distribute, sublicense, and/or sell copies of the Software, and to
8 : * permit persons to whom the Software is furnished to do so, subject to
9 : * the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included
12 : * in all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 : */
22 :
23 : #include "precompiled.h"
24 :
25 : #include "lib/sysdep/rtl.h"
26 : #include "lib/bits.h"
27 :
28 : // Linux glibc has posix_memalign and (obsolete) memalign
29 : // Android libc has only memalign
30 : // OS X and BSD probably do not have either.
31 : #define HAVE_POSIX_MEMALIGN (OS_LINUX && !OS_ANDROID)
32 : #define HAVE_MEMALIGN OS_LINUX
33 :
34 : #if HAVE_POSIX_MEMALIGN
35 :
36 3329 : void* rtl_AllocateAligned(size_t size, size_t alignment)
37 : {
38 : void *ptr;
39 3329 : int ret = posix_memalign(&ptr, alignment, size);
40 3329 : if (ret) {
41 : // TODO: report error?
42 0 : return NULL;
43 : }
44 3329 : return ptr;
45 : }
46 :
47 3390 : void rtl_FreeAligned(void* alignedPointer)
48 : {
49 3390 : free(alignedPointer);
50 3393 : }
51 :
52 : #elif HAVE_MEMALIGN
53 :
54 : void* rtl_AllocateAligned(size_t size, size_t alignment)
55 : {
56 : return memalign(alignment, size);
57 : }
58 :
59 : void rtl_FreeAligned(void* alignedPointer)
60 : {
61 : free(alignedPointer);
62 : }
63 :
64 : #else // Fallback aligned allocation using malloc
65 :
66 : void* rtl_AllocateAligned(size_t size, size_t align)
67 : {
68 : // This ensures we have enough extra space to store the original pointer,
69 : // and produce an aligned buffer, assuming the platform malloc ensures at
70 : // least sizeof(void*) alignment.
71 : if (align < 2*sizeof(void*))
72 : align = 2*sizeof(void*);
73 :
74 : void* const malloc_ptr = malloc(size + align);
75 : if (!malloc_ptr)
76 : return NULL;
77 :
78 : // Round malloc_ptr up to the next aligned address, leaving some unused
79 : // space before the pointer we'll return. The minimum alignment above
80 : // ensures we'll have at least sizeof(void*) extra space.
81 : void* const aligned_ptr =
82 : (void *)(round_down(uintptr_t(malloc_ptr), uintptr_t(align)) + align);
83 :
84 : // Just make sure we did the right thing with all the alignment hacks above.
85 : ENSURE(((void**)aligned_ptr) - 1 >= malloc_ptr);
86 :
87 : // Store the original pointer which will have to be sent to free().
88 : ((void **)aligned_ptr)[-1] = malloc_ptr;
89 :
90 : return aligned_ptr;
91 : }
92 :
93 : void rtl_FreeAligned(void* alignedPointer)
94 : {
95 : if (alignedPointer)
96 : free(((void**)alignedPointer)[-1]);
97 : }
98 :
99 : #endif
|