Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gcc.cpp
Go to the documentation of this file.
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 void* rtl_AllocateAligned(size_t size, size_t alignment)
37 {
38  void *ptr;
39  int ret = posix_memalign(&ptr, alignment, size);
40  if (ret) {
41  // TODO: report error?
42  return NULL;
43  }
44  return ptr;
45 }
46 
47 void rtl_FreeAligned(void* alignedPointer)
48 {
49  free(alignedPointer);
50 }
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
void * rtl_AllocateAligned(size_t size, size_t align)
Definition: gcc.cpp:66
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
T round_down(T n, T multiple)
Definition: bits.h:274
void rtl_FreeAligned(void *alignedPointer)
Definition: gcc.cpp:93