123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- #include <library/cpp/balloc/lib/balloc.h>
- #include <errno.h>
- namespace NBalloc {
- static constexpr size_t ALIVE_SIGNATURE = 0xaULL << 56;
- static constexpr size_t DISABLED_SIGNATURE = 0xbULL << 56;
- static constexpr size_t SIGNATURE_MASK = 0xfULL << 56;
- static constexpr size_t MINIMAL_ALIGNMENT = sizeof(NBalloc::TAllocHeader);
- static_assert(((MINIMAL_ALIGNMENT - 1) & MINIMAL_ALIGNMENT) == 0,
- "invalid BALLOC_MINIMAL_ALIGNMENT");
- static Y_FORCE_INLINE void* Malloc(size_t size) {
- TLS& ltls = tls;
- size = Align(size, sizeof(TAllocHeader));
- if (Y_UNLIKELY(ltls.Mode == Empty || ltls.Mode == ToBeEnabled)) {
- Init(ltls);
- }
- if (Y_LIKELY(ltls.Mode != Disabled)) {
- TAllocHeader* allocHeader = AllocateRaw(size, ALIVE_SIGNATURE);
- return allocHeader + 1;
- } else {
- // ltls.Mode == Disabled
- const size_t extsize = size + sizeof(TAllocHeader);
- TAllocHeader* allocHeader = (TAllocHeader*)LibcMalloc(extsize);
- allocHeader->Encode(allocHeader, size, DISABLED_SIGNATURE);
- return allocHeader + 1;
- }
- }
- static void Y_FORCE_INLINE Free(void* ptr) {
- if (ptr == nullptr) {
- return;
- }
- TAllocHeader* allocHeader = ((TAllocHeader*)ptr) - 1;
- size_t size = allocHeader->AllocSize;
- const size_t signature = size & SIGNATURE_MASK;
- if (Y_LIKELY(signature == ALIVE_SIGNATURE)) {
- allocHeader->AllocSize = 0; // abort later on double free
- #ifdef DBG_FILL_MEMORY
- memset(ptr, 0xde, size - signature);
- #endif
- FreeRaw(allocHeader->Block);
- if (NAllocStats::IsEnabled()) {
- NAllocStats::DecThreadAllocStats(size - signature);
- }
- } else if (signature == DISABLED_SIGNATURE) {
- LibcFree(allocHeader->Block);
- } else {
- NMalloc::AbortFromCorruptedAllocator();
- }
- }
- static bool Y_FORCE_INLINE IsOwnedByBalloc(void* ptr) {
- TAllocHeader* allocHeader = ((TAllocHeader*)ptr) - 1;
- size_t size = allocHeader->AllocSize;
- const size_t signature = size & SIGNATURE_MASK;
- if (signature == ALIVE_SIGNATURE) {
- return true;
- } else if (signature == DISABLED_SIGNATURE) {
- return false;
- }
- NMalloc::AbortFromCorruptedAllocator();
- Y_UNREACHABLE();
- }
- static void Y_FORCE_INLINE Disable() {
- #if defined(_musl_)
- // just skip it
- #else
- tls.Mode = Disabled;
- #endif
- }
- static void Y_FORCE_INLINE Enable() {
- tls.Mode = ToBeEnabled;
- }
- static bool Y_FORCE_INLINE IsDisabled() {
- return tls.Mode == Disabled;
- }
- };
- #if defined(Y_COVER_PTR)
- void* CoverPtr(void* ptr, size_t len) noexcept;
- void* UncoverPtr(void* ptr) noexcept;
- #endif
- extern "C" void* malloc(size_t size) {
- #if defined(Y_COVER_PTR)
- return CoverPtr(NBalloc::Malloc(size + 32), size);
- #else
- return NBalloc::Malloc(size);
- #endif
- }
- extern "C" void free(void* data) {
- #if defined(Y_COVER_PTR)
- NBalloc::Free(UncoverPtr(data));
- #else
- NBalloc::Free(data);
- #endif
- }
- #if defined(USE_INTELCC) || defined(_darwin_) || defined(_freebsd_) || defined(_STLPORT_VERSION)
- #define OP_THROWNOTHING noexcept
- #else
- #define OP_THROWNOTHING
- #endif
- void* operator new(size_t size) {
- #if defined(Y_COVER_PTR)
- return malloc(size);
- #else
- return NBalloc::Malloc(size);
- #endif
- }
- int posix_memalign(void** memptr, const size_t alignment, const size_t size) {
- #if defined(Y_COVER_PTR)
- (void)alignment;
- *memptr = malloc(size);
- return 0;
- #else
- if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void*)) {
- return EINVAL;
- }
- if (alignment <= NBalloc::MINIMAL_ALIGNMENT) {
- *memptr = NBalloc::Malloc(size);
- return 0;
- }
- size_t bigSize = size + alignment - NBalloc::MINIMAL_ALIGNMENT;
- void* res = NBalloc::Malloc(bigSize);
- void* alignedPtr = (void*)NBalloc::Align((size_t)res, alignment);
- if (alignedPtr != res) {
- auto oldAllocHeader = (NBalloc::TAllocHeader*)res - 1;
- auto newAllocHeader = (NBalloc::TAllocHeader*)alignedPtr - 1;
- void* block = oldAllocHeader->Block;
- newAllocHeader->Encode(block, size, NBalloc::ALIVE_SIGNATURE);
- }
- *memptr = alignedPtr;
- return 0;
- #endif
- }
- void* operator new(size_t size, const std::nothrow_t&) OP_THROWNOTHING {
- #if defined(Y_COVER_PTR)
- return malloc(size);
- #else
- return NBalloc::Malloc(size);
- #endif
- }
- void operator delete(void* p)OP_THROWNOTHING {
- #if defined(Y_COVER_PTR)
- free(p);
- #else
- NBalloc::Free(p);
- #endif
- }
- void operator delete(void* p, const std::nothrow_t&)OP_THROWNOTHING {
- #if defined(Y_COVER_PTR)
- free(p);
- #else
- NBalloc::Free(p);
- #endif
- }
- void* operator new[](size_t size) {
- #if defined(Y_COVER_PTR)
- return malloc(size);
- #else
- return NBalloc::Malloc(size);
- #endif
- }
- void* operator new[](size_t size, const std::nothrow_t&) OP_THROWNOTHING {
- #if defined(Y_COVER_PTR)
- return malloc(size);
- #else
- return NBalloc::Malloc(size);
- #endif
- }
- void operator delete[](void* p) OP_THROWNOTHING {
- #if defined(Y_COVER_PTR)
- free(p);
- #else
- NBalloc::Free(p);
- #endif
- }
- void operator delete[](void* p, const std::nothrow_t&) OP_THROWNOTHING {
- #if defined(Y_COVER_PTR)
- free(p);
- #else
- NBalloc::Free(p);
- #endif
- }
- extern "C" void* calloc(size_t n, size_t elemSize) {
- const size_t size = n * elemSize;
- if (elemSize != 0 && size / elemSize != n) {
- return nullptr;
- }
- #if defined(Y_COVER_PTR)
- void* result = malloc(size);
- #else
- void* result = NBalloc::Malloc(size);
- #endif
- if (result) {
- memset(result, 0, size);
- }
- return result;
- }
- extern "C" void cfree(void* ptr) {
- #if defined(Y_COVER_PTR)
- free(ptr);
- #else
- NBalloc::Free(ptr);
- #endif
- }
- #if defined(Y_COVER_PTR)
- static inline void* DoRealloc(void* oldPtr, size_t newSize) {
- #else
- extern "C" void* realloc(void* oldPtr, size_t newSize) {
- #endif
- if (!oldPtr) {
- void* result = NBalloc::Malloc(newSize);
- return result;
- }
- if (newSize == 0) {
- NBalloc::Free(oldPtr);
- return nullptr;
- }
- void* newPtr = NBalloc::Malloc(newSize);
- if (!newPtr) {
- return nullptr;
- }
- NBalloc::TAllocHeader* header = (NBalloc::TAllocHeader*)oldPtr - 1;
- const size_t oldSize = header->AllocSize & ~NBalloc::SIGNATURE_MASK;
- const size_t signature = header->AllocSize & NBalloc::SIGNATURE_MASK;
- if (Y_LIKELY((signature == NBalloc::ALIVE_SIGNATURE) || (signature == NBalloc::DISABLED_SIGNATURE))) {
- memcpy(newPtr, oldPtr, oldSize < newSize ? oldSize : newSize);
- NBalloc::Free(oldPtr);
- return newPtr;
- }
- NMalloc::AbortFromCorruptedAllocator();
- return nullptr;
- }
- #if defined(Y_COVER_PTR)
- extern "C" void* realloc(void* oldPtr, size_t newSize) {
- if (!oldPtr) {
- return malloc(newSize);
- }
- if (!newSize) {
- free(oldPtr);
- return nullptr;
- }
- return CoverPtr(DoRealloc(UncoverPtr(oldPtr), newSize + 32), newSize);
- }
- #endif
- // Only for testing purposes. Never use in production.
- extern "C" bool IsOwnedByBalloc(void* ptr) {
- return NBalloc::IsOwnedByBalloc(ptr);
- }
- extern "C" bool BallocDisabled() {
- return NBalloc::IsDisabled();
- }
- extern "C" void DisableBalloc() {
- NBalloc::Disable();
- }
- extern "C" void EnableBalloc() {
- NBalloc::Enable();
- }
- extern "C" void* memalign(size_t alignment, size_t size) {
- void* ptr;
- int res = posix_memalign(&ptr, alignment, size);
- return res ? nullptr : ptr;
- }
- extern "C" void* valloc(size_t size) {
- return memalign(NBalloc::PAGE_ELEM, size);
- }
- #if !defined(_MSC_VER) && !defined(_freebsd_)
- // Workaround for pthread_create bug in linux.
- extern "C" void* __libc_memalign(size_t alignment, size_t size) {
- return memalign(alignment, size);
- }
- #endif
|