| 2430 | } |
| 2431 | |
| 2432 | void MemPool::releaseBlock(MemBlock* block, bool decrUsage) noexcept |
| 2433 | { |
| 2434 | if (block->pool != this) |
| 2435 | corrupt("bad block released"); |
| 2436 | |
| 2437 | #ifdef MEM_DEBUG |
| 2438 | for (const UCHAR* end = (UCHAR*) block + block->getSize(), *p = end - GUARD_BYTES; p < end;) |
| 2439 | { |
| 2440 | if (*p++ != GUARD_BYTE) |
| 2441 | corrupt("guard bytes overwritten"); |
| 2442 | } |
| 2443 | #endif |
| 2444 | |
| 2445 | const size_t length = block->getSize(); |
| 2446 | |
| 2447 | MutexEnsureUnlock guard(mutex, "MemPool::releaseBlock"); |
| 2448 | guard.enter(); |
| 2449 | --blocksActive; |
| 2450 | |
| 2451 | Validator vld(decrUsage ? this : NULL); |
| 2452 | |
| 2453 | if (decrUsage) |
| 2454 | decrement_usage(length); |
| 2455 | |
| 2456 | // If length is less than threshold, this is a small block |
| 2457 | if (smallObjects.deallocateBlock(block)) |
| 2458 | return; |
| 2459 | |
| 2460 | // Redirected to parent block? |
| 2461 | if (block->redirected()) |
| 2462 | { |
| 2463 | FB_SIZE_T pos; |
| 2464 | if (parentRedirected.find(block, pos)) |
| 2465 | parentRedirected.remove(pos); |
| 2466 | guard.leave(); |
| 2467 | |
| 2468 | #ifdef VALIDATE_POOL |
| 2469 | MutexLockGuard guard(parent->mutex, "MemPool::releaseBlock /parent"); |
| 2470 | #endif |
| 2471 | block->resetRedirect(parent); |
| 2472 | parent->releaseBlock(block, false); |
| 2473 | return; |
| 2474 | } |
| 2475 | |
| 2476 | // Medium block - with another threshold |
| 2477 | if (mediumObjects.deallocateBlock(block)) |
| 2478 | return; |
| 2479 | |
| 2480 | // This must be BIG block |
| 2481 | block->assertBig(); |
| 2482 | |
| 2483 | #ifdef MEM_DEBUG |
| 2484 | memset(&block->body, DEL_BYTE, length - offsetof(MemBlock, body)); |
| 2485 | #endif |
| 2486 | |
| 2487 | MemBigHunk* hunk = (MemBigHunk*)(((UCHAR*)block) - MemBigHunk::hdrSize()); |
| 2488 | SemiDoubleLink::remove(hunk); |
| 2489 | decrement_mapping(FB_ALIGN(hunk->length, get_map_page_size())); |
no test coverage detected