alloc.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "alloc.h"
  4. #include "intrinsics.h"
  5. #include "sysinfo.h"
  6. #include "mutex.h"
  7. ////////////////////////////////////////////////////////////////////////////////
  8. /// All Platforms
  9. ////////////////////////////////////////////////////////////////////////////////
  10. namespace embree
  11. {
  12. void* alignedMalloc(size_t size, size_t align)
  13. {
  14. if (size == 0)
  15. return nullptr;
  16. assert((align & (align-1)) == 0);
  17. void* ptr = _mm_malloc(size,align);
  18. if (size != 0 && ptr == nullptr)
  19. // -- GODOT start --
  20. // throw std::bad_alloc();
  21. abort();
  22. // -- GODOT end --
  23. return ptr;
  24. }
  25. void alignedFree(void* ptr)
  26. {
  27. if (ptr)
  28. _mm_free(ptr);
  29. }
  30. static bool huge_pages_enabled = false;
  31. static MutexSys os_init_mutex;
  32. __forceinline bool isHugePageCandidate(const size_t bytes)
  33. {
  34. if (!huge_pages_enabled)
  35. return false;
  36. /* use huge pages only when memory overhead is low */
  37. const size_t hbytes = (bytes+PAGE_SIZE_2M-1) & ~size_t(PAGE_SIZE_2M-1);
  38. return 66*(hbytes-bytes) < bytes; // at most 1.5% overhead
  39. }
  40. }
  41. ////////////////////////////////////////////////////////////////////////////////
  42. /// Windows Platform
  43. ////////////////////////////////////////////////////////////////////////////////
  44. #ifdef _WIN32
  45. #define WIN32_LEAN_AND_MEAN
  46. #include <windows.h>
  47. #include <malloc.h>
  48. namespace embree
  49. {
  50. bool win_enable_selockmemoryprivilege (bool verbose)
  51. {
  52. HANDLE hToken;
  53. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
  54. if (verbose) std::cout << "WARNING: OpenProcessToken failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
  55. return false;
  56. }
  57. TOKEN_PRIVILEGES tp;
  58. tp.PrivilegeCount = 1;
  59. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  60. if (!LookupPrivilegeValueW(nullptr, L"SeLockMemoryPrivilege", &tp.Privileges[0].Luid)) {
  61. if (verbose) std::cout << "WARNING: LookupPrivilegeValue failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
  62. return false;
  63. }
  64. SetLastError(ERROR_SUCCESS);
  65. if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), nullptr, 0)) {
  66. if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed while trying to enable SeLockMemoryPrivilege" << std::endl;
  67. return false;
  68. }
  69. if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
  70. if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed to enable SeLockMemoryPrivilege: Add SeLockMemoryPrivilege for current user and run process in elevated mode (Run as administrator)." << std::endl;
  71. return false;
  72. }
  73. return true;
  74. }
  75. bool os_init(bool hugepages, bool verbose)
  76. {
  77. Lock<MutexSys> lock(os_init_mutex);
  78. if (!hugepages) {
  79. huge_pages_enabled = false;
  80. return true;
  81. }
  82. if (GetLargePageMinimum() != PAGE_SIZE_2M) {
  83. huge_pages_enabled = false;
  84. return false;
  85. }
  86. huge_pages_enabled = true;
  87. return true;
  88. }
  89. void* os_malloc(size_t bytes, bool& hugepages)
  90. {
  91. if (bytes == 0) {
  92. hugepages = false;
  93. return nullptr;
  94. }
  95. /* try direct huge page allocation first */
  96. if (isHugePageCandidate(bytes))
  97. {
  98. int flags = MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES;
  99. char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
  100. if (ptr != nullptr) {
  101. hugepages = true;
  102. return ptr;
  103. }
  104. }
  105. /* fall back to 4k pages */
  106. int flags = MEM_COMMIT | MEM_RESERVE;
  107. char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
  108. // -- GODOT start --
  109. // if (ptr == nullptr) throw std::bad_alloc();
  110. if (ptr == nullptr) abort();
  111. // -- GODOT end --
  112. hugepages = false;
  113. return ptr;
  114. }
  115. size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
  116. {
  117. if (hugepages) // decommitting huge pages seems not to work under Windows
  118. return bytesOld;
  119. const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
  120. bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
  121. bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
  122. if (bytesNew >= bytesOld)
  123. return bytesOld;
  124. if (!VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT))
  125. // -- GODOT start --
  126. // throw std::bad_alloc();
  127. abort();
  128. // -- GODOT end --
  129. return bytesNew;
  130. }
  131. void os_free(void* ptr, size_t bytes, bool hugepages)
  132. {
  133. if (bytes == 0)
  134. return;
  135. if (!VirtualFree(ptr,0,MEM_RELEASE))
  136. // -- GODOT start --
  137. // throw std::bad_alloc();
  138. abort();
  139. // -- GODOT end --
  140. }
  141. void os_advise(void *ptr, size_t bytes)
  142. {
  143. }
  144. }
  145. #endif
  146. ////////////////////////////////////////////////////////////////////////////////
  147. /// Unix Platform
  148. ////////////////////////////////////////////////////////////////////////////////
  149. #if defined(__UNIX__)
  150. #include <sys/mman.h>
  151. #include <errno.h>
  152. #include <stdlib.h>
  153. #include <string.h>
  154. #include <sstream>
  155. #if defined(__MACOSX__)
  156. #include <mach/vm_statistics.h>
  157. #endif
  158. namespace embree
  159. {
  160. bool os_init(bool hugepages, bool verbose)
  161. {
  162. Lock<MutexSys> lock(os_init_mutex);
  163. if (!hugepages) {
  164. huge_pages_enabled = false;
  165. return true;
  166. }
  167. #if defined(__LINUX__)
  168. int hugepagesize = 0;
  169. std::ifstream file;
  170. file.open("/proc/meminfo",std::ios::in);
  171. if (!file.is_open()) {
  172. if (verbose) std::cout << "WARNING: Could not open /proc/meminfo. Huge page support cannot get enabled!" << std::endl;
  173. huge_pages_enabled = false;
  174. return false;
  175. }
  176. std::string line;
  177. while (getline(file,line))
  178. {
  179. std::stringstream sline(line);
  180. while (!sline.eof() && sline.peek() == ' ') sline.ignore();
  181. std::string tag; getline(sline,tag,' ');
  182. while (!sline.eof() && sline.peek() == ' ') sline.ignore();
  183. std::string val; getline(sline,val,' ');
  184. while (!sline.eof() && sline.peek() == ' ') sline.ignore();
  185. std::string unit; getline(sline,unit,' ');
  186. if (tag == "Hugepagesize:" && unit == "kB") {
  187. hugepagesize = std::stoi(val)*1024;
  188. break;
  189. }
  190. }
  191. if (hugepagesize != PAGE_SIZE_2M)
  192. {
  193. if (verbose) std::cout << "WARNING: Only 2MB huge pages supported. Huge page support cannot get enabled!" << std::endl;
  194. huge_pages_enabled = false;
  195. return false;
  196. }
  197. #endif
  198. huge_pages_enabled = true;
  199. return true;
  200. }
  201. void* os_malloc(size_t bytes, bool& hugepages)
  202. {
  203. if (bytes == 0) {
  204. hugepages = false;
  205. return nullptr;
  206. }
  207. /* try direct huge page allocation first */
  208. if (isHugePageCandidate(bytes))
  209. {
  210. #if defined(__MACOSX__)
  211. void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
  212. if (ptr != MAP_FAILED) {
  213. hugepages = true;
  214. return ptr;
  215. }
  216. #elif defined(MAP_HUGETLB)
  217. void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0);
  218. if (ptr != MAP_FAILED) {
  219. hugepages = true;
  220. return ptr;
  221. }
  222. #endif
  223. }
  224. /* fallback to 4k pages */
  225. void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  226. // -- GODOT start --
  227. // if (ptr == MAP_FAILED) throw std::bad_alloc();
  228. if (ptr == MAP_FAILED) abort();
  229. // -- GODOT end --
  230. hugepages = false;
  231. /* advise huge page hint for THP */
  232. os_advise(ptr,bytes);
  233. return ptr;
  234. }
  235. size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
  236. {
  237. const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
  238. bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
  239. bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
  240. if (bytesNew >= bytesOld)
  241. return bytesOld;
  242. if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
  243. // -- GODOT start --
  244. // throw std::bad_alloc();
  245. abort();
  246. // -- GODOT end --
  247. return bytesNew;
  248. }
  249. void os_free(void* ptr, size_t bytes, bool hugepages)
  250. {
  251. if (bytes == 0)
  252. return;
  253. /* for hugepages we need to also align the size */
  254. const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
  255. bytes = (bytes+pageSize-1) & ~(pageSize-1);
  256. if (munmap(ptr,bytes) == -1)
  257. // -- GODOT start --
  258. // throw std::bad_alloc();
  259. abort();
  260. // -- GODOT end --
  261. }
  262. /* hint for transparent huge pages (THP) */
  263. void os_advise(void* pptr, size_t bytes)
  264. {
  265. #if defined(MADV_HUGEPAGE)
  266. madvise(pptr,bytes,MADV_HUGEPAGE);
  267. #endif
  268. }
  269. }
  270. #endif