2
0

CustomMemoryHook.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include <TestFramework.h>
  4. #include <Utils/CustomMemoryHook.h>
  5. #if defined(_DEBUG) && !defined(JPH_DISABLE_CUSTOM_ALLOCATOR) && !defined(JPH_COMPILER_MINGW)
  6. // Global to turn checking on/off
  7. static bool sEnableCustomMemoryHook = false;
  8. // Local to temporarily disable checking
  9. static thread_local int sDisableCustomMemoryHook = 1;
  10. // Local to keep track if we're coming through the custom allocator
  11. static thread_local bool sInCustomAllocator = false;
  12. // Struct to put on the stack to flag that we're in the custom memory allocator
  13. struct InCustomAllocator
  14. {
  15. InCustomAllocator()
  16. {
  17. JPH_ASSERT(!sInCustomAllocator);
  18. sInCustomAllocator = true;
  19. }
  20. ~InCustomAllocator()
  21. {
  22. JPH_ASSERT(sInCustomAllocator);
  23. sInCustomAllocator = false;
  24. }
  25. };
  26. // Add a tag to an allocation to track if it is aligned / unaligned
  27. static void *TagAllocation(void *inPointer, size_t inAlignment, char inMode)
  28. {
  29. uint8 *p = reinterpret_cast<uint8 *>(inPointer);
  30. *p = inMode;
  31. return p + inAlignment;
  32. }
  33. // Remove tag from allocation
  34. static void *UntagAllocation(void *inPointer, size_t inAlignment, char inMode)
  35. {
  36. uint8 *p = reinterpret_cast<uint8 *>(inPointer) - inAlignment;
  37. JPH_ASSERT(*p == inMode);
  38. *p = 0;
  39. return p;
  40. }
  41. static void *AllocateHook(size_t inSize)
  42. {
  43. InCustomAllocator ica;
  44. return TagAllocation(malloc(inSize + 16), 16, 'U');
  45. }
  46. static void FreeHook(void *inBlock)
  47. {
  48. InCustomAllocator ica;
  49. free(UntagAllocation(inBlock, 16, 'U'));
  50. }
  51. static void *AlignedAllocateHook(size_t inSize, size_t inAlignment)
  52. {
  53. JPH_ASSERT(inAlignment <= 64);
  54. InCustomAllocator ica;
  55. return TagAllocation(_aligned_malloc(inSize + 64, inAlignment), 64, 'A');
  56. }
  57. static void AlignedFreeHook(void *inBlock)
  58. {
  59. InCustomAllocator ica;
  60. _aligned_free(UntagAllocation(inBlock, 64, 'A'));
  61. }
  62. static int MyAllocHook(int nAllocType, void *pvData, size_t nSize, int nBlockUse, long lRequest, const unsigned char * szFileName, int nLine) noexcept
  63. {
  64. JPH_ASSERT(!sEnableCustomMemoryHook || sDisableCustomMemoryHook <= 0 || sInCustomAllocator);
  65. return true;
  66. }
  67. void RegisterCustomMemoryHook()
  68. {
  69. Allocate = AllocateHook;
  70. Free = FreeHook;
  71. AlignedAllocate = AlignedAllocateHook;
  72. AlignedFree = AlignedFreeHook;
  73. _CrtSetAllocHook(MyAllocHook);
  74. }
  75. void EnableCustomMemoryHook(bool inEnable)
  76. {
  77. sEnableCustomMemoryHook = inEnable;
  78. }
  79. bool IsCustomMemoryHookEnabled()
  80. {
  81. return sEnableCustomMemoryHook;
  82. }
  83. DisableCustomMemoryHook::DisableCustomMemoryHook()
  84. {
  85. sDisableCustomMemoryHook--;
  86. }
  87. DisableCustomMemoryHook::~DisableCustomMemoryHook()
  88. {
  89. sDisableCustomMemoryHook++;
  90. }
  91. #else
  92. DisableCustomMemoryHook::DisableCustomMemoryHook()
  93. {
  94. }
  95. DisableCustomMemoryHook::~DisableCustomMemoryHook()
  96. {
  97. }
  98. #endif // _DEBUG && !JPH_DISABLE_CUSTOM_ALLOCATOR && !JPH_COMPILER_MINGW