CustomMemoryHook.cpp 2.8 KB

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