alloc.cpp (Firebird-3.0.2.32703-0.tar.bz2) | : | alloc.cpp (Firebird-3.0.4.33054-0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 85 | skipping to change at line 85 | |||
static void* lastBlock; | static void* lastBlock; | |||
static void* stopAddress = (void*) 0x2254938; | static void* stopAddress = (void*) 0x2254938; | |||
***/ | ***/ | |||
#undef MEM_DEBUG | #undef MEM_DEBUG | |||
#if defined(DEBUG_GDS_ALLOC) && !defined(USE_VALGRIND) | #if defined(DEBUG_GDS_ALLOC) && !defined(USE_VALGRIND) | |||
#define MEM_DEBUG | #define MEM_DEBUG | |||
#endif | #endif | |||
#ifdef MEM_DEBUG | #ifdef MEM_DEBUG | |||
static const int GUARD_BYTES = Firebird::ALLOC_ALIGNMENT; // * 2048; | static const int GUARD_BYTES = ALLOC_ALIGNMENT; // * 2048; | |||
static const UCHAR INIT_BYTE = 0xCC; | static const UCHAR INIT_BYTE = 0xCC; | |||
static const UCHAR GUARD_BYTE = 0xDD; | static const UCHAR GUARD_BYTE = 0xDD; | |||
static const UCHAR DEL_BYTE = 0xEE; | static const UCHAR DEL_BYTE = 0xEE; | |||
#else | #else | |||
static const int GUARD_BYTES = 0; | static const int GUARD_BYTES = 0; | |||
#endif | #endif | |||
template <typename T> | template <typename T> | |||
T absVal(T n) throw () | T absVal(T n) throw () | |||
{ | { | |||
skipping to change at line 122 | skipping to change at line 122 | |||
void* memory; // Extent pointer | void* memory; // Extent pointer | |||
size_t size; // Size of extent | size_t size; // Size of extent | |||
int handle; // Valgrind handle of protected extent block | int handle; // Valgrind handle of protected extent block | |||
}; | }; | |||
DelayedExtent delayedExtents[DELAYED_EXTENT_COUNT]; | DelayedExtent delayedExtents[DELAYED_EXTENT_COUNT]; | |||
size_t delayedExtentCount = 0; | size_t delayedExtentCount = 0; | |||
size_t delayedExtentsPos = 0; | size_t delayedExtentsPos = 0; | |||
#endif | #endif | |||
// Uncomment to validate pool on every alloc\release operation. | ||||
// Could slowdown pool significantly ! | ||||
//#define VALIDATE_POOL | ||||
// We cache this amount of extents to avoid memory mapping overhead | // We cache this amount of extents to avoid memory mapping overhead | |||
const int MAP_CACHE_SIZE = 16; // == 1 MB | const int MAP_CACHE_SIZE = 16; // == 1 MB | |||
const size_t DEFAULT_ALLOCATION = 65536; | const size_t DEFAULT_ALLOCATION = 65536; | |||
Firebird::Vector<void*, MAP_CACHE_SIZE> extents_cache; | Firebird::Vector<void*, MAP_CACHE_SIZE> extents_cache; | |||
#ifndef WIN_NT | ||||
struct FailedBlock | ||||
{ | ||||
size_t blockSize; | ||||
FailedBlock* next; | ||||
FailedBlock** prev; | ||||
}; | ||||
FailedBlock* failedList = NULL; | ||||
#endif | ||||
void corrupt(const char* text) throw () | void corrupt(const char* text) throw () | |||
{ | { | |||
#ifdef DEV_BUILD | #ifdef DEV_BUILD | |||
fprintf(stderr, "%s\n", text); | fprintf(stderr, "%s\n", text); | |||
abort(); | abort(); | |||
#endif | #endif | |||
} | } | |||
} // anonymous namespace | } // anonymous namespace | |||
skipping to change at line 193 | skipping to change at line 208 | |||
template <class T> | template <class T> | |||
void validate(T* e) | void validate(T* e) | |||
{ | { | |||
if (e->next && e->next->prev != &(e->next)) | if (e->next && e->next->prev != &(e->next)) | |||
fatal_exception::raise("bad back link in SemiDoubleLink") ; | fatal_exception::raise("bad back link in SemiDoubleLink") ; | |||
} | } | |||
} | } | |||
#ifdef USE_VALGRIND | #ifdef USE_VALGRIND | |||
// Size of Valgrind red zone applied before and after memory block allocated for user | // Size of Valgrind red zone applied before and after memory block allocated for user | |||
#define VALGRIND_REDZONE 8 | #define VALGRIND_REDZONE MEM_ALIGN | |||
#undef MEM_DEBUG // valgrind works instead | #undef MEM_DEBUG // valgrind works instead | |||
#else | #else | |||
#define VALGRIND_REDZONE 0 | #define VALGRIND_REDZONE 0 | |||
#endif | #endif | |||
typedef SLONG INT32; | typedef SLONG INT32; | |||
class MemBlock; | class MemBlock; | |||
class MemMediumHunk; | class MemMediumHunk; | |||
skipping to change at line 228 | skipping to change at line 243 | |||
MemBlock* next; | MemBlock* next; | |||
}; | }; | |||
private: | private: | |||
size_t hdrLength; | size_t hdrLength; | |||
public: | public: | |||
#ifdef DEBUG_GDS_ALLOC | #ifdef DEBUG_GDS_ALLOC | |||
INT32 lineNumber; | INT32 lineNumber; | |||
const char *fileName; | const char *fileName; | |||
#elif (SIZEOF_VOID_P == 4) && (ALLOC_ALIGNMENT == 16) | ||||
FB_UINT64 dummyAlign; | ||||
#endif | #endif | |||
#if defined(USE_VALGRIND) && (VALGRIND_REDZONE != 0) | #if defined(USE_VALGRIND) && (VALGRIND_REDZONE != 0) | |||
char mbk_valgrind_redzone[VALGRIND_REDZONE]; | char mbk_valgrind_redzone[VALGRIND_REDZONE]; | |||
#endif | #endif | |||
MemHeader(size_t size) | MemHeader(size_t size) | |||
: pool(NULL), hdrLength(size) | : pool(NULL), hdrLength(size) | |||
{ | { | |||
fb_assert(size < MAX_USHORT); | fb_assert(size < MAX_USHORT); | |||
fb_assert(!(size & MEM_MASK)); | fb_assert(!(size & MEM_MASK)); | |||
skipping to change at line 514 | skipping to change at line 531 | |||
return MEM_ALIGN(sizeof(MemMediumHunk)); | return MEM_ALIGN(sizeof(MemMediumHunk)); | |||
} | } | |||
}; | }; | |||
class MemBigHunk | class MemBigHunk | |||
{ | { | |||
public: | public: | |||
MemBigHunk* next; | MemBigHunk* next; | |||
MemBigHunk** prev; | MemBigHunk** prev; | |||
const size_t length; | const size_t length; | |||
MemBlock block; | MemBlock* block; | |||
MemBigHunk(MemBigHunk** top, size_t l) | MemBigHunk(MemBigHunk** top, size_t l) | |||
: next(NULL), prev(NULL), length(l), block(MemBlock::HUGE_BLOCK, | : next(NULL), prev(NULL), length(l), | |||
length - hdrSize()) | block(new(((UCHAR*) this) + hdrSize()) MemBlock(MemBlock::HUGE_ | |||
BLOCK, length - hdrSize())) | ||||
{ | { | |||
SemiDoubleLink::push(top, this); | SemiDoubleLink::push(top, this); | |||
} | } | |||
#ifdef MEM_DEBUG | #ifdef MEM_DEBUG | |||
void print_contents(FILE* file, MemPool* pool, bool used_only, | void print_contents(FILE* file, MemPool* pool, bool used_only, | |||
const char* filter_path, const size_t filter_len) throw() | const char* filter_path, const size_t filter_len) throw() | |||
{ | { | |||
fprintf(file, "Big hunk %p: memory=%p length=%" SIZEFORMAT "\n", | fprintf(file, "Big hunk %p: memory=%p length=%" SIZEFORMAT "\n", | |||
this, &block, length); | this, block, length); | |||
block.print_contents(true, file, used_only, filter_path, filter_l | block->print_contents(true, file, used_only, filter_path, filter_ | |||
en); | len); | |||
if (next) | if (next) | |||
next->print_contents(file, pool, used_only, filter_path, filter_len); | next->print_contents(file, pool, used_only, filter_path, filter_len); | |||
} | } | |||
#endif | #endif | |||
static size_t hdrSize() | static size_t hdrSize() | |||
{ | { | |||
return offsetof(MemBigHunk, block); | return MEM_ALIGN(sizeof(MemBigHunk)); | |||
} | } | |||
void validate() | void validate() | |||
{ | { | |||
SemiDoubleLink::validate(this); | SemiDoubleLink::validate(this); | |||
block.assertBig(); | block->assertBig(); | |||
fb_assert(block.getSize() + hdrSize() == length); | fb_assert(block->getSize() + hdrSize() == length); | |||
} | } | |||
}; | }; | |||
enum GetSlotFor { SLOT_ALLOC, SLOT_FREE }; | enum GetSlotFor { SLOT_ALLOC, SLOT_FREE }; | |||
#if ALLOC_ALIGNMENT == 8 | ||||
const unsigned char lowSlots[] = | const unsigned char lowSlots[] = | |||
{ | { | |||
0, // 24 | 0, // 24 | |||
1, // 32 | 1, // 32 | |||
2, // 40 | 2, // 40 | |||
3, // 48 | 3, // 48 | |||
4, // 56 | 4, // 56 | |||
5, // 64 | 5, // 64 | |||
6, // 72 | 6, // 72 | |||
7, // 80 | 7, // 80 | |||
skipping to change at line 712 | skipping to change at line 731 | |||
472, // 21 | 472, // 21 | |||
528, // 22 | 528, // 22 | |||
592, // 23 | 592, // 23 | |||
664, // 24 | 664, // 24 | |||
744, // 25 | 744, // 25 | |||
832, // 26 | 832, // 26 | |||
928, // 27 | 928, // 27 | |||
1024, // 28 | 1024, // 28 | |||
}; | }; | |||
const int SLOT_SHIFT = 3; | ||||
#elif ALLOC_ALIGNMENT == 16 | ||||
const unsigned char lowSlots[] = | ||||
{ | ||||
0, // 32 | ||||
1, // 48 | ||||
2, // 64 | ||||
3, // 80 | ||||
4, // 96 | ||||
5, // 112 | ||||
6, // 128 | ||||
7, // 144 | ||||
8, // 160 | ||||
9, // 176 | ||||
9, // 192 | ||||
10, // 208 | ||||
10, // 224 | ||||
11, // 240 | ||||
11, // 256 | ||||
12, // 272 | ||||
12, // 288 | ||||
13, // 304 | ||||
13, // 320 | ||||
14, // 336 | ||||
14, // 352 | ||||
14, // 368 | ||||
15, // 384 | ||||
15, // 400 | ||||
15, // 416 | ||||
16, // 432 | ||||
16, // 448 | ||||
16, // 464 | ||||
17, // 480 | ||||
17, // 496 | ||||
17, // 512 | ||||
17, // 528 | ||||
18, // 544 | ||||
18, // 560 | ||||
18, // 576 | ||||
18, // 592 | ||||
19, // 608 | ||||
19, // 624 | ||||
19, // 640 | ||||
19, // 656 | ||||
19, // 672 | ||||
20, // 688 | ||||
20, // 704 | ||||
20, // 720 | ||||
20, // 736 | ||||
20, // 752 | ||||
21, // 768 | ||||
21, // 784 | ||||
21, // 800 | ||||
21, // 816 | ||||
21, // 832 | ||||
21, // 848 | ||||
22, // 864 | ||||
22, // 880 | ||||
22, // 896 | ||||
22, // 912 | ||||
22, // 928 | ||||
22, // 944 | ||||
23, // 960 | ||||
23, // 976 | ||||
23, // 992 | ||||
23, // 1008 | ||||
23, // 1024 | ||||
}; | ||||
const unsigned short lowLimits[] = | ||||
{ | ||||
32, // 0 | ||||
48, // 1 | ||||
64, // 2 | ||||
80, // 3 | ||||
96, // 4 | ||||
112, // 5 | ||||
128, // 6 | ||||
144, // 7 | ||||
160, // 8 | ||||
192, // 9 | ||||
224, // 10 | ||||
256, // 11 | ||||
288, // 12 | ||||
320, // 13 | ||||
368, // 14 | ||||
416, // 15 | ||||
464, // 16 | ||||
528, // 17 | ||||
592, // 18 | ||||
672, // 19 | ||||
752, // 20 | ||||
848, // 21 | ||||
944, // 22 | ||||
1024, // 23 | ||||
}; | ||||
const int SLOT_SHIFT = 4; | ||||
#endif | ||||
const size_t TINY_SLOTS = FB_NELEM(lowLimits); | const size_t TINY_SLOTS = FB_NELEM(lowLimits); | |||
const unsigned short* TINY_BLOCK_LIMIT = &lowLimits[TINY_SLOTS - 1]; | const unsigned short* TINY_BLOCK_LIMIT = &lowLimits[TINY_SLOTS - 1]; | |||
// Access to slots for small (<= 1Kb) blocks | // Access to slots for small (<= 1Kb) blocks | |||
class LowLimits | class LowLimits | |||
{ | { | |||
public: | public: | |||
#if ALLOC_ALIGNMENT == 8 | ||||
static const unsigned TOTAL_ELEMENTS = 29; // TINY_SLOTS | static const unsigned TOTAL_ELEMENTS = 29; // TINY_SLOTS | |||
#elif ALLOC_ALIGNMENT == 16 | ||||
static const unsigned TOTAL_ELEMENTS = 24; // TINY_SLOTS | ||||
#endif | ||||
static const unsigned TOP_LIMIT = 1024; // TINY_BLOCK_LIM IT | static const unsigned TOP_LIMIT = 1024; // TINY_BLOCK_LIM IT | |||
static unsigned getSlot(size_t size, GetSlotFor mode) | static unsigned getSlot(size_t size, GetSlotFor mode) | |||
{ | { | |||
// add 2 asserts as long as we have not found better way to decla re consts | // add 2 asserts as long as we have not found better way to decla re consts | |||
fb_assert(TOTAL_ELEMENTS == TINY_SLOTS); | fb_assert(TOTAL_ELEMENTS == TINY_SLOTS); | |||
fb_assert(TOP_LIMIT == *TINY_BLOCK_LIMIT); | fb_assert(TOP_LIMIT == *TINY_BLOCK_LIMIT); | |||
const size_t LOW_LIMIT = lowLimits[0]; | const size_t LOW_LIMIT = lowLimits[0]; | |||
fb_assert(size <= TOP_LIMIT); | fb_assert(size <= TOP_LIMIT); | |||
if (size < LOW_LIMIT) | if (size < LOW_LIMIT) | |||
size = LOW_LIMIT; | size = LOW_LIMIT; | |||
fb_assert(MEM_ALIGN(size) == size); | fb_assert(MEM_ALIGN(size) == size); | |||
unsigned slot = lowSlots[(size - LOW_LIMIT) >> 3]; | unsigned slot = lowSlots[(size - LOW_LIMIT) >> SLOT_SHIFT]; | |||
fb_assert(size <= lowLimits[slot]); | fb_assert(size <= lowLimits[slot]); | |||
if (lowLimits[slot] > size && mode == SLOT_FREE) | if (lowLimits[slot] > size && mode == SLOT_FREE) | |||
{ | { | |||
if (!slot) | if (!slot) | |||
return ~0; | return ~0; | |||
--slot; | --slot; | |||
} | } | |||
return slot; | return slot; | |||
} | } | |||
skipping to change at line 1516 | skipping to change at line 1639 | |||
public: | public: | |||
static MemPool* defaultMemPool; | static MemPool* defaultMemPool; | |||
MemPool(); | MemPool(); | |||
MemPool(MemPool& parent, MemoryStats& stats); | MemPool(MemPool& parent, MemoryStats& stats); | |||
virtual ~MemPool(void); | virtual ~MemPool(void); | |||
private: | private: | |||
static const size_t minAllocation = 65536; | static const size_t minAllocation = 65536; | |||
static const size_t roundingSize = 8; | static const size_t roundingSize = ALLOC_ALIGNMENT; | |||
FreeObjects<LinkedList, LowLimits> smallObjects; | FreeObjects<LinkedList, LowLimits> smallObjects; | |||
Vector<MemBlock*, 16> parentRedirected; | Vector<MemBlock*, 16> parentRedirected; | |||
FreeObjects<DoubleLinkedList, MediumLimits> mediumObjects; | FreeObjects<DoubleLinkedList, MediumLimits> mediumObjects; | |||
MemBigHunk* bigHunks; | MemBigHunk* bigHunks; | |||
Mutex mutex; | Mutex mutex; | |||
int blocksAllocated; | int blocksAllocated; | |||
int blocksActive; | int blocksActive; | |||
bool pool_destroying, parent_redirect; | bool pool_destroying, parent_redirect; | |||
// Statistics group for the pool | // Statistics group for the pool | |||
MemoryStats* stats; | MemoryStats* stats; | |||
// Parent pool if present | // Parent pool if present | |||
MemPool* parent; | MemPool* parent; | |||
// Memory used | // Memory used | |||
AtomicCounter used_memory, mapped_memory; | AtomicCounter used_memory, mapped_memory; | |||
private: | private: | |||
#ifdef VALIDATE_POOL | ||||
class Validator | ||||
{ | ||||
public: | ||||
Validator(MemPool* p) : | ||||
m_pool(p) | ||||
{ | ||||
m_pool->validate(); | ||||
} | ||||
~Validator() | ||||
{ | ||||
m_pool->validate(); | ||||
} | ||||
private: | ||||
MemPool* m_pool; | ||||
}; | ||||
#else | ||||
class Validator | ||||
{ | ||||
public: | ||||
Validator(MemPool*) {} | ||||
}; | ||||
#endif // VALIDATE_POOL | ||||
MemBlock* alloc(size_t from, size_t& length, bool flagRedirect) throw (OO M_EXCEPTION); | MemBlock* alloc(size_t from, size_t& length, bool flagRedirect) throw (OO M_EXCEPTION); | |||
void releaseBlock(MemBlock *block) throw (); | void releaseBlock(MemBlock *block) throw (); | |||
public: | public: | |||
void* allocate(size_t size ALLOC_PARAMS) throw (OOM_EXCEPTION); | void* allocate(size_t size ALLOC_PARAMS) throw (OOM_EXCEPTION); | |||
MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS) throw (OOM_EX CEPTION); | MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS) throw (OOM_EX CEPTION); | |||
private: | private: | |||
virtual void memoryIsExhausted(void) throw (OOM_EXCEPTION); | virtual void memoryIsExhausted(void) throw (OOM_EXCEPTION); | |||
void* allocRaw(size_t length) throw (OOM_EXCEPTION); | void* allocRaw(size_t length) throw (OOM_EXCEPTION); | |||
skipping to change at line 1596 | skipping to change at line 1745 | |||
return defaultMemPool; | return defaultMemPool; | |||
} | } | |||
static void cleanup() | static void cleanup() | |||
{ | { | |||
defaultMemPool->~MemPool(); | defaultMemPool->~MemPool(); | |||
defaultMemPool = NULL; | defaultMemPool = NULL; | |||
while (extents_cache.getCount()) | while (extents_cache.getCount()) | |||
releaseRaw(true, extents_cache.pop(), DEFAULT_ALLOCATION, false); | releaseRaw(true, extents_cache.pop(), DEFAULT_ALLOCATION, false); | |||
#ifndef WIN_NT | ||||
unsigned oldCount = 0; | ||||
for(;;) | ||||
{ | ||||
unsigned newCount = 0; | ||||
FailedBlock* oldList = failedList; | ||||
if (oldList) | ||||
{ | ||||
fb_assert(oldList->prev); | ||||
oldList->prev = &oldList; | ||||
failedList = NULL; | ||||
} | ||||
while (oldList) | ||||
{ | ||||
++newCount; | ||||
FailedBlock* fb = oldList; | ||||
SemiDoubleLink::pop(oldList); | ||||
releaseRaw(true, fb, fb->blockSize, false); | ||||
} | ||||
if (newCount == oldCount) | ||||
break; | ||||
oldCount = newCount; | ||||
} | ||||
#endif // WIN_NT | ||||
} | } | |||
// Statistics | // Statistics | |||
void increment_usage(size_t size) throw () | void increment_usage(size_t size) throw () | |||
{ | { | |||
stats->increment_usage(size); | stats->increment_usage(size); | |||
used_memory += size; | used_memory += size; | |||
} | } | |||
void decrement_usage(size_t size) throw () | void decrement_usage(size_t size) throw () | |||
skipping to change at line 1800 | skipping to change at line 1975 | |||
if (cache_mutex) | if (cache_mutex) | |||
{ | { | |||
cache_mutex->~Mutex(); | cache_mutex->~Mutex(); | |||
cache_mutex = NULL; | cache_mutex = NULL; | |||
} | } | |||
} | } | |||
MemPool::MemPool() | MemPool::MemPool() | |||
: pool_destroying(false), parent_redirect(false), stats(MemoryPool::defau lt_stats_group), parent(NULL) | : pool_destroying(false), parent_redirect(false), stats(MemoryPool::defau lt_stats_group), parent(NULL) | |||
{ | { | |||
fb_assert(offsetof(MemBlock, body) == MEM_ALIGN(offsetof(MemBlock, body)) ); | ||||
initialize(); | initialize(); | |||
} | } | |||
MemPool::MemPool(MemPool& p, MemoryStats& s) | MemPool::MemPool(MemPool& p, MemoryStats& s) | |||
: pool_destroying(false), parent_redirect(true), stats(&s), parent(&p) | : pool_destroying(false), parent_redirect(true), stats(&s), parent(&p) | |||
{ | { | |||
initialize(); | initialize(); | |||
} | } | |||
void MemPool::initialize() | void MemPool::initialize() | |||
skipping to change at line 1965 | skipping to change at line 2141 | |||
void MemoryPool::setStatsGroup(MemoryStats& newStats) throw () | void MemoryPool::setStatsGroup(MemoryStats& newStats) throw () | |||
{ | { | |||
pool->setStatsGroup(newStats); | pool->setStatsGroup(newStats); | |||
} | } | |||
MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) throw ( OOM_EXCEPTION) | MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) throw ( OOM_EXCEPTION) | |||
{ | { | |||
MutexEnsureUnlock guard(mutex, "MemPool::alloc"); | MutexEnsureUnlock guard(mutex, "MemPool::alloc"); | |||
guard.enter(); | guard.enter(); | |||
Validator vld(this); | ||||
// If this is a small block, look for it there | // If this is a small block, look for it there | |||
MemBlock* block = smallObjects.allocateBlock(this, from, length); | MemBlock* block = smallObjects.allocateBlock(this, from, length); | |||
if (block) | if (block) | |||
return block; | return block; | |||
if (parent_redirect && flagRedirect && length < PARENT_REDIRECT_THRESHOLD ) | if (parent_redirect && flagRedirect && length < PARENT_REDIRECT_THRESHOLD ) | |||
{ | { | |||
guard.leave(); | guard.leave(); | |||
block = parent->alloc(from, length, false); | block = parent->alloc(from, length, false); | |||
skipping to change at line 2012 | skipping to change at line 2190 | |||
/* | /* | |||
* OK, we've got a "big block" on hands. To maximize confusing, the ind icated | * OK, we've got a "big block" on hands. To maximize confusing, the ind icated | |||
* "length" of a free big block is the length of MemHeader plus body*/ | * "length" of a free big block is the length of MemHeader plus body*/ | |||
fb_assert(from == 0); | fb_assert(from == 0); | |||
size_t hunkLength = MemBigHunk::hdrSize() + offsetof(MemBlock, body) + le ngth; | size_t hunkLength = MemBigHunk::hdrSize() + offsetof(MemBlock, body) + le ngth; | |||
// Allocate the new hunk | // Allocate the new hunk | |||
MemBigHunk* hunk = new(allocRaw(hunkLength)) MemBigHunk(&bigHunks, hunkLe ngth); | MemBigHunk* hunk = new(allocRaw(hunkLength)) MemBigHunk(&bigHunks, hunkLe ngth); | |||
return &hunk->block; | return hunk->block; | |||
} | } | |||
MemBlock* MemPool::allocate2(size_t from, size_t& size | MemBlock* MemPool::allocate2(size_t from, size_t& size | |||
#ifdef DEBUG_GDS_ALLOC | #ifdef DEBUG_GDS_ALLOC | |||
, const char* fileName, int line | , const char* fileName, int line | |||
#endif | #endif | |||
) throw (OOM_EXCEPTION) | ) throw (OOM_EXCEPTION) | |||
{ | { | |||
size_t length = from ? size : ROUNDUP(size + VALGRIND_REDZONE, roundingSi ze) + GUARD_BYTES; | size_t length = from ? size : ROUNDUP(size + VALGRIND_REDZONE, roundingSi ze) + GUARD_BYTES; | |||
MemBlock* memory = alloc(from, length, true); | MemBlock* memory = alloc(from, length, true); | |||
skipping to change at line 2044 | skipping to change at line 2222 | |||
#endif | #endif | |||
#ifdef MEM_DEBUG | #ifdef MEM_DEBUG | |||
memset(&memory->body, INIT_BYTE, size); | memset(&memory->body, INIT_BYTE, size); | |||
memset(&memory->body + size, GUARD_BYTE, memory->getSize() - offsetof(Mem Block,body) - size); | memset(&memory->body + size, GUARD_BYTE, memory->getSize() - offsetof(Mem Block,body) - size); | |||
#endif | #endif | |||
++blocksAllocated; | ++blocksAllocated; | |||
++blocksActive; | ++blocksActive; | |||
fb_assert((U_IPTR)(&memory->body) % ALLOC_ALIGNMENT == 0); | ||||
return memory; | return memory; | |||
} | } | |||
void* MemPool::allocate(size_t size ALLOC_PARAMS) throw (OOM_EXCEPTION) | void* MemPool::allocate(size_t size ALLOC_PARAMS) throw (OOM_EXCEPTION) | |||
{ | { | |||
MemBlock* memory = allocate2(0, size ALLOC_PASS_ARGS); | MemBlock* memory = allocate2(0, size ALLOC_PASS_ARGS); | |||
increment_usage(memory->getSize()); | increment_usage(memory->getSize()); | |||
return &memory->body; | return &memory->body; | |||
skipping to change at line 2137 | skipping to change at line 2316 | |||
corrupt("guard bytes overwritten"); | corrupt("guard bytes overwritten"); | |||
} | } | |||
#endif | #endif | |||
--blocksActive; | --blocksActive; | |||
const size_t length = block->getSize(); | const size_t length = block->getSize(); | |||
MutexEnsureUnlock guard(mutex, "MemPool::release"); | MutexEnsureUnlock guard(mutex, "MemPool::release"); | |||
guard.enter(); | guard.enter(); | |||
Validator vld(this); | ||||
// If length is less than threshold, this is a small block | // If length is less than threshold, this is a small block | |||
if (smallObjects.deallocateBlock(block)) | if (smallObjects.deallocateBlock(block)) | |||
return; | return; | |||
// Redirected to parent block? | // Redirected to parent block? | |||
if (block->redirected()) | if (block->redirected()) | |||
{ | { | |||
FB_SIZE_T pos; | FB_SIZE_T pos; | |||
if (parentRedirected.find(block, pos)) | if (parentRedirected.find(block, pos)) | |||
parentRedirected.remove(pos); | parentRedirected.remove(pos); | |||
skipping to change at line 2197 | skipping to change at line 2378 | |||
} | } | |||
} | } | |||
#endif | #endif | |||
size = FB_ALIGN(size, get_map_page_size()); | size = FB_ALIGN(size, get_map_page_size()); | |||
#ifdef WIN_NT | #ifdef WIN_NT | |||
void* result = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); | void* result = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); | |||
if (!result) | if (!result) | |||
{ | ||||
#else // WIN_NT | #else // WIN_NT | |||
void* result = NULL; | ||||
if (failedList) | ||||
{ | ||||
MutexLockGuard guard(*cache_mutex, "MemPool::allocRaw"); | ||||
for (FailedBlock* fb = failedList; fb; fb = fb->next) | ||||
{ | ||||
if (fb->blockSize == size) | ||||
{ | ||||
result = fb; | ||||
SemiDoubleLink::pop(fb); | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
if (!result) | ||||
{ | ||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) | #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) | |||
#define MAP_ANONYMOUS MAP_ANON | #define MAP_ANONYMOUS MAP_ANON | |||
#endif | #endif | |||
#ifdef MAP_ANONYMOUS | #ifdef MAP_ANONYMOUS | |||
void* result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP _ANONYMOUS, -1, 0); | result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | M AP_ANONYMOUS, -1, 0); | |||
#else // MAP_ANONYMOUS | #else // MAP_ANONYMOUS | |||
if (dev_zero_fd < 0) | if (dev_zero_fd < 0) | |||
dev_zero_fd = os_utils::open("/dev/zero", O_RDWR); | dev_zero_fd = os_utils::open("/dev/zero", O_RDWR); | |||
void* result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_ | result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, de | |||
zero_fd, 0); | v_zero_fd, 0); | |||
#endif // MAP_ANONYMOUS | #endif // MAP_ANONYMOUS | |||
if (result == MAP_FAILED) | if (result == MAP_FAILED) | |||
#endif // WIN_NT | #endif // WIN_NT | |||
{ | { | |||
// failure happens! | // failure happens! | |||
memoryIsExhausted(); | memoryIsExhausted(); | |||
return NULL; | return NULL; | |||
} | ||||
} | } | |||
#ifdef USE_VALGRIND | #ifdef USE_VALGRIND | |||
// Let Valgrind forget that block was zero-initialized | // Let Valgrind forget that block was zero-initialized | |||
VALGRIND_DISCARD(VALGRIND_MAKE_WRITABLE(result, size)); | VALGRIND_DISCARD(VALGRIND_MAKE_WRITABLE(result, size)); | |||
#endif | #endif | |||
increment_mapping(size); | increment_mapping(size); | |||
return result; | return result; | |||
} | } | |||
skipping to change at line 2321 | skipping to change at line 2522 | |||
else | else | |||
{ | { | |||
// Let Valgrind forget about unmapped block | // Let Valgrind forget about unmapped block | |||
VALGRIND_DISCARD(handle); | VALGRIND_DISCARD(handle); | |||
} | } | |||
#endif | #endif | |||
size = FB_ALIGN(size, get_map_page_size()); | size = FB_ALIGN(size, get_map_page_size()); | |||
#ifdef WIN_NT | #ifdef WIN_NT | |||
if (!VirtualFree(block, 0, MEM_RELEASE)) | if (!VirtualFree(block, 0, MEM_RELEASE)) | |||
{ | ||||
#else // WIN_NT | #else // WIN_NT | |||
#if (defined SOLARIS) && (defined HAVE_CADDR_T) | #if (defined SOLARIS) && (defined HAVE_CADDR_T) | |||
if (munmap((caddr_t) block, size)) | int rc = munmap((caddr_t) block, size); | |||
#else | #else | |||
if (munmap(block, size)) | int rc = munmap(block, size); | |||
#endif | #endif | |||
if (rc) | ||||
{ | ||||
if (errno == ENOMEM) | ||||
{ | ||||
FailedBlock* failed = (FailedBlock*) block; | ||||
failed->blockSize = size; | ||||
MutexLockGuard guard(*cache_mutex, "MemPool::releaseRaw") | ||||
; | ||||
SemiDoubleLink::push(&failedList, failed); | ||||
return; | ||||
} | ||||
#endif // WIN_NT | #endif // WIN_NT | |||
corrupt("OS memory deallocation error"); | corrupt("OS memory deallocation error"); | |||
} | ||||
} | } | |||
void MemPool::globalFree(void* block) throw () | void MemPool::globalFree(void* block) throw () | |||
{ | { | |||
deallocate(block); | deallocate(block); | |||
} | } | |||
void* MemoryPool::calloc(size_t size ALLOC_PARAMS) throw (OOM_EXCEPTION) | void* MemoryPool::calloc(size_t size ALLOC_PARAMS) throw (OOM_EXCEPTION) | |||
{ | { | |||
void* block = allocate(size ALLOC_PASS_ARGS); | void* block = allocate(size ALLOC_PASS_ARGS); | |||
End of changes. 36 change blocks. | ||||
26 lines changed or deleted | 244 lines changed or added |