| 449 | |
| 450 | |
| 451 | static void* LargeBlockAlloc(size_t _nSize, ELFAllocCounter counter) { |
| 452 | size_t pgCount = (_nSize + 4095) / 4096; |
| 453 | #ifdef _MSC_VER |
| 454 | char* pRes = (char*)VirtualAlloc(0, (pgCount + 1) * 4096ll, MEM_COMMIT, PAGE_READWRITE); |
| 455 | if (Y_UNLIKELY(pRes == 0)) { |
| 456 | NMalloc::AbortFromCorruptedAllocator("out of memory"); |
| 457 | } |
| 458 | #else |
| 459 | |
| 460 | IncrementCounter(counter, pgCount * 4096ll); |
| 461 | IncrementCounter(CT_SYSTEM_ALLOC, 4096ll); |
| 462 | |
| 463 | int lbHash = pgCount % LB_BUF_HASH; |
| 464 | for (int i = 0; i < LB_BUF_SIZE; ++i) { |
| 465 | void* p = lbFreePtrs[lbHash][i]; |
| 466 | if (p == nullptr) |
| 467 | continue; |
| 468 | if (DoCas(&lbFreePtrs[lbHash][i], (void*)nullptr, p) == p) { |
| 469 | size_t realPageCount = TLargeBlk::As(p)->Pages; |
| 470 | if (realPageCount == pgCount) { |
| 471 | AtomicAdd(lbFreePageCount, -pgCount); |
| 472 | TLargeBlk::As(p)->Mark(ELarge::Alloc); |
| 473 | return p; |
| 474 | } else { |
| 475 | if (DoCas(&lbFreePtrs[lbHash][i], p, (void*)nullptr) != (void*)nullptr) { |
| 476 | // block was freed while we were busy |
| 477 | AtomicAdd(lbFreePageCount, -realPageCount); |
| 478 | LargeBlockUnmap(p, realPageCount); |
| 479 | --i; |
| 480 | } |
| 481 | } |
| 482 | } |
| 483 | } |
| 484 | char* pRes = AllocWithMMap((pgCount + 1) * 4096ll, MM_HUGE); |
| 485 | #endif |
| 486 | pRes += 4096ll; |
| 487 | TLargeBlk::As(pRes)->SetSize(_nSize, pgCount); |
| 488 | TLargeBlk::As(pRes)->Mark(ELarge::Alloc); |
| 489 | |
| 490 | return pRes; |
| 491 | } |
| 492 | |
| 493 | #ifndef _MSC_VER |
| 494 | static void FreeAllLargeBlockMem() { |
no test coverage detected