1 /*
2  * Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2015 Robin Gareus <robin@gareus.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "libpbd-config.h"
21 
22 #include <cstring>
23 #include <cerrno>
24 
25 #include "pbd/malign.h"
26 #include "pbd/error.h"
27 
28 #include "pbd/i18n.h"
29 
30 using namespace PBD;
31 
32 #if ( defined(__x86_64__) || defined(_M_X64) )
33 static const int CPU_CACHE_ALIGN = 64;
34 #elif defined ARM_NEON_SUPPORT
35 static const int CPU_CACHE_ALIGN = 128; // sizeof(float32x4_t)
36 #else
37 static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
38 #endif
39 
cache_aligned_malloc(void ** memptr,size_t size)40 int cache_aligned_malloc (void** memptr, size_t size)
41 {
42 #ifndef HAVE_POSIX_MEMALIGN
43 #ifdef PLATFORM_WINDOWS
44 	if (((*memptr) = _aligned_malloc (size, CPU_CACHE_ALIGN)) == 0) {
45 		fatal << string_compose (_("Memory allocation error: malloc (%1 * %2) failed (%3)"),
46 					 CPU_CACHE_ALIGN, size, strerror (errno)) << endmsg;
47 		return errno;
48 	} else {
49 		return 0;
50 	}
51 #else
52 	if (((*memptr) = malloc (size)) == 0) {
53 		fatal << string_compose (_("Memory allocation error: malloc (%1 * %2) failed (%3)"),
54 					 CPU_CACHE_ALIGN, size, strerror (errno)) << endmsg;
55 		return errno;
56 	} else {
57 		return 0;
58 	}
59 #endif
60 #else
61         if (posix_memalign (memptr, CPU_CACHE_ALIGN, size)) {
62 		fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
63 					 CPU_CACHE_ALIGN, size, strerror (errno)) << endmsg;
64 	}
65 
66 	return 0;
67 #endif
68 }
69 
cache_aligned_free(void * memptr)70 void cache_aligned_free (void* memptr)
71 {
72 #ifdef PLATFORM_WINDOWS
73 	_aligned_free (memptr);
74 #else
75 	free (memptr);
76 #endif
77 }
78 
aligned_malloc(void ** memptr,size_t size,size_t alignment)79 int  aligned_malloc (void** memptr, size_t size, size_t alignment)
80 {
81 #ifndef HAVE_POSIX_MEMALIGN
82 #ifdef PLATFORM_WINDOWS
83 	if (((*memptr) = _aligned_malloc (size, alignment)) == 0) {
84 		fatal << string_compose (_("Memory allocation error: malloc (%1 * %2) failed (%3)"),
85 					 alignment, size, strerror (errno)) << endmsg;
86 		return errno;
87 	} else {
88 		return 0;
89 	}
90 #else
91 	if (((*memptr) = malloc (size)) == 0) {
92 		fatal << string_compose (_("Memory allocation error: malloc (%1 * %2) failed (%3)"),
93 					 alignment, size, strerror (errno)) << endmsg;
94 		return errno;
95 	} else {
96 		return 0;
97 	}
98 #endif
99 #else
100         if (posix_memalign (memptr, alignment, size)) {
101 		fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
102 					 alignment, size, strerror (errno)) << endmsg;
103 	}
104 
105 	return 0;
106 #endif
107 }
108 
aligned_free(void * memptr)109 void aligned_free (void* memptr)
110 {
111 #ifdef PLATFORM_WINDOWS
112 	_aligned_free (memptr);
113 #else
114 	free (memptr);
115 #endif
116 }
117