arena_ctx.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "arena_ctx.h"
  2. #include <util/generic/yexception.h>
  3. #define TypeName PG_TypeName
  4. #define SortBy PG_SortBy
  5. #undef SIZEOF_SIZE_T
  6. extern "C" {
  7. #include "postgres.h"
  8. #include "nodes/memnodes.h"
  9. #include "utils/memutils.h"
  10. #include "utils/memutils_internal.h"
  11. }
  12. namespace NYql {
  13. struct TArenaPAllocHeader {
  14. size_t Size;
  15. ui64 Self; // should be placed right before pointer to allocated area, see GetMemoryChunkContext
  16. };
  17. static_assert(sizeof(TArenaPAllocHeader) == sizeof(size_t) + sizeof(MemoryContext), "Padding is not allowed");
  18. extern "C" {
  19. extern void *ArenaAlloc(MemoryContext context, Size size);
  20. extern void ArenaFree(void *pointer);
  21. extern void *ArenaRealloc(void *pointer, Size size);
  22. extern void ArenaReset(MemoryContext context);
  23. extern void ArenaDelete(MemoryContext context);
  24. extern MemoryContext ArenaGetChunkContext(void *pointer);
  25. extern Size ArenaGetChunkSpace(void *pointer);
  26. extern bool ArenaIsEmpty(MemoryContext context);
  27. extern void ArenaStats(MemoryContext context,
  28. MemoryStatsPrintFunc printfunc, void *passthru,
  29. MemoryContextCounters *totals,
  30. bool print_to_stderr);
  31. #ifdef MEMORY_CONTEXT_CHECKING
  32. extern void ArenaCheck(MemoryContext context);
  33. #endif
  34. }
  35. extern "C" void *ArenaAlloc(MemoryContext context, Size size) {
  36. Y_UNUSED(context);
  37. auto fullSize = size + MAXIMUM_ALIGNOF - 1 + sizeof(TArenaPAllocHeader);
  38. auto ptr = TArenaMemoryContext::GetCurrentPool().Allocate(fullSize);
  39. auto aligned = (TArenaPAllocHeader*)MAXALIGN(ptr + sizeof(TArenaPAllocHeader));
  40. Y_ENSURE((ui64(context) & MEMORY_CONTEXT_METHODID_MASK) == 0);
  41. aligned[-1].Self = ui64(context) | MCTX_UNUSED2_ID;
  42. aligned[-1].Size = size;
  43. return aligned;
  44. }
  45. extern "C" void ArenaFree(void* pointer) {
  46. Y_UNUSED(pointer);
  47. }
  48. extern "C" void* ArenaRealloc(void* pointer, Size size) {
  49. if (!size) {
  50. return nullptr;
  51. }
  52. void* ret = ArenaAlloc(nullptr, size);
  53. if (pointer) {
  54. auto prevSize = ((const TArenaPAllocHeader*)pointer)[-1].Size;
  55. memmove(ret, pointer, prevSize);
  56. }
  57. return ret;
  58. }
  59. extern "C" void ArenaReset(MemoryContext context) {
  60. Y_UNUSED(context);
  61. }
  62. extern "C" void ArenaDelete(MemoryContext context) {
  63. Y_UNUSED(context);
  64. }
  65. extern "C" MemoryContext ArenaGetChunkContext(void *pointer) {
  66. return (MemoryContext)(((ui64*)pointer)[-1] & ~MEMORY_CONTEXT_METHODID_MASK);
  67. }
  68. extern "C" Size ArenaGetChunkSpace(void* pointer) {
  69. Y_UNUSED(pointer);
  70. return 0;
  71. }
  72. extern "C" bool ArenaIsEmpty(MemoryContext context) {
  73. Y_UNUSED(context);
  74. return false;
  75. }
  76. extern "C" void ArenaStats(MemoryContext context,
  77. MemoryStatsPrintFunc printfunc, void *passthru,
  78. MemoryContextCounters *totals,
  79. bool print_to_stderr) {
  80. Y_UNUSED(context);
  81. Y_UNUSED(printfunc);
  82. Y_UNUSED(passthru);
  83. Y_UNUSED(totals);
  84. Y_UNUSED(print_to_stderr);
  85. }
  86. extern "C" void ArenaCheck(MemoryContext context) {
  87. Y_UNUSED(context);
  88. }
  89. __thread TArenaMemoryContext* TArenaMemoryContext::Current = nullptr;
  90. TArenaMemoryContext::TArenaMemoryContext() {
  91. MyContext = (MemoryContext)malloc(sizeof(MemoryContextData));
  92. static_assert(MEMORY_CONTEXT_METHODID_MASK < sizeof(void*));
  93. MemoryContextCreate(MyContext,
  94. T_AllocSetContext,
  95. MCTX_UNUSED2_ID,
  96. nullptr,
  97. "arena");
  98. Acquire();
  99. }
  100. TArenaMemoryContext::~TArenaMemoryContext() {
  101. MemoryContextDeleteChildren(MyContext);
  102. Release();
  103. free(MyContext);
  104. }
  105. void TArenaMemoryContext::Acquire() {
  106. PrevContext = CurrentMemoryContext;
  107. CurrentMemoryContext = MyContext;
  108. Prev = Current;
  109. Current = this;
  110. }
  111. void TArenaMemoryContext::Release() {
  112. CurrentMemoryContext = PrevContext;
  113. PrevContext = nullptr;
  114. Current = Prev;
  115. Prev = nullptr;
  116. }
  117. }