From f557016851fff73128c193c8d834af6bee6d5ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 22 Mar 2005 22:59:41 +0000 Subject: [PATCH] Applied our coding style, but all clases into the BPrivate namespace. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11953 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../libroot/posix/malloc/arch-specific.cpp | 1 + src/kernel/libroot/posix/malloc/block.h | 181 +++-- src/kernel/libroot/posix/malloc/config.h | 15 +- src/kernel/libroot/posix/malloc/heap.cpp | 553 +++++++------ src/kernel/libroot/posix/malloc/heap.h | 748 +++++++++--------- src/kernel/libroot/posix/malloc/heapstats.h | 182 ++--- .../libroot/posix/malloc/processheap.cpp | 254 +++--- src/kernel/libroot/posix/malloc/processheap.h | 293 +++---- .../libroot/posix/malloc/superblock.cpp | 140 ++-- src/kernel/libroot/posix/malloc/superblock.h | 336 ++++---- .../libroot/posix/malloc/threadheap.cpp | 106 +-- src/kernel/libroot/posix/malloc/threadheap.h | 185 +++-- src/kernel/libroot/posix/malloc/wrapper.cpp | 24 +- 13 files changed, 1569 insertions(+), 1449 deletions(-) diff --git a/src/kernel/libroot/posix/malloc/arch-specific.cpp b/src/kernel/libroot/posix/malloc/arch-specific.cpp index 3768827395..59172de7b3 100644 --- a/src/kernel/libroot/posix/malloc/arch-specific.cpp +++ b/src/kernel/libroot/posix/malloc/arch-specific.cpp @@ -33,6 +33,7 @@ extern "C" { #include #include +using namespace BPrivate; static area_id heap_region = -1; static addr_t brk; diff --git a/src/kernel/libroot/posix/malloc/block.h b/src/kernel/libroot/posix/malloc/block.h index 1c0b0fb7ab..3798be0727 100644 --- a/src/kernel/libroot/posix/malloc/block.h +++ b/src/kernel/libroot/posix/malloc/block.h @@ -24,148 +24,175 @@ //#include +namespace BPrivate { class superblock; class block { -public: - - block (superblock * sb) - : + public: + block(superblock * sb) + : #if HEAP_DEBUG - _magic (FREE_BLOCK_MAGIC), + _magic(FREE_BLOCK_MAGIC), #endif - _next (NULL), - _mySuperblock (sb) - {} + _next(NULL), _mySuperblock(sb) + { + } - block& operator= (const block& b) { + block & + operator=(const block & b) + { #if HEAP_DEBUG - _magic = b._magic; + _magic = b._magic; #endif - _next = b._next; - _mySuperblock = b._mySuperblock; + _next = b._next; + _mySuperblock = b._mySuperblock; #if HEAP_FRAG_STATS - _requestedSize = b._requestedSize; + _requestedSize = b._requestedSize; #endif - return *this; - } + return *this; + } - enum { ALLOCATED_BLOCK_MAGIC = 0xcafecafe, - FREE_BLOCK_MAGIC = 0xbabebabe }; + enum { + ALLOCATED_BLOCK_MAGIC = 0xcafecafe, + FREE_BLOCK_MAGIC = 0xbabebabe + }; - // Mark this block as free. - inline void markFree (void); + // Mark this block as free. + inline void markFree(void); - // Mark this block as allocated. - inline void markAllocated (void); + // Mark this block as allocated. + inline void markAllocated(void); - // Is this block valid? (i.e., - // does it have the right magic number?) - inline const int isValid (void) const; + // Is this block valid? (i.e., + // does it have the right magic number?) + inline const int isValid(void) const; - // Return the block's superblock pointer. - inline superblock * getSuperblock (void); + // Return the block's superblock pointer. + inline superblock *getSuperblock(void); #if HEAP_FRAG_STATS - void setRequestedSize (size_t s) - { - _requestedSize = s; - } + void + setRequestedSize(size_t s) + { + _requestedSize = s; + } - size_t getRequestedSize (void) { return _requestedSize; } + size_t + getRequestedSize(void) + { + return _requestedSize; + } #endif #if USE_PRIVATE_HEAPS - void setActualSize (size_t s) { _actualSize = s; } - size_t getActualSize (void) { return _actualSize; } + void + setActualSize(size_t s) + { + _actualSize = s; + } + + size_t + getActualSize(void) + { + return _actualSize; + } #endif + void + setNext(block * b) + { + _next = b; + } - void setNext (block * b) { _next = b; } - block * getNext (void) { return _next; } - -private: + block * + getNext(void) + { + return _next; + } + private: #if USE_PRIVATE_HEAPS - #if HEAP_DEBUG - union { - unsigned long _magic; - double _d1; // For alignment. - }; + union { + unsigned long _magic; + double _d1; // For alignment. + }; #endif - block * _next; // The next block in a linked-list of blocks. - size_t _actualSize; // The actual size of the block. - - union { - double _d2; // For alignment. - superblock * _mySuperblock; // A pointer to my superblock. - }; - + block *_next; // The next block in a linked-list of blocks. + size_t _actualSize; // The actual size of the block. + union { + double _d2; // For alignment. + superblock *_mySuperblock; // A pointer to my superblock. + }; #else // ! USE_PRIVATE_HEAPS #if HEAP_DEBUG - union { - unsigned long _magic; - double _d3; // For alignment. - }; + union { + unsigned long _magic; + double _d3; // For alignment. + }; #endif - block * _next; // The next block in a linked-list of blocks. - superblock * _mySuperblock; // A pointer to my superblock. - + block *_next; // The next block in a linked-list of blocks. + superblock *_mySuperblock; // A pointer to my superblock. #endif // USE_PRIVATE_HEAPS #if HEAP_FRAG_STATS - union { - double _d4; // This is just for alignment purposes. - size_t _requestedSize; // The amount of space requested (vs. allocated). - }; + union { + double _d4; // This is just for alignment purposes. + size_t _requestedSize; // The amount of space requested (vs. allocated). + }; #endif - // Disable copying. - - block (const block&); + // Disable copying. + block(const block &); }; -superblock * block::getSuperblock (void) +superblock * +block::getSuperblock(void) { #if HEAP_DEBUG - assert (isValid()); + assert(isValid()); #endif - return _mySuperblock; + + return _mySuperblock; } -void block::markFree (void) +void +block::markFree(void) { #if HEAP_DEBUG - assert (_magic == ALLOCATED_BLOCK_MAGIC); - _magic = FREE_BLOCK_MAGIC; + assert(_magic == ALLOCATED_BLOCK_MAGIC); + _magic = FREE_BLOCK_MAGIC; #endif } -void block::markAllocated (void) +void +block::markAllocated(void) { #if HEAP_DEBUG - assert (_magic == FREE_BLOCK_MAGIC); - _magic = ALLOCATED_BLOCK_MAGIC; + assert(_magic == FREE_BLOCK_MAGIC); + _magic = ALLOCATED_BLOCK_MAGIC; #endif } -const int block::isValid (void) const +const int +block::isValid(void) const { #if HEAP_DEBUG - return ((_magic == FREE_BLOCK_MAGIC) - || (_magic == ALLOCATED_BLOCK_MAGIC)); + return _magic == FREE_BLOCK_MAGIC + || _magic == ALLOCATED_BLOCK_MAGIC; #else - return 1; + return 1; #endif } +} // namespace BPrivate + #endif // _BLOCK_H_ diff --git a/src/kernel/libroot/posix/malloc/config.h b/src/kernel/libroot/posix/malloc/config.h index 633579b0e8..d7ff98e66c 100644 --- a/src/kernel/libroot/posix/malloc/config.h +++ b/src/kernel/libroot/posix/malloc/config.h @@ -20,11 +20,11 @@ #define _CONFIG_H_ #ifndef _REENTRANT -#define _REENTRANT // If defined, generate a multithreaded-capable version. +# define _REENTRANT // If defined, generate a multithreaded-capable version. #endif #ifndef USER_LOCKS -#define USER_LOCKS 1 // Use our own user-level locks if they're available for the current architecture. +# define USER_LOCKS 1 // Use our own user-level locks if they're available for the current architecture. #endif #define HEAP_LOG 0 // If non-zero, keep a log of heap accesses. @@ -63,15 +63,15 @@ enum { SUPERBLOCK_FULLNESS_GROUP = 9 }; // CACHE_LINE = The number of bytes in a cache line. #if defined(i386) || defined(WIN32) -#define CACHE_LINE 32 +# define CACHE_LINE 32 #endif #ifdef sparc -#define CACHE_LINE 64 +# define CACHE_LINE 64 #endif #ifdef __sgi -#define CACHE_LINE 128 +# define CACHE_LINE 128 #endif #ifndef CACHE_LINE @@ -82,11 +82,10 @@ enum { SUPERBLOCK_FULLNESS_GROUP = 9 }; #ifdef __GNUG__ // Use the max operator, an extension to C++ found in GNU C++. -#define MAX(a,b) ((a) >? (b)) +# define MAX(a,b) ((a) >? (b)) #else -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +# define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif #endif // _CONFIG_H_ - diff --git a/src/kernel/libroot/posix/malloc/heap.cpp b/src/kernel/libroot/posix/malloc/heap.cpp index 1c9cfa0306..f53f65d7f8 100644 --- a/src/kernel/libroot/posix/malloc/heap.cpp +++ b/src/kernel/libroot/posix/malloc/heap.cpp @@ -16,6 +16,7 @@ // Library General Public License for more details. // ////////////////////////////////////////////////////////////////////////////// + #include "config.h" #include "heap.h" @@ -23,7 +24,7 @@ #include "processheap.h" #include "superblock.h" -static const char version[] = "The Hoard memory allocator, version 2.0 (http://www.hoard.org). Copyright (C) 1998, 1999, 2000 The University of Texas at Austin. $Id: heap.cpp,v 1.2 2005/02/10 18:47:16 axeld Exp $"; +using namespace BPrivate; // NB: Use maketable.cpp to update this // if SIZE_CLASSES, ALIGNMENT, SIZE_CLASS_BASE, MAX_EMPTY_SUPERBLOCKS, @@ -31,354 +32,404 @@ static const char version[] = "The Hoard memory allocator, version 2.0 (http://w #if (MAX_INTERNAL_FRAGMENTATION == 2) -size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = {8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 72UL, 80UL, 96UL, 120UL, 144UL, 168UL, 200UL, 240UL, 288UL, 344UL, 416UL, 496UL, 592UL, 712UL, 856UL, 1024UL, 1232UL, 1472UL, 1768UL, 2120UL, 2544UL, 3048UL, 3664UL, 4392UL, 5272UL, 6320UL, 7584UL, 9104UL, 10928UL, 13112UL, 15728UL, 18872UL, 22648UL, 27176UL, 32616UL, 39136UL, 46960UL, 56352UL, 67624UL, 81144UL, 97376UL, 116848UL, 140216UL, 168256UL, 201904UL, 242288UL, 290744UL, 348896UL, 418672UL, 502408UL, 602888UL, 723464UL, 868152UL, 1041784UL, 1250136UL, 1500160UL, 1800192UL, 2160232UL, 2592280UL, 3110736UL, 3732880UL, 4479456UL, 5375344UL, 6450408UL, 7740496UL, 9288592UL, 11146312UL, 13375568UL, 16050680UL, 19260816UL, 23112984UL, 27735576UL, 33282688UL, 39939224UL, 47927072UL, 57512488UL, 69014984UL, 82817976UL, 99381576UL, 119257888UL, 143109472UL, 171731360UL, 206077632UL, 247293152UL, 296751776UL, 356102144UL, 427322560UL, 512787072UL, 615344512UL, 738413376UL, 886096064UL, 1063315264UL}; +size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = { + 8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 72UL, 80UL, 96UL, 120UL, 144UL, + 168UL, 200UL, 240UL, 288UL, 344UL, 416UL, 496UL, 592UL, 712UL, 856UL, + 1024UL, 1232UL, 1472UL, 1768UL, 2120UL, 2544UL, 3048UL, 3664UL, + 4392UL, 5272UL, 6320UL, 7584UL, 9104UL, 10928UL, 13112UL, 15728UL, + 18872UL, 22648UL, 27176UL, 32616UL, 39136UL, 46960UL, 56352UL, + 67624UL, 81144UL, 97376UL, 116848UL, 140216UL, 168256UL, 201904UL, + 242288UL, 290744UL, 348896UL, 418672UL, 502408UL, 602888UL, 723464UL, + 868152UL, 1041784UL, 1250136UL, 1500160UL, 1800192UL, 2160232UL, + 2592280UL, 3110736UL, 3732880UL, 4479456UL, 5375344UL, 6450408UL, + 7740496UL, 9288592UL, 11146312UL, 13375568UL, 16050680UL, 19260816UL, + 23112984UL, 27735576UL, 33282688UL, 39939224UL, 47927072UL, + 57512488UL, 69014984UL, 82817976UL, 99381576UL, 119257888UL, + 143109472UL, 171731360UL, 206077632UL, 247293152UL, 296751776UL, + 356102144UL, 427322560UL, 512787072UL, 615344512UL, 738413376UL, + 886096064UL, 1063315264UL +}; -size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {4096UL, 2048UL, 1364UL, 1024UL, 816UL, 680UL, 584UL, 452UL, 408UL, 340UL, 272UL, 224UL, 192UL, 160UL, 136UL, 112UL, 92UL, 76UL, 64UL, 52UL, 44UL, 36UL, 32UL, 24UL, 20UL, 16UL, 12UL, 12UL, 8UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL}; +size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = { + 4096UL, 2048UL, 1364UL, 1024UL, 816UL, 680UL, 584UL, 452UL, 408UL, + 340UL, 272UL, 224UL, 192UL, 160UL, 136UL, 112UL, 92UL, 76UL, 64UL, + 52UL, 44UL, 36UL, 32UL, 24UL, 20UL, 16UL, 12UL, 12UL, 8UL, 8UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL +}; #elif (MAX_INTERNAL_FRAGMENTATION == 6) -size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = {8UL, 16UL, 24UL, 32UL, 48UL, 72UL, 112UL, 176UL, 288UL, 456UL, 728UL, 1160UL, 1848UL, 2952UL, 4728UL, 7560UL, 12096UL, 19344UL, 30952UL, 49520UL, 79232UL, 126768UL, 202832UL, 324520UL, 519232UL, 830768UL, 1329232UL, 2126768UL, 3402824UL, 5444520UL, 8711232UL, 13937968UL, 22300752UL, 35681200UL, 57089912UL, 91343856UL, 146150176UL, 233840256UL, 374144416UL, 598631040UL, 957809728UL, 1532495488UL}; +size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = { + 8UL, 16UL, 24UL, 32UL, 48UL, 72UL, 112UL, 176UL, 288UL, 456UL, 728UL, + 1160UL, 1848UL, 2952UL, 4728UL, 7560UL, 12096UL, 19344UL, 30952UL, + 49520UL, 79232UL, 126768UL, 202832UL, 324520UL, 519232UL, 830768UL, + 1329232UL, 2126768UL, 3402824UL, 5444520UL, 8711232UL, 13937968UL, + 22300752UL, 35681200UL, 57089912UL, 91343856UL, 146150176UL, + 233840256UL, 374144416UL, 598631040UL, 957809728UL, 1532495488UL +}; -size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {4096UL, 2048UL, 1364UL, 1024UL, 680UL, 452UL, 292UL, 184UL, 112UL, 68UL, 44UL, 28UL, 16UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL}; +size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = { + 4096UL, 2048UL, 1364UL, 1024UL, 680UL, 452UL, 292UL, 184UL, 112UL, 68UL, + 44UL, 28UL, 16UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL +}; #elif (MAX_INTERNAL_FRAGMENTATION == 10) -size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = {8UL, 16UL, 32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL, 8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL, 1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL, 67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL, 2147483648UL}; +size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = { + 8UL, 16UL, 32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL, + 8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL, + 1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL, + 67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL, + 2147483648UL +}; -size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {4096UL, 2048UL, 1024UL, 512UL, 256UL, 128UL, 64UL, 32UL, 16UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL}; +size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = { + 4096UL, 2048UL, 1024UL, 512UL, 256UL, 128UL, 64UL, 32UL, 16UL, 8UL, 4UL, + 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, + 4UL, 4UL, 4UL, 4UL +}; #else -#error "Undefined size class base." +# error "Undefined size class base." #endif -hoardHeap::hoardHeap (void) - : _index (0), - _reusableSuperblocks (NULL), - _reusableSuperblocksCount (0) +hoardHeap::hoardHeap(void) + : + _index(0), _reusableSuperblocks(NULL), _reusableSuperblocksCount(0) #if HEAP_DEBUG - , _magic (HEAP_MAGIC) + , _magic(HEAP_MAGIC) #endif { - // Initialize the per-heap lock. - hoardLockInit(_lock, "hoard heap"); - for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { - for (int j = 0; j < SIZE_CLASSES; j++) { - // Initialize all superblocks lists to empty. - _superblocks[i][j] = NULL; - } - } - for (int k = 0; k < SIZE_CLASSES; k++) { - _leastEmptyBin[k] = 0; - } + // Initialize the per-heap lock. + hoardLockInit(_lock, "hoard heap"); + + for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { + for (int j = 0; j < SIZE_CLASSES; j++) { + // Initialize all superblocks lists to empty. + _superblocks[i][j] = NULL; + } + } + + for (int k = 0; k < SIZE_CLASSES; k++) { + _leastEmptyBin[k] = 0; + } } -void hoardHeap::insertSuperblock (int sizeclass, - superblock * sb, - processHeap * pHeap) +void +hoardHeap::insertSuperblock(int sizeclass, + superblock *sb, processHeap *pHeap) { - assert (sb->isValid()); - assert (sb->getBlockSizeClass() == sizeclass); - assert (sb->getPrev() == NULL); - assert (sb->getNext() == NULL); - assert (_magic == HEAP_MAGIC); + assert(sb->isValid()); + assert(sb->getBlockSizeClass() == sizeclass); + assert(sb->getPrev() == NULL); + assert(sb->getNext() == NULL); + assert(_magic == HEAP_MAGIC); - // Now it's ours. - sb->setOwner (this); + // Now it's ours. + sb->setOwner(this); - // How full is this superblock? We'll use this information to put - // it into the right 'bin'. - sb->computeFullness(); - int fullness = sb->getFullness(); + // How full is this superblock? We'll use this information to put + // it into the right 'bin'. + sb->computeFullness(); + int fullness = sb->getFullness(); - // Update the stats. - incStats (sizeclass, - sb->getNumBlocks() - sb->getNumAvailable(), - sb->getNumBlocks()); + // Update the stats. + incStats(sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); - if ((fullness == 0) && - (sb->getNumBlocks() > 1) && - (sb->getNumBlocks() == sb->getNumAvailable())) { - // Recycle this superblock. + if (fullness == 0 + && sb->getNumBlocks() > 1 + && sb->getNumBlocks() == sb->getNumAvailable()) { + // Recycle this superblock. #if 0 - removeSuperblock (sb, sizeclass); - // Update the stats. - decStats (sizeclass, - sb->getNumBlocks() - sb->getNumAvailable(), - sb->getNumBlocks()); - // Free it immediately. - const size_t s = sizeFromClass (sizeclass); - const int blksize = align (sizeof(block) + s); + removeSuperblock(sb, sizeclass); + // Update the stats. + decStats(sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks()); + // Free it immediately. + const size_t s = sizeFromClass(sizeclass); + const int blksize = align(sizeof(block) + s); #if HEAP_LOG - // Record the memory deallocation. - MemoryRequest m; - m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); - pHeap->getLog(getIndex()).append(m); + // Record the memory deallocation. + MemoryRequest m; + m.deallocate((int)sb->getNumBlocks() * + (int)sizeFromClass(sb->getBlockSizeClass())); + pHeap->getLog(getIndex()).append(m); #endif #if HEAP_FRAG_STATS - pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); + + pHeap->setDeallocated(0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); #endif - hoardUnsbrk (sb, align (sizeof(superblock) + blksize)); + + hoardUnsbrk(sb, align(sizeof(superblock) + blksize)); #else - recycle (sb); + recycle(sb); #endif - } else { + } else { + // Insert it into the appropriate list. + superblock *&head = _superblocks[fullness][sizeclass]; + sb->insertBefore(head); + head = sb; + assert(head->isValid()); - // Insert it into the appropriate list. - superblock *& head = _superblocks[fullness][sizeclass]; - sb->insertBefore (head); - head = sb; - assert (head->isValid()); - - // Reset the least-empty bin counter. - _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN; - } + // Reset the least-empty bin counter. + _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN; + } } -superblock * hoardHeap::removeMaxSuperblock (int sizeclass) +superblock * +hoardHeap::removeMaxSuperblock(int sizeclass) { - assert (_magic == HEAP_MAGIC); + assert(_magic == HEAP_MAGIC); - superblock * head = NULL; + superblock *head = NULL; - // First check the reusable superblocks list. + // First check the reusable superblocks list. - head = reuse (sizeclass); - if (head) { - // We found one. Since we're removing this superblock, update the - // stats accordingly. - decStats (sizeclass, - head->getNumBlocks() - head->getNumAvailable(), - head->getNumBlocks()); + head = reuse(sizeclass); + if (head) { + // We found one. Since we're removing this superblock, update the + // stats accordingly. + decStats(sizeclass, + head->getNumBlocks() - head->getNumAvailable(), + head->getNumBlocks()); - return head; - } + return head; + } - // Instead of finding the superblock with the most available space - // (something that would either involve a linear scan through the - // superblocks or maintaining the superblocks in sorted order), we - // just pick one that is no more than - // 1/(SUPERBLOCK_FULLNESS_GROUP-1) more full than the superblock - // with the most available space. We start with the emptiest group. + // Instead of finding the superblock with the most available space + // (something that would either involve a linear scan through the + // superblocks or maintaining the superblocks in sorted order), we + // just pick one that is no more than + // 1/(SUPERBLOCK_FULLNESS_GROUP-1) more full than the superblock + // with the most available space. We start with the emptiest group. - int i = 0; + int i = 0; - // Note: the last group (SUPERBLOCK_FULLNESS_GROUP - 1) is full, so - // we never need to check it. But for robustness, we leave it in. - while (i < SUPERBLOCK_FULLNESS_GROUP) { - head = _superblocks[i][sizeclass]; - if (head) { - break; - } - i++; - } + // Note: the last group (SUPERBLOCK_FULLNESS_GROUP - 1) is full, so + // we never need to check it. But for robustness, we leave it in. + while (i < SUPERBLOCK_FULLNESS_GROUP) { + head = _superblocks[i][sizeclass]; + if (head) + break; - if (!head) { - return NULL; - } + i++; + } - // Make sure that this superblock is at least 1/EMPTY_FRACTION - // empty. - assert (head->getNumAvailable() * EMPTY_FRACTION >= head->getNumBlocks()); + if (!head) + return NULL; - removeSuperblock (head, sizeclass); + // Make sure that this superblock is at least 1/EMPTY_FRACTION + // empty. + assert(head->getNumAvailable() * EMPTY_FRACTION >= head->getNumBlocks()); - assert (head->isValid()); - assert (head->getPrev() == NULL); - assert (head->getNext() == NULL); - return head; + removeSuperblock(head, sizeclass); + + assert(head->isValid()); + assert(head->getPrev() == NULL); + assert(head->getNext() == NULL); + return head; } -void hoardHeap::removeSuperblock (superblock * sb, - int sizeclass) +void +hoardHeap::removeSuperblock(superblock *sb, int sizeclass) { - assert (_magic == HEAP_MAGIC); + assert(_magic == HEAP_MAGIC); - assert (sb->isValid()); - assert (sb->getOwner() == this); - assert (sb->getBlockSizeClass() == sizeclass); + assert(sb->isValid()); + assert(sb->getOwner() == this); + assert(sb->getBlockSizeClass() == sizeclass); - for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { - if (sb == _superblocks[i][sizeclass]) { - _superblocks[i][sizeclass] = sb->getNext(); - if (_superblocks[i][sizeclass] != NULL) { - assert (_superblocks[i][sizeclass]->isValid()); - } - break; - } - } + for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { + if (sb == _superblocks[i][sizeclass]) { + _superblocks[i][sizeclass] = sb->getNext(); + if (_superblocks[i][sizeclass] != NULL) { + assert(_superblocks[i][sizeclass]->isValid()); + } + break; + } + } - sb->remove(); - decStats (sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks()); + sb->remove(); + decStats(sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); } -void hoardHeap::moveSuperblock (superblock * sb, - int sizeclass, - int fromBin, - int toBin) +void +hoardHeap::moveSuperblock(superblock *sb, + int sizeclass, int fromBin, int toBin) { - assert (_magic == HEAP_MAGIC); - assert (sb->isValid()); - assert (sb->getOwner() == this); - assert (sb->getBlockSizeClass() == sizeclass); - assert (sb->getFullness() == toBin); + assert(_magic == HEAP_MAGIC); + assert(sb->isValid()); + assert(sb->getOwner() == this); + assert(sb->getBlockSizeClass() == sizeclass); + assert(sb->getFullness() == toBin); - // Remove the superblock from the old bin. + // Remove the superblock from the old bin. - superblock *& oldHead = _superblocks[fromBin][sizeclass]; - if (sb == oldHead) { - oldHead = sb->getNext(); - if (oldHead != NULL) { - assert (oldHead->isValid()); - } - } + superblock *&oldHead = _superblocks[fromBin][sizeclass]; + if (sb == oldHead) { + oldHead = sb->getNext(); + if (oldHead != NULL) { + assert(oldHead->isValid()); + } + } - sb->remove(); + sb->remove(); - // Insert the superblock into the new bin. + // Insert the superblock into the new bin. - superblock *& newHead = _superblocks[toBin][sizeclass]; - sb->insertBefore (newHead); - newHead = sb; - assert (newHead->isValid()); + superblock *&newHead = _superblocks[toBin][sizeclass]; + sb->insertBefore(newHead); + newHead = sb; + assert(newHead->isValid()); - // Reset the least-empty bin counter. - _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN; + // Reset the least-empty bin counter. + _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN; } // The heap lock must be held when this procedure is called. -int hoardHeap::freeBlock (block *& b, - superblock *& sb, - int sizeclass, - processHeap * pHeap) +int +hoardHeap::freeBlock(block * &b, superblock * &sb, + int sizeclass, processHeap *pHeap) { - assert (sb->isValid()); - assert (b->isValid()); - assert (this == sb->getOwner()); + assert(sb->isValid()); + assert(b->isValid()); + assert(this == sb->getOwner()); - const int oldFullness = sb->getFullness(); - sb->putBlock (b); - decUStats (sizeclass); - const int newFullness = sb->getFullness(); - - // Free big superblocks. - if (sb->getNumBlocks() == 1) { - removeSuperblock (sb, sizeclass); - const size_t s = sizeFromClass (sizeclass); - const int blksize = align (sizeof(block) + s); + const int oldFullness = sb->getFullness(); + sb->putBlock(b); + decUStats(sizeclass); + const int newFullness = sb->getFullness(); + + // Free big superblocks. + if (sb->getNumBlocks() == 1) { + removeSuperblock(sb, sizeclass); + const size_t s = sizeFromClass(sizeclass); + const int blksize = align(sizeof(block) + s); #if HEAP_LOG - // Record the memory deallocation. - MemoryRequest m; - m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); - pHeap->getLog(getIndex()).append(m); + // Record the memory deallocation. + MemoryRequest m; + m.deallocate((int)sb->getNumBlocks() + * (int)sizeFromClass(sb->getBlockSizeClass())); + pHeap->getLog(getIndex()).append(m); #endif #if HEAP_FRAG_STATS - pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); + pHeap->setDeallocated(0, + sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); #endif - hoardUnsbrk (sb, align (sizeof(superblock) + blksize)); - return 1; - } + hoardUnsbrk(sb, align(sizeof(superblock) + blksize)); + return 1; + } - // If the fullness value has changed, move the superblock. - if (newFullness != oldFullness) { - moveSuperblock (sb, sizeclass, oldFullness, newFullness); - } else { - // Move the superblock to the front of its list (to reduce - // paging). - superblock *& head = _superblocks[newFullness][sizeclass]; - if (sb != head) { - sb->remove(); - sb->insertBefore (head); - head = sb; - } - } - - // If the superblock is now empty, recycle it. + // If the fullness value has changed, move the superblock. + if (newFullness != oldFullness) { + moveSuperblock(sb, sizeclass, oldFullness, newFullness); + } else { + // Move the superblock to the front of its list (to reduce + // paging). + superblock *&head = _superblocks[newFullness][sizeclass]; + if (sb != head) { + sb->remove(); + sb->insertBefore(head); + head = sb; + } + } - if ((newFullness == 0) && - (sb->getNumBlocks() == sb->getNumAvailable())) { - removeSuperblock (sb, sizeclass); + // If the superblock is now empty, recycle it. + + if ((newFullness == 0) && (sb->getNumBlocks() == sb->getNumAvailable())) { + removeSuperblock(sb, sizeclass); #if 0 - // Free it immediately. - const size_t s = sizeFromClass (sizeclass); - const int blksize = align (sizeof(block) + s); + // Free it immediately. + const size_t s = sizeFromClass(sizeclass); + const int blksize = align(sizeof(block) + s); #if HEAP_LOG - // Record the memory deallocation. - MemoryRequest m; - m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); - pHeap->getLog(getIndex()).append(m); + // Record the memory deallocation. + MemoryRequest m; + m.deallocate((int)sb->getNumBlocks() + * (int)sizeFromClass(sb->getBlockSizeClass())); + pHeap->getLog(getIndex()).append(m); #endif #if HEAP_FRAG_STATS - pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); + pHeap->setDeallocated(0, + sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); #endif - hoardUnsbrk (sb, align (sizeof(superblock) + blksize)); - return 1; + + hoardUnsbrk(sb, align(sizeof(superblock) + blksize)); + return 1; #else - recycle (sb); - // Update the stats. This restores the stats to their state - // before the call to removeSuperblock, above. - incStats (sizeclass, - sb->getNumBlocks() - sb->getNumAvailable(), - sb->getNumBlocks()); + recycle(sb); + // Update the stats. This restores the stats to their state + // before the call to removeSuperblock, above. + incStats(sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks()); #endif - } + } - // If this is the process heap, then we're done. - if (this == (hoardHeap *) pHeap) { - return 0; - } + // If this is the process heap, then we're done. + if (this == (hoardHeap *)pHeap) + return 0; - // - // Release a superblock, if necessary. - // + // + // Release a superblock, if necessary. + // - // - // Check to see if the amount free exceeds the release threshold - // (two superblocks worth of blocks for a given sizeclass) and if - // the heap is sufficiently empty. - // + // + // Check to see if the amount free exceeds the release threshold + // (two superblocks worth of blocks for a given sizeclass) and if + // the heap is sufficiently empty. + // - // We never move anything to the process heap if we're on a - // uniprocessor. - if (_numProcessors > 1) { - int inUse, allocated; - getStats (sizeclass, inUse, allocated); - if ((inUse < allocated - getReleaseThreshold(sizeclass)) - && (EMPTY_FRACTION * inUse < EMPTY_FRACTION * allocated - allocated)) { - - // We've crossed the magical threshold. Find the superblock with - // the most free blocks and give it to the process heap. - superblock * const maxSb = removeMaxSuperblock (sizeclass); - assert (maxSb != NULL); - - // Update the statistics. - - assert (maxSb->getNumBlocks() >= maxSb->getNumAvailable()); - - // Give the superblock back to the process heap. - pHeap->release (maxSb); - - } - } + // We never move anything to the process heap if we're on a + // uniprocessor. + if (_numProcessors > 1) { + int inUse, allocated; + getStats(sizeclass, inUse, allocated); + if ((inUse < allocated - getReleaseThreshold(sizeclass)) + && (EMPTY_FRACTION * inUse < + EMPTY_FRACTION * allocated - allocated)) { - return 0; + // We've crossed the magical threshold. Find the superblock with + // the most free blocks and give it to the process heap. + superblock *const maxSb = removeMaxSuperblock(sizeclass); + assert(maxSb != NULL); + + // Update the statistics. + + assert(maxSb->getNumBlocks() >= maxSb->getNumAvailable()); + + // Give the superblock back to the process heap. + pHeap->release(maxSb); + } + } + + return 0; } // Static initialization of the number of processors (and a mask). - + int hoardHeap::_numProcessors; int hoardHeap::_numProcessorsMask; hoardHeap::_initNumProcs::_initNumProcs(void) { - hoardHeap::_numProcessors = hoardGetNumProcessors(); - hoardHeap::_numProcessorsMask = (1 << (lg(hoardGetNumProcessors()) + 1)) - 1; + hoardHeap::_numProcessors = hoardGetNumProcessors(); + hoardHeap::_numProcessorsMask = + (1 << (lg(hoardGetNumProcessors()) + 1)) - 1; } static hoardHeap::_initNumProcs initProcs; diff --git a/src/kernel/libroot/posix/malloc/heap.h b/src/kernel/libroot/posix/malloc/heap.h index 5f783f1fdb..cef837a0e8 100644 --- a/src/kernel/libroot/posix/malloc/heap.h +++ b/src/kernel/libroot/posix/malloc/heap.h @@ -30,485 +30,503 @@ #include "superblock.h" #include "heapstats.h" -class processHeap; // forward declaration +namespace BPrivate { + +class processHeap; class hoardHeap { + public: + hoardHeap(void); -public: + // A superblock that holds more than one object must hold at least + // this many bytes. + enum { SUPERBLOCK_SIZE = 8192 }; - hoardHeap (void); + // A thread heap must be at least 1/EMPTY_FRACTION empty before we + // start returning superblocks to the process heap. + enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 }; - // A superblock that holds more than one object must hold at least - // this many bytes. - enum { SUPERBLOCK_SIZE = 8192 }; + // Reset value for the least-empty bin. The last bin + // (SUPERBLOCK_FULLNESS_GROUP-1) is for completely full superblocks, + // so we use the next-to-last bin. + enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 }; - // A thread heap must be at least 1/EMPTY_FRACTION empty before we - // start returning superblocks to the process heap. - enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 }; + // The number of empty superblocks that we allow any thread heap to + // hold once the thread heap has fallen below 1/EMPTY_FRACTION + // empty. + enum { MAX_EMPTY_SUPERBLOCKS = EMPTY_FRACTION }; - // Reset value for the least-empty bin. The last bin - // (SUPERBLOCK_FULLNESS_GROUP-1) is for completely full superblocks, - // so we use the next-to-last bin. - enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 }; + // The maximum number of thread heaps we allow. (NOT the maximum + // number of threads -- Hoard imposes no such limit.) This must be + // a power of two! NB: This number is twice the maximum number of + // PROCESSORS supported by Hoard. + enum { MAX_HEAPS = B_MAX_CPU_COUNT }; - // The number of empty superblocks that we allow any thread heap to - // hold once the thread heap has fallen below 1/EMPTY_FRACTION - // empty. - enum { MAX_EMPTY_SUPERBLOCKS = EMPTY_FRACTION }; + // ANDing with this rounds to MAX_HEAPS. + enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 }; - // The maximum number of thread heaps we allow. (NOT the maximum - // number of threads -- Hoard imposes no such limit.) This must be - // a power of two! NB: This number is twice the maximum number of - // PROCESSORS supported by Hoard. - enum { MAX_HEAPS = B_MAX_CPU_COUNT }; - - // ANDing with this rounds to MAX_HEAPS. - enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 }; - - // - // The number of size classes. This combined with the - // SIZE_CLASS_BASE determine the maximum size of an object. - // - // NB: Once this is changed, you must execute maketable.cpp and put - // the generated values into heap.cpp. + // + // The number of size classes. This combined with the + // SIZE_CLASS_BASE determine the maximum size of an object. + // + // NB: Once this is changed, you must execute maketable.cpp and put + // the generated values into heap.cpp. #if MAX_INTERNAL_FRAGMENTATION == 2 - enum { SIZE_CLASSES = 115 }; + enum { SIZE_CLASSES = 115 }; #elif MAX_INTERNAL_FRAGMENTATION == 6 - enum { SIZE_CLASSES = 46 }; + enum { SIZE_CLASSES = 46 }; #elif MAX_INTERNAL_FRAGMENTATION == 10 - enum { SIZE_CLASSES = 32 }; + enum { SIZE_CLASSES = 32 }; #else # error "Undefined size class base." #endif - // Every object is aligned so that it can always hold a double. - enum { ALIGNMENT = sizeof(double) }; + // Every object is aligned so that it can always hold a double. + enum { ALIGNMENT = sizeof(double) }; - // ANDing with this rounds to ALIGNMENT. - enum { ALIGNMENT_MASK = ALIGNMENT - 1}; + // ANDing with this rounds to ALIGNMENT. + enum { ALIGNMENT_MASK = ALIGNMENT - 1 }; - // Used for sanity checking. - enum { HEAP_MAGIC = 0x0badcafe }; + // Used for sanity checking. + enum { HEAP_MAGIC = 0x0badcafe }; - // Get the usage and allocated statistics. - inline void getStats (int sizeclass, int& U, int& A); + // Get the usage and allocated statistics. + inline void getStats(int sizeclass, int &U, int &A); #if HEAP_STATS - // How much is the maximum ever in use for this size class? - inline int maxInUse (int sizeclass); + // How much is the maximum ever in use for this size class? + inline int maxInUse(int sizeclass); - // How much is the maximum memory allocated for this size class? - inline int maxAllocated (int sizeclass); + // How much is the maximum memory allocated for this size class? + inline int maxAllocated(int sizeclass); #endif - // Insert a superblock into our list. - void insertSuperblock (int sizeclass, - superblock * sb, - processHeap * pHeap); + // Insert a superblock into our list. + void insertSuperblock(int sizeclass, superblock *sb, processHeap *pHeap); - // Remove the superblock with the most free space. - superblock * removeMaxSuperblock (int sizeclass); + // Remove the superblock with the most free space. + superblock *removeMaxSuperblock(int sizeclass); - // Find an available superblock (i.e., with some space in it). - inline superblock * findAvailableSuperblock (int sizeclass, - block *& b, - processHeap * pHeap); + // Find an available superblock (i.e., with some space in it). + inline superblock *findAvailableSuperblock(int sizeclass, + block * &b, processHeap * pHeap); - // Lock this heap. - inline void lock (void); + // Lock this heap. + inline void lock(void); - // Unlock this heap. - inline void unlock (void); + // Unlock this heap. + inline void unlock(void); - // Set our index number (which heap we are). - inline void setIndex (int i); + // Set our index number (which heap we are). + inline void setIndex(int i); - // Get our index number (which heap we are). - inline int getIndex (void); + // Get our index number (which heap we are). + inline int getIndex(void); - // Free a block into a superblock. - // This is used by processHeap::free(). - // Returns 1 iff the superblock was munmapped. - int freeBlock (block *& b, - superblock *& sb, - int sizeclass, - processHeap * pHeap); + // Free a block into a superblock. + // This is used by processHeap::free(). + // Returns 1 iff the superblock was munmapped. + int freeBlock(block * &b, superblock * &sb, int sizeclass, + processHeap * pHeap); - //// Utility functions //// + //// Utility functions //// - // Return the size class for a given size. - inline static int sizeClass (const size_t sz); + // Return the size class for a given size. + inline static int sizeClass(const size_t sz); - // Return the size corresponding to a given size class. - inline static size_t sizeFromClass (const int sizeclass); + // Return the size corresponding to a given size class. + inline static size_t sizeFromClass(const int sizeclass); - // Return the release threshold corresponding to a given size class. - inline static int getReleaseThreshold (const int sizeclass); + // Return the release threshold corresponding to a given size class. + inline static int getReleaseThreshold(const int sizeclass); - // Return how many blocks of a given size class fit into a superblock. - inline static int numBlocks (const int sizeclass); + // Return how many blocks of a given size class fit into a superblock. + inline static int numBlocks(const int sizeclass); - // Align a value. - inline static size_t align (const size_t sz); + // Align a value. + inline static size_t align(const size_t sz); -private: + private: + // Disable copying and assignment. - // Disable copying and assignment. + hoardHeap(const hoardHeap &); + const hoardHeap & operator=(const hoardHeap &); - hoardHeap (const hoardHeap&); - const hoardHeap& operator= (const hoardHeap&); + // Recycle a superblock. + inline void recycle(superblock *); - // Recycle a superblock. - inline void recycle (superblock *); + // Reuse a superblock (if one is available). + inline superblock *reuse(int sizeclass); - // Reuse a superblock (if one is available). - inline superblock * reuse (int sizeclass); + // Remove a particular superblock. + void removeSuperblock(superblock *, int sizeclass); - // Remove a particular superblock. - void removeSuperblock (superblock *, int sizeclass); + // Move a particular superblock from one bin to another. + void moveSuperblock(superblock *, + int sizeclass, int fromBin, int toBin); - // Move a particular superblock from one bin to another. - void moveSuperblock (superblock *, - int sizeclass, - int fromBin, - int toBin); + // Update memory in-use and allocated statistics. + // (*UStats = just update U.) + inline void incStats(int sizeclass, int updateU, int updateA); + inline void incUStats(int sizeclass); - // Update memory in-use and allocated statistics. - // (*UStats = just update U.) - inline void incStats (int sizeclass, int updateU, int updateA); - inline void incUStats (int sizeclass); + inline void decStats(int sizeclass, int updateU, int updateA); + inline void decUStats(int sizeclass); - inline void decStats (int sizeclass, int updateU, int updateA); - inline void decUStats (int sizeclass); - - //// Members //// + //// Members //// #if HEAP_DEBUG - // For sanity checking. - const unsigned long _magic; + // For sanity checking. + const unsigned long _magic; #else # define _magic HEAP_MAGIC #endif - // Heap statistics. - heapStats _stats[SIZE_CLASSES]; + // Heap statistics. + heapStats _stats[SIZE_CLASSES]; - // The per-heap lock. - hoardLockType _lock; + // The per-heap lock. + hoardLockType _lock; - // Which heap this is (0 = the process (global) heap). - int _index; + // Which heap this is (0 = the process (global) heap). + int _index; - // Reusable superblocks. - superblock * _reusableSuperblocks; - int _reusableSuperblocksCount; + // Reusable superblocks. + superblock *_reusableSuperblocks; + int _reusableSuperblocksCount; - // Lists of superblocks. - superblock * _superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES]; + // Lists of superblocks. + superblock *_superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES]; - // The current least-empty superblock bin. - int _leastEmptyBin[SIZE_CLASSES]; + // The current least-empty superblock bin. + int _leastEmptyBin[SIZE_CLASSES]; - // The lookup table for size classes. - static size_t _sizeTable[SIZE_CLASSES]; + // The lookup table for size classes. + static size_t _sizeTable[SIZE_CLASSES]; - // The lookup table for release thresholds. - static size_t _threshold[SIZE_CLASSES]; + // The lookup table for release thresholds. + static size_t _threshold[SIZE_CLASSES]; -public: - // A little helper class that we use to define some statics. - class _initNumProcs { - public: - _initNumProcs(void); - }; + public: + // A little helper class that we use to define some statics. + class _initNumProcs { + public: + _initNumProcs(void); + }; - friend class _initNumProcs; -protected: - // number of CPUs, cached - static int _numProcessors; - static int _numProcessorsMask; + friend class _initNumProcs; + + protected: + // number of CPUs, cached + static int _numProcessors; + static int _numProcessorsMask; }; -void hoardHeap::incStats (int sizeclass, int updateU, int updateA) { - assert (_magic == HEAP_MAGIC); - assert (updateU >= 0); - assert (updateA >= 0); - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - _stats[sizeclass].incStats (updateU, updateA); -} - - - -void hoardHeap::incUStats (int sizeclass) { - assert (_magic == HEAP_MAGIC); - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - _stats[sizeclass].incUStats (); -} - - -void hoardHeap::decStats (int sizeclass, int updateU, int updateA) { - assert (_magic == HEAP_MAGIC); - assert (updateU >= 0); - assert (updateA >= 0); - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - _stats[sizeclass].decStats (updateU, updateA); -} - - -void hoardHeap::decUStats (int sizeclass) +void +hoardHeap::incStats(int sizeclass, int updateU, int updateA) { - assert (_magic == HEAP_MAGIC); - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - _stats[sizeclass].decUStats(); + assert(_magic == HEAP_MAGIC); + assert(updateU >= 0); + assert(updateA >= 0); + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + _stats[sizeclass].incStats(updateU, updateA); } -void hoardHeap::getStats (int sizeclass, int& U, int& A) { - assert (_magic == HEAP_MAGIC); - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - _stats[sizeclass].getStats (U, A); +void +hoardHeap::incUStats(int sizeclass) +{ + assert(_magic == HEAP_MAGIC); + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + _stats[sizeclass].incUStats(); +} + + +void +hoardHeap::decStats(int sizeclass, int updateU, int updateA) +{ + assert(_magic == HEAP_MAGIC); + assert(updateU >= 0); + assert(updateA >= 0); + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + _stats[sizeclass].decStats(updateU, updateA); +} + + +void +hoardHeap::decUStats(int sizeclass) +{ + assert(_magic == HEAP_MAGIC); + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + _stats[sizeclass].decUStats(); +} + + +void +hoardHeap::getStats(int sizeclass, int &U, int &A) +{ + assert(_magic == HEAP_MAGIC); + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + _stats[sizeclass].getStats(U, A); } #if HEAP_STATS -int hoardHeap::maxInUse (int sizeclass) { - assert (_magic == HEAP_MAGIC); - return _stats[sizeclass].getUmax(); -} - - -int hoardHeap::maxAllocated (int sizeclass) { - assert (_magic == HEAP_MAGIC); - return _stats[sizeclass].getAmax(); -} -#endif - - -superblock * hoardHeap::findAvailableSuperblock (int sizeclass, - block *& b, - processHeap * pHeap) +int +hoardHeap::maxInUse(int sizeclass) { - assert (this); - assert (_magic == HEAP_MAGIC); - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); + assert(_magic == HEAP_MAGIC); + return _stats[sizeclass].getUmax(); +} - superblock * sb = NULL; - int reUsed = 0; - // Look through the superblocks, starting with the almost-full ones - // and going to the emptiest ones. The Least Empty Bin for a - // sizeclass is a conservative approximation (fixed after one - // iteration) of the first bin that has superblocks in it, starting - // with (surprise) the least-empty bin. +int +hoardHeap::maxAllocated(int sizeclass) +{ + assert(_magic == HEAP_MAGIC); + return _stats[sizeclass].getAmax(); +} +#endif // HEAP_STATS - for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) { - sb = _superblocks[i][sizeclass]; - if (sb == NULL) { - if (i == _leastEmptyBin[sizeclass]) { - // There wasn't a superblock in this bin, - // so we adjust the least empty bin. - _leastEmptyBin[sizeclass]--; - } - } else if(sb->getNumAvailable() > 0){ - assert (sb->getOwner() == this); - break; - } - sb = NULL; - } + +superblock * +hoardHeap::findAvailableSuperblock(int sizeclass, + block * &b, processHeap * pHeap) +{ + assert(this); + assert(_magic == HEAP_MAGIC); + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + + superblock *sb = NULL; + int reUsed = 0; + + // Look through the superblocks, starting with the almost-full ones + // and going to the emptiest ones. The Least Empty Bin for a + // sizeclass is a conservative approximation (fixed after one + // iteration) of the first bin that has superblocks in it, starting + // with (surprise) the least-empty bin. + + for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) { + sb = _superblocks[i][sizeclass]; + if (sb == NULL) { + if (i == _leastEmptyBin[sizeclass]) { + // There wasn't a superblock in this bin, + // so we adjust the least empty bin. + _leastEmptyBin[sizeclass]--; + } + } else if (sb->getNumAvailable() > 0) { + assert(sb->getOwner() == this); + break; + } + sb = NULL; + } #if 1 - if (sb == NULL) { - // Try to reuse a superblock. - sb = reuse (sizeclass); - if (sb) { - assert (sb->getOwner() == this); - reUsed = 1; - } - } + if (sb == NULL) { + // Try to reuse a superblock. + sb = reuse(sizeclass); + if (sb) { + assert(sb->getOwner() == this); + reUsed = 1; + } + } #endif - if (sb != NULL) { - // Sanity checks: - // This superblock is 'valid'. - assert (sb->isValid()); - // This superblock has the right ownership. - assert (sb->getOwner() == this); + if (sb != NULL) { + // Sanity checks: + // This superblock is 'valid'. + assert(sb->isValid()); + // This superblock has the right ownership. + assert(sb->getOwner() == this); - int oldFullness = sb->getFullness(); + int oldFullness = sb->getFullness(); - // Now get a block from the superblock. - // This superblock must have space available. - b = sb->getBlock(); - assert (b != NULL); + // Now get a block from the superblock. + // This superblock must have space available. + b = sb->getBlock(); + assert(b != NULL); - // Update the stats. - incUStats (sizeclass); + // Update the stats. + incUStats(sizeclass); - if (reUsed) { - insertSuperblock (sizeclass, sb, pHeap); - // Fix the stats (since insert will just have incremented them - // by this amount). - decStats (sizeclass, - sb->getNumBlocks() - sb->getNumAvailable(), - sb->getNumBlocks()); - } else { - // If we've crossed a fullness group, - // move the superblock. - int fullness = sb->getFullness(); + if (reUsed) { + insertSuperblock(sizeclass, sb, pHeap); + // Fix the stats (since insert will just have incremented them + // by this amount). + decStats(sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + } else { + // If we've crossed a fullness group, + // move the superblock. + int fullness = sb->getFullness(); - if (fullness != oldFullness) { - // Move the superblock. - moveSuperblock (sb, sizeclass, oldFullness, fullness); - } - } - } + if (fullness != oldFullness) { + // Move the superblock. + moveSuperblock(sb, sizeclass, oldFullness, fullness); + } + } + } + // Either we didn't find a superblock or we did and got a block. + assert((sb == NULL) || (b != NULL)); + // Either we didn't get a block or we did and we also got a superblock. + assert((b == NULL) || (sb != NULL)); - // Either we didn't find a superblock or we did and got a block. - assert ((sb == NULL) || (b != NULL)); - // Either we didn't get a block or we did and we also got a superblock. - assert ((b == NULL) || (sb != NULL)); - - return sb; + return sb; } -int hoardHeap::sizeClass (const size_t sz) { - // Find the size class for a given object size - // (the smallest i such that _sizeTable[i] >= sz). - int sizeclass = 0; - while (_sizeTable[sizeclass] < sz) - { - sizeclass++; - assert (sizeclass < SIZE_CLASSES); - } - return sizeclass; -} - - -size_t hoardHeap::sizeFromClass (const int sizeclass) { - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - return _sizeTable[sizeclass]; -} - - -int hoardHeap::getReleaseThreshold (const int sizeclass) { - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - return _threshold[sizeclass]; -} - - -int hoardHeap::numBlocks (const int sizeclass) { - assert (sizeclass >= 0); - assert (sizeclass < SIZE_CLASSES); - const size_t s = sizeFromClass (sizeclass); - assert (s > 0); - const int blksize = align (sizeof(block) + s); - // Compute the number of blocks that will go into this superblock. - int nb = MAX (1, ((SUPERBLOCK_SIZE - sizeof(superblock)) / blksize)); - return nb; -} - - -void hoardHeap::lock (void) +int +hoardHeap::sizeClass(const size_t sz) { - assert (_magic == HEAP_MAGIC); - hoardLock (_lock); + // Find the size class for a given object size + // (the smallest i such that _sizeTable[i] >= sz). + int sizeclass = 0; + while (_sizeTable[sizeclass] < sz) { + sizeclass++; + assert(sizeclass < SIZE_CLASSES); + } + return sizeclass; } -void hoardHeap::unlock (void) { - assert (_magic == HEAP_MAGIC); - hoardUnlock (_lock); -} - - -size_t hoardHeap::align (const size_t sz) +size_t +hoardHeap::sizeFromClass(const int sizeclass) { - // Align sz up to the nearest multiple of ALIGNMENT. - // This is much faster than using multiplication - // and division. - return (sz + ALIGNMENT_MASK) & ~ALIGNMENT_MASK; + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + return _sizeTable[sizeclass]; } -void hoardHeap::setIndex (int i) +int +hoardHeap::getReleaseThreshold(const int sizeclass) { - _index = i; + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + return _threshold[sizeclass]; } -int hoardHeap::getIndex (void) +int +hoardHeap::numBlocks(const int sizeclass) { - return _index; + assert(sizeclass >= 0); + assert(sizeclass < SIZE_CLASSES); + const size_t s = sizeFromClass(sizeclass); + assert(s > 0); + const int blksize = align(sizeof(block) + s); + // Compute the number of blocks that will go into this superblock. + int nb = MAX(1, ((SUPERBLOCK_SIZE - sizeof(superblock)) / blksize)); + return nb; } - - -void hoardHeap::recycle (superblock * sb) +void +hoardHeap::lock(void) { - assert (sb != NULL); - assert (sb->getOwner() == this); - assert (sb->getNumBlocks() > 1); - assert (sb->getNext() == NULL); - assert (sb->getPrev() == NULL); - assert (hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1); - sb->insertBefore (_reusableSuperblocks); - _reusableSuperblocks = sb; - ++_reusableSuperblocksCount; - // printf ("count: %d => %d\n", getIndex(), _reusableSuperblocksCount); + assert(_magic == HEAP_MAGIC); + hoardLock(_lock); } -superblock * hoardHeap::reuse (int sizeclass) +void +hoardHeap::unlock(void) { - if (_reusableSuperblocks == NULL) { - return NULL; - } - - // Make sure that we aren't using a sizeclass - // that is too big for a 'normal' superblock. - if (hoardHeap::numBlocks(sizeclass) <= 1) { - return NULL; - } - - // Pop off a superblock from the reusable-superblock list. - assert (_reusableSuperblocksCount > 0); - superblock * sb = _reusableSuperblocks; - _reusableSuperblocks = sb->getNext(); - sb->remove(); - assert (sb->getNumBlocks() > 1); - --_reusableSuperblocksCount; - - // Reformat the superblock if necessary. - if (sb->getBlockSizeClass() != sizeclass) { - decStats (sb->getBlockSizeClass(), - sb->getNumBlocks() - sb->getNumAvailable(), - sb->getNumBlocks()); - - sb = new ((char *) sb) superblock (numBlocks(sizeclass), sizeclass, this); - - incStats (sizeclass, - sb->getNumBlocks() - sb->getNumAvailable(), - sb->getNumBlocks()); - } - - assert (sb->getOwner() == this); - assert (sb->getBlockSizeClass() == sizeclass); - return sb; + assert(_magic == HEAP_MAGIC); + hoardUnlock(_lock); } + +size_t +hoardHeap::align(const size_t sz) +{ + // Align sz up to the nearest multiple of ALIGNMENT. + // This is much faster than using multiplication + // and division. + return (sz + ALIGNMENT_MASK) & ~ALIGNMENT_MASK; +} + + +void +hoardHeap::setIndex(int i) +{ + _index = i; +} + + +int +hoardHeap::getIndex(void) +{ + return _index; +} + + +void +hoardHeap::recycle(superblock *sb) +{ + assert(sb != NULL); + assert(sb->getOwner() == this); + assert(sb->getNumBlocks() > 1); + assert(sb->getNext() == NULL); + assert(sb->getPrev() == NULL); + assert(hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1); + sb->insertBefore(_reusableSuperblocks); + _reusableSuperblocks = sb; + ++_reusableSuperblocksCount; + // printf ("count: %d => %d\n", getIndex(), _reusableSuperblocksCount); +} + + +superblock * +hoardHeap::reuse(int sizeclass) +{ + if (_reusableSuperblocks == NULL) + return NULL; + + // Make sure that we aren't using a sizeclass + // that is too big for a 'normal' superblock. + if (hoardHeap::numBlocks(sizeclass) <= 1) + return NULL; + + // Pop off a superblock from the reusable-superblock list. + assert(_reusableSuperblocksCount > 0); + superblock *sb = _reusableSuperblocks; + _reusableSuperblocks = sb->getNext(); + sb->remove(); + assert(sb->getNumBlocks() > 1); + --_reusableSuperblocksCount; + + // Reformat the superblock if necessary. + if (sb->getBlockSizeClass() != sizeclass) { + decStats(sb->getBlockSizeClass(), + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + + sb = new((char *)sb) superblock(numBlocks(sizeclass), + sizeclass, this); + + incStats(sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + } + + assert(sb->getOwner() == this); + assert(sb->getBlockSizeClass() == sizeclass); + return sb; +} + +} // namespace BPrivate + #endif // _HEAP_H_ diff --git a/src/kernel/libroot/posix/malloc/heapstats.h b/src/kernel/libroot/posix/malloc/heapstats.h index fceefec27b..387cac65a9 100644 --- a/src/kernel/libroot/posix/malloc/heapstats.h +++ b/src/kernel/libroot/posix/malloc/heapstats.h @@ -26,148 +26,150 @@ class heapStats { -public: - - heapStats (void) - : - U (0), - A (0) + public: + heapStats(void) + : U(0), A(0) #if HEAP_STATS - ,Umax (0), - Amax (0) + , Umax(0), Amax(0) #endif - {} + { + } - inline const heapStats& operator= (const heapStats& p); + inline const heapStats & operator=(const heapStats & p); - inline void incStats (int updateU, int updateA); - inline void incUStats (void); + inline void incStats(int updateU, int updateA); + inline void incUStats(void); - inline void decStats (int updateU, int updateA); - inline void decUStats (void); - inline void decUStats (int& Uout, int& Aout); - - inline void getStats (int& Uout, int& Aout); + inline void decStats(int updateU, int updateA); + inline void decUStats(void); + inline void decUStats(int &Uout, int &Aout); + inline void getStats(int &Uout, int &Aout); #if HEAP_STATS - - inline int getUmax (void); - inline int getAmax (void); - + inline int getUmax(void); + inline int getAmax(void); #endif + private: + // U and A *must* be the first items in this class -- + // we will depend on this to atomically update them. -private: - - // U and A *must* be the first items in this class -- - // we will depend on this to atomically update them. - - int U; // Memory in use. - int A; // Memory allocated. + int U; // Memory in use. + int A; // Memory allocated. #if HEAP_STATS - int Umax; - int Amax; + int Umax; + int Amax; #endif }; -inline void heapStats::incStats (int updateU, int updateA) +inline void +heapStats::incStats(int updateU, int updateA) { - assert (updateU >= 0); - assert (updateA >= 0); - assert (U <= A); - assert (U >= 0); - assert (A >= 0); - U += updateU; - A += updateA; + assert(updateU >= 0); + assert(updateA >= 0); + assert(U <= A); + assert(U >= 0); + assert(A >= 0); + U += updateU; + A += updateA; + #if HEAP_STATS - Amax = MAX (Amax, A); - Umax = MAX (Umax, U); + Amax = MAX(Amax, A); + Umax = MAX(Umax, U); #endif - assert (U <= A); - assert (U >= 0); - assert (A >= 0); + + assert(U <= A); + assert(U >= 0); + assert(A >= 0); } -inline void heapStats::incUStats (void) +inline void +heapStats::incUStats(void) { - assert (U < A); - assert (U >= 0); - assert (A >= 0); - U++; + assert(U < A); + assert(U >= 0); + assert(A >= 0); + U++; + #if HEAP_STATS - Umax = MAX (Umax, U); + Umax = MAX(Umax, U); #endif - assert (U >= 0); - assert (A >= 0); + + assert(U >= 0); + assert(A >= 0); } -inline void heapStats::decStats (int updateU, int updateA) +inline void +heapStats::decStats(int updateU, int updateA) { - assert (updateU >= 0); - assert (updateA >= 0); - assert (U <= A); - assert (U >= updateU); - assert (A >= updateA); - U -= updateU; - A -= updateA; - assert (U <= A); - assert (U >= 0); - assert (A >= 0); + assert(updateU >= 0); + assert(updateA >= 0); + assert(U <= A); + assert(U >= updateU); + assert(A >= updateA); + U -= updateU; + A -= updateA; + assert(U <= A); + assert(U >= 0); + assert(A >= 0); } -inline void heapStats::decUStats (int& Uout, int& Aout) +inline void +heapStats::decUStats(int &Uout, int &Aout) { - assert (U <= A); - assert (U > 0); - assert (A >= 0); - U--; - Uout = U; - Aout = A; - assert (U >= 0); - assert (A >= 0); + assert(U <= A); + assert(U > 0); + assert(A >= 0); + U--; + Uout = U; + Aout = A; + assert(U >= 0); + assert(A >= 0); } -inline void heapStats::decUStats (void) +inline void +heapStats::decUStats(void) { - assert (U <= A); - assert (U > 0); - assert (A >= 0); - U--; + assert(U <= A); + assert(U > 0); + assert(A >= 0); + U--; } -inline void heapStats::getStats (int& Uout, int& Aout) +inline void +heapStats::getStats(int &Uout, int &Aout) { - assert (U >= 0); - assert (A >= 0); - Uout = U; - Aout = A; - assert (U <= A); - assert (U >= 0); - assert (A >= 0); + assert(U >= 0); + assert(A >= 0); + Uout = U; + Aout = A; + assert(U <= A); + assert(U >= 0); + assert(A >= 0); } #if HEAP_STATS -inline int heapStats::getUmax (void) +inline int +heapStats::getUmax(void) { - return Umax; + return Umax; } -inline int heapStats::getAmax (void) +inline int +heapStats::getAmax(void) { - return Amax; + return Amax; } #endif // HEAP_STATS - - #endif // _HEAPSTATS_H_ diff --git a/src/kernel/libroot/posix/malloc/processheap.cpp b/src/kernel/libroot/posix/malloc/processheap.cpp index b0c1343bfa..989e145a93 100644 --- a/src/kernel/libroot/posix/malloc/processheap.cpp +++ b/src/kernel/libroot/posix/malloc/processheap.cpp @@ -23,111 +23,115 @@ #include "config.h" #if USE_PRIVATE_HEAPS -#include "privateheap.h" -#define HEAPTYPE privateHeap +# include "privateheap.h" +# define HEAPTYPE privateHeap #else -#define HEAPTYPE threadHeap -#include "threadheap.h" +# define HEAPTYPE threadHeap +# include "threadheap.h" #endif #include "processheap.h" +using namespace BPrivate; -processHeap::processHeap (void) - : _buffer (NULL), - _bufferCount (0) + +processHeap::processHeap(void) + : _buffer(NULL), _bufferCount(0) #if HEAP_FRAG_STATS - , _currentAllocated (0), - _currentRequested (0), - _maxAllocated (0), - _inUseAtMaxAllocated (0), - _maxRequested (0) + , _currentAllocated(0), + _currentRequested(0), + _maxAllocated(0), _inUseAtMaxAllocated(0), _maxRequested(0) #endif { - int i; - // The process heap is heap 0. - setIndex (0); - for (i = 0; i < MAX_HEAPS; i++) { - // Set every thread's process heap to this one. - theap[i].setpHeap (this); - // Set every thread heap's index. - theap[i].setIndex (i + 1); - } + int i; + // The process heap is heap 0. + setIndex(0); + for (i = 0; i < MAX_HEAPS; i++) { + // Set every thread's process heap to this one. + theap[i].setpHeap(this); + // Set every thread heap's index. + theap[i].setIndex(i + 1); + } #if HEAP_LOG - for (i = 0; i < MAX_HEAPS + 1; i++) { - char fname[255]; - sprintf (fname, "log%d", i); - unlink (fname); - _log[i].open (fname); - } + for (i = 0; i < MAX_HEAPS + 1; i++) { + char fname[255]; + sprintf(fname, "log%d", i); + unlink(fname); + _log[i].open(fname); + } #endif #if HEAP_FRAG_STATS - hoardLockInit(_statsLock, "hoard stats"); + hoardLockInit(_statsLock, "hoard stats"); #endif - hoardLockInit(_bufferLock, "hoard buffer"); + hoardLockInit(_bufferLock, "hoard buffer"); } // Print out statistics information. -void processHeap::stats (void) { +void +processHeap::stats(void) +{ #if HEAP_STATS - int umax = 0; - int amax = 0; - for (int j = 0; j < MAX_HEAPS; j++) { - for (int i = 0; i < SIZE_CLASSES; i++) { - amax += theap[j].maxAllocated(i) * sizeFromClass (i); - umax += theap[j].maxInUse(i) * sizeFromClass (i); - } - } - printf ("Amax <= %d, Umax <= %d\n", amax, umax); -#if HEAP_FRAG_STATS - amax = getMaxAllocated(); - umax = getMaxRequested(); - printf ("Maximum allocated = %d\nMaximum in use = %d\nIn use at max allocated = %d\n", amax, umax, getInUseAtMaxAllocated()); - printf ("Still in use = %d\n", _currentRequested); - printf ("Fragmentation (3) = %f\n", (float) amax / (float) getInUseAtMaxAllocated()); - printf ("Fragmentation (4) = %f\n", (float) amax / (float) umax); -#endif + int umax = 0; + int amax = 0; + for (int j = 0; j < MAX_HEAPS; j++) { + for (int i = 0; i < SIZE_CLASSES; i++) { + amax += theap[j].maxAllocated(i) * sizeFromClass(i); + umax += theap[j].maxInUse(i) * sizeFromClass(i); + } + } + printf("Amax <= %d, Umax <= %d\n", amax, umax); +#if HEAP_FRAG_STATS + amax = getMaxAllocated(); + umax = getMaxRequested(); + printf + ("Maximum allocated = %d\nMaximum in use = %d\nIn use at max allocated = %d\n", + amax, umax, getInUseAtMaxAllocated()); + printf("Still in use = %d\n", _currentRequested); + printf("Fragmentation (3) = %f\n", + (float)amax / (float)getInUseAtMaxAllocated()); + printf("Fragmentation (4) = %f\n", (float)amax / (float)umax); +#endif #endif // HEAP_STATS + #if HEAP_LOG - printf ("closing logs.\n"); - fflush (stdout); - for (int i = 0; i < MAX_HEAPS + 1; i++) { - _log[i].close(); - } + printf("closing logs.\n"); + fflush(stdout); + for (int i = 0; i < MAX_HEAPS + 1; i++) { + _log[i].close(); + } #endif } - #if HEAP_FRAG_STATS -void processHeap::setAllocated (int requestedSize, - int actualSize) +void +processHeap::setAllocated(int requestedSize, int actualSize) { - hoardLock (_statsLock); - _currentRequested += requestedSize; - _currentAllocated += actualSize; - if (_currentRequested > _maxRequested) { - _maxRequested = _currentRequested; - } - if (_currentAllocated > _maxAllocated) { - _maxAllocated = _currentAllocated; - _inUseAtMaxAllocated = _currentRequested; - } - hoardUnlock (_statsLock); + hoardLock(_statsLock); + _currentRequested += requestedSize; + _currentAllocated += actualSize; + if (_currentRequested > _maxRequested) { + _maxRequested = _currentRequested; + } + if (_currentAllocated > _maxAllocated) { + _maxAllocated = _currentAllocated; + _inUseAtMaxAllocated = _currentRequested; + } + hoardUnlock(_statsLock); } -void processHeap::setDeallocated (int requestedSize, - int actualSize) +void +processHeap::setDeallocated(int requestedSize, int actualSize) { - hoardLock (_statsLock); - _currentRequested -= requestedSize; - _currentAllocated -= actualSize; - hoardUnlock (_statsLock); + hoardLock(_statsLock); + _currentRequested -= requestedSize; + _currentAllocated -= actualSize; + hoardUnlock(_statsLock); } -#endif +#endif // HEAP_FRAG_STATS // free (ptr, pheap): @@ -136,74 +140,72 @@ void processHeap::setDeallocated (int requestedSize, // updates the thread heap's statistics; // may release the superblock to the process heap. -void processHeap::free (void * ptr) +void +processHeap::free(void *ptr) { + // Return if ptr is 0. + // This is the behavior prescribed by the standard. + if (ptr == 0) + return; - // Return if ptr is 0. - // This is the behavior prescribed by the standard. - if (ptr == 0) { - return; - } + // Find the block and superblock corresponding to this ptr. - // Find the block and superblock corresponding to this ptr. + block *b = (block *) ptr - 1; + assert(b->isValid()); - block * b = (block *) ptr - 1; - assert (b->isValid()); + // Check to see if this block came from a memalign() call. + if (((unsigned long)b->getNext() & 1) == 1) { + // It did. Set the block to the actual block header. + b = (block *) ((unsigned long)b->getNext() & ~1); + assert(b->isValid()); + } - // Check to see if this block came from a memalign() call. - if (((unsigned long) b->getNext() & 1) == 1) { - // It did. Set the block to the actual block header. - b = (block *) ((unsigned long) b->getNext() & ~1); - assert (b->isValid()); - } + b->markFree(); - b->markFree(); + superblock *sb = b->getSuperblock(); + assert(sb); + assert(sb->isValid()); - superblock * sb = b->getSuperblock(); - assert (sb); - assert (sb->isValid()); + const int sizeclass = sb->getBlockSizeClass(); - const int sizeclass = sb->getBlockSizeClass(); + // + // Return the block to the superblock, + // find the heap that owns this superblock + // and update its statistics. + // - // - // Return the block to the superblock, - // find the heap that owns this superblock - // and update its statistics. - // + hoardHeap *owner; - hoardHeap * owner; - - // By acquiring the up lock on the superblock, - // we prevent it from moving to the global heap. - // This eventually pins it down in one heap, - // so this loop is guaranteed to terminate. - // (It should generally take no more than two iterations.) - sb->upLock(); - while (1) { - owner = sb->getOwner(); - owner->lock(); - if (owner == sb->getOwner()) { - break; - } else { - owner->unlock(); - } - // Suspend to allow ownership to quiesce. - hoardYield(); - } + // By acquiring the up lock on the superblock, + // we prevent it from moving to the global heap. + // This eventually pins it down in one heap, + // so this loop is guaranteed to terminate. + // (It should generally take no more than two iterations.) + sb->upLock(); + while (1) { + owner = sb->getOwner(); + owner->lock(); + if (owner == sb->getOwner()) { + break; + } else { + owner->unlock(); + } + // Suspend to allow ownership to quiesce. + hoardYield(); + } #if HEAP_LOG - MemoryRequest m; - m.free (ptr); - getLog (owner->getIndex()).append(m); + MemoryRequest m; + m.free(ptr); + getLog(owner->getIndex()).append(m); #endif #if HEAP_FRAG_STATS - setDeallocated (b->getRequestedSize(), 0); + setDeallocated(b->getRequestedSize(), 0); #endif - int sbUnmapped = owner->freeBlock (b, sb, sizeclass, this); + int sbUnmapped = owner->freeBlock(b, sb, sizeclass, this); - owner->unlock(); - if (!sbUnmapped) { - sb->upUnlock(); - } + owner->unlock(); + if (!sbUnmapped) + sb->upUnlock(); } diff --git a/src/kernel/libroot/posix/malloc/processheap.h b/src/kernel/libroot/posix/malloc/processheap.h index 04beb840af..340ab1774c 100644 --- a/src/kernel/libroot/posix/malloc/processheap.h +++ b/src/kernel/libroot/posix/malloc/processheap.h @@ -30,149 +30,155 @@ #include "arch-specific.h" #include "heap.h" #if USE_PRIVATE_HEAPS -#include "privateheap.h" -#define HEAPTYPE privateHeap +# include "privateheap.h" +# define HEAPTYPE privateHeap #else -#define HEAPTYPE threadHeap -#include "threadheap.h" +# define HEAPTYPE threadHeap +# include "threadheap.h" #endif #if HEAP_LOG -#include "memstat.h" -#include "log.h" +# include "memstat.h" +# include "log.h" #endif + +namespace BPrivate { + class processHeap : public hoardHeap { + public: + // Always grab at least this many superblocks' worth of memory which + // we parcel out. + enum { REFILL_NUMBER_OF_SUPERBLOCKS = 16 }; -public: - - // Always grab at least this many superblocks' worth of memory which - // we parcel out. - enum { REFILL_NUMBER_OF_SUPERBLOCKS = 16 }; - - processHeap (void); - - ~processHeap (void) { + processHeap(void); + ~processHeap(void) + { #if HEAP_STATS - stats(); + stats(); #endif - } + } + // Memory deallocation routines. + void free(void *ptr); - // Memory deallocation routines. - void free (void * ptr); + // Print out statistics information. + void stats(void); - // Print out statistics information. - void stats (void); + // Get a thread heap index. + inline int getHeapIndex(void); - // Get a thread heap index. - inline int getHeapIndex (void); + // Get the thread heap with index i. + inline HEAPTYPE & getHeap(int i); - // Get the thread heap with index i. - inline HEAPTYPE& getHeap (int i); + // Extract a superblock. + inline superblock *acquire(const int c, hoardHeap * dest); - // Extract a superblock. - inline superblock * acquire (const int c, - hoardHeap * dest); + // Get space for a superblock. + inline char *getSuperblockBuffer(void); - // Get space for a superblock. - inline char * getSuperblockBuffer (void); - - // Insert a superblock. - inline void release (superblock * sb); + // Insert a superblock. + inline void release(superblock * sb); #if HEAP_LOG - // Get the log for index i. - inline Log& getLog (int i); + // Get the log for index i. + inline Log < MemoryRequest > &getLog(int i); #endif #if HEAP_FRAG_STATS - // Declare that we have allocated an object. - void setAllocated (int requestedSize, - int actualSize); + // Declare that we have allocated an object. + void setAllocated(int requestedSize, int actualSize); - // Declare that we have deallocated an object. - void setDeallocated (int requestedSize, - int actualSize); + // Declare that we have deallocated an object. + void setDeallocated(int requestedSize, int actualSize); - // Return the number of wasted bytes at the high-water mark - // (maxAllocated - maxRequested) - inline int getFragmentation (void); + // Return the number of wasted bytes at the high-water mark + // (maxAllocated - maxRequested) + inline int getFragmentation(void); - int getMaxAllocated (void) { - return _maxAllocated; - } + int + getMaxAllocated(void) + { + return _maxAllocated; + } - int getInUseAtMaxAllocated (void) { - return _inUseAtMaxAllocated; - } - - int getMaxRequested (void) { - return _maxRequested; - } + int + getInUseAtMaxAllocated(void) + { + return _inUseAtMaxAllocated; + } + int + getMaxRequested(void) + { + return _maxRequested; + } #endif -private: + private: + // Hide the lock & unlock methods. + void + lock(void) + { + hoardHeap::lock(); + } - // Hide the lock & unlock methods. + void + unlock(void) + { + hoardHeap::unlock(); + } - void lock (void) { - hoardHeap::lock(); - } + // Prevent copying and assignment. + processHeap(const processHeap &); + const processHeap & operator=(const processHeap &); - void unlock (void) { - hoardHeap::unlock(); - } - - // Prevent copying and assignment. - processHeap (const processHeap&); - const processHeap& operator= (const processHeap&); - - // The per-thread heaps. - HEAPTYPE theap[MAX_HEAPS]; + // The per-thread heaps. + HEAPTYPE theap[MAX_HEAPS]; #if HEAP_FRAG_STATS - // Statistics required to compute fragmentation. We cannot - // unintrusively keep track of these on a multiprocessor, because - // this would become a bottleneck. + // Statistics required to compute fragmentation. We cannot + // unintrusively keep track of these on a multiprocessor, because + // this would become a bottleneck. - int _currentAllocated; - int _currentRequested; - int _maxAllocated; - int _maxRequested; - int _inUseAtMaxAllocated; - int _fragmentation; + int _currentAllocated; + int _currentRequested; + int _maxAllocated; + int _maxRequested; + int _inUseAtMaxAllocated; + int _fragmentation; - // A lock to protect these statistics. - hoardLockType _statsLock; + // A lock to protect these statistics. + hoardLockType _statsLock; #endif #if HEAP_LOG - Log _log[MAX_HEAPS + 1]; + Log < MemoryRequest > _log[MAX_HEAPS + 1]; #endif - // A lock for the superblock buffer. - hoardLockType _bufferLock; + // A lock for the superblock buffer. + hoardLockType _bufferLock; - char * _buffer; - int _bufferCount; + char *_buffer; + int _bufferCount; }; -HEAPTYPE& processHeap::getHeap (int i) +HEAPTYPE & +processHeap::getHeap(int i) { - assert (i >= 0); - assert (i < MAX_HEAPS); - return theap[i]; + assert(i >= 0); + assert(i < MAX_HEAPS); + return theap[i]; } #if HEAP_LOG -Log& processHeap::getLog (int i) +Log & +processHeap::getLog(int i) { - assert (i >= 0); - assert (i < MAX_HEAPS + 1); - return _log[i]; + assert(i >= 0); + assert(i < MAX_HEAPS + 1); + return _log[i]; } #endif @@ -180,77 +186,86 @@ Log& processHeap::getLog (int i) #ifdef NEED_LG // Return ceil(log_2(num)). // num must be positive. -static int lg (int num) +static int +lg(int num) { - assert (num > 0); - int power = 0; - int n = 1; - // Invariant: 2^power == n. - while (n < num) { - n <<= 1; - power++; - } - return power; + assert(num > 0); + int power = 0; + int n = 1; + // Invariant: 2^power == n. + while (n < num) { + n <<= 1; + power++; + } + return power; } #endif /* NEED_LG */ // Hash out the thread id to a heap and return an index to that heap. -int processHeap::getHeapIndex (void) { - // Here we use the number of processors as the maximum number of heaps. - // In fact, for efficiency, we just round up to the highest power of two, - // times two. - int tid = hoardGetThreadID() & _numProcessorsMask; - assert (tid < MAX_HEAPS); - return tid; + +int +processHeap::getHeapIndex(void) +{ + // Here we use the number of processors as the maximum number of heaps. + // In fact, for efficiency, we just round up to the highest power of two, + // times two. + int tid = hoardGetThreadID() & _numProcessorsMask; + assert(tid < MAX_HEAPS); + return tid; } -superblock * processHeap::acquire (const int sizeclass, - hoardHeap * dest) +superblock * +processHeap::acquire(const int sizeclass, hoardHeap * dest) { - lock (); + lock(); - // Remove the superblock with the most free space. - superblock * maxSb = removeMaxSuperblock (sizeclass); - if (maxSb) { - maxSb->setOwner (dest); - } + // Remove the superblock with the most free space. + superblock *maxSb = removeMaxSuperblock(sizeclass); + if (maxSb) + maxSb->setOwner(dest); - unlock (); + unlock(); - return maxSb; + return maxSb; } -inline char * processHeap::getSuperblockBuffer (void) +inline char * +processHeap::getSuperblockBuffer(void) { - char * buf; - hoardLock (_bufferLock); - if (_bufferCount == 0) { - _buffer = (char *) hoardSbrk (SUPERBLOCK_SIZE * REFILL_NUMBER_OF_SUPERBLOCKS); - _bufferCount = REFILL_NUMBER_OF_SUPERBLOCKS; - } - buf = _buffer; - _buffer += SUPERBLOCK_SIZE; - _bufferCount--; - hoardUnlock (_bufferLock); - return buf; + char *buf; + hoardLock(_bufferLock); + if (_bufferCount == 0) { + _buffer = (char *)hoardSbrk(SUPERBLOCK_SIZE + * REFILL_NUMBER_OF_SUPERBLOCKS); + _bufferCount = REFILL_NUMBER_OF_SUPERBLOCKS; + } + + buf = _buffer; + _buffer += SUPERBLOCK_SIZE; + _bufferCount--; + hoardUnlock(_bufferLock); + + return buf; } // Put a superblock back into our list of superblocks. -void processHeap::release (superblock * sb) + +void +processHeap::release(superblock *sb) { - assert (EMPTY_FRACTION * sb->getNumAvailable() > sb->getNumBlocks()); + assert(EMPTY_FRACTION * sb->getNumAvailable() > sb->getNumBlocks()); - lock(); + lock(); - // Insert the superblock. - insertSuperblock (sb->getBlockSizeClass(), sb, this); + // Insert the superblock. + insertSuperblock(sb->getBlockSizeClass(), sb, this); - unlock(); + unlock(); } +} // namespace BPrivate #endif // _PROCESSHEAP_H_ - diff --git a/src/kernel/libroot/posix/malloc/superblock.cpp b/src/kernel/libroot/posix/malloc/superblock.cpp index 7af9db805c..6f1e3f5d46 100644 --- a/src/kernel/libroot/posix/malloc/superblock.cpp +++ b/src/kernel/libroot/posix/malloc/superblock.cpp @@ -22,7 +22,7 @@ The superblock class controls a number of blocks (which are allocatable units of memory). ------------------------------------------------------------------------ - @(#) $Id: superblock.cpp,v 1.2 2005/02/10 18:47:16 axeld Exp $ + @(#) $Id$ ------------------------------------------------------------------------ Emery Berger | Department of Computer Sciences | @@ -39,94 +39,94 @@ #include "processheap.h" #include "superblock.h" +using namespace BPrivate; -superblock::superblock (int numBlocks, // The number of blocks in the sb. - int szclass, // The size class of the blocks. - hoardHeap * o) // The heap that "owns" this sb. - : + +superblock::superblock(int numBlocks, // The number of blocks in the sb. + int szclass, // The size class of the blocks. + hoardHeap * o) // The heap that "owns" this sb. + : #if HEAP_DEBUG - _magic (SUPERBLOCK_MAGIC), + _magic(SUPERBLOCK_MAGIC), #endif - _sizeClass (szclass), - _numBlocks (numBlocks), - _numAvailable (0), - _fullness (0), - _freeList (NULL), - _owner (o), - _next (NULL), - _prev (NULL) + _sizeClass(szclass), + _numBlocks(numBlocks), + _numAvailable(0), + _fullness(0), _freeList(NULL), _owner(o), _next(NULL), _prev(NULL) { - assert (_numBlocks >= 1); + assert(_numBlocks >= 1); - // Determine the size of each block. - const int blksize = - hoardHeap::align (sizeof(block) + hoardHeap::sizeFromClass(_sizeClass)); + // Determine the size of each block. + const int blksize = hoardHeap::align(sizeof(block) + + hoardHeap::sizeFromClass(_sizeClass)); - // Make sure this size is in fact aligned. - assert ((blksize & hoardHeap::ALIGNMENT_MASK) == 0); + // Make sure this size is in fact aligned. + assert((blksize & hoardHeap::ALIGNMENT_MASK) == 0); - // Set the first block to just past this superblock header. - block * b - = (block *) hoardHeap::align ((unsigned long) (this + 1)); + // Set the first block to just past this superblock header. + block *b = (block *) hoardHeap::align((unsigned long)(this + 1)); - // Initialize all the blocks, - // and insert the block pointers into the linked list. - for (int i = 0; i < _numBlocks; i++) { - // Make sure the block is on a double-word boundary. - assert (((unsigned int) b & hoardHeap::ALIGNMENT_MASK) == 0); - new (b) block (this); - assert (b->getSuperblock() == this); - b->setNext (_freeList); - _freeList = b; - b = (block *) ((char *) b + blksize); - } - _numAvailable = _numBlocks; - computeFullness(); - assert ((unsigned long) b <= hoardHeap::align (sizeof(superblock) + blksize * _numBlocks) + (unsigned long) this); + // Initialize all the blocks, + // and insert the block pointers into the linked list. + for (int i = 0; i < _numBlocks; i++) { + // Make sure the block is on a double-word boundary. + assert(((unsigned int)b & hoardHeap::ALIGNMENT_MASK) == 0); + new(b) block(this); + assert(b->getSuperblock() == this); + b->setNext(_freeList); + _freeList = b; + b = (block *)((char *)b + blksize); + } - hoardLockInit(_upLock, "hoard superblock"); + _numAvailable = _numBlocks; + computeFullness(); + assert((unsigned long)b <= hoardHeap::align(sizeof(superblock) + blksize * _numBlocks) + + (unsigned long)this); + + hoardLockInit(_upLock, "hoard superblock"); } -superblock * superblock::makeSuperblock (int sizeclass, - processHeap * pHeap) + +superblock * +superblock::makeSuperblock(int sizeclass, processHeap * pHeap) { - // We need to get more memory. + // We need to get more memory. - char * buf; - int numBlocks = hoardHeap::numBlocks(sizeclass); + char *buf; + int numBlocks = hoardHeap::numBlocks(sizeclass); - // Compute how much memory we need. - unsigned long moreMemory; - if (numBlocks > 1) { - moreMemory = hoardHeap::SUPERBLOCK_SIZE; - assert (moreMemory >= hoardHeap::align(sizeof(superblock) + (hoardHeap::align (sizeof(block) + hoardHeap::sizeFromClass(sizeclass))) * numBlocks)); + // Compute how much memory we need. + unsigned long moreMemory; + if (numBlocks > 1) { + moreMemory = hoardHeap::SUPERBLOCK_SIZE; + assert(moreMemory >= hoardHeap::align(sizeof(superblock) + + (hoardHeap::align(sizeof(block) + + hoardHeap::sizeFromClass(sizeclass))) * numBlocks)); - // Get some memory from the process heap. - buf = (char *) pHeap->getSuperblockBuffer(); + // Get some memory from the process heap. + buf = (char *)pHeap->getSuperblockBuffer(); + } else { + // One object. + assert(numBlocks == 1); - } else { - // One object. - assert (numBlocks == 1); + size_t blksize = hoardHeap::align(sizeof(block) + + hoardHeap::sizeFromClass(sizeclass)); + moreMemory = hoardHeap::align(sizeof(superblock) + blksize); - size_t blksize = hoardHeap::align (sizeof(block) + hoardHeap::sizeFromClass(sizeclass)); - moreMemory = hoardHeap::align (sizeof(superblock) + blksize); + // Get space from the system. + buf = (char *)hoardSbrk(moreMemory); + } - // Get space from the system. - buf = (char *) hoardSbrk (moreMemory); - } + // Make sure that we actually got the memory. + if (buf == NULL) + return 0; - // Make sure that we actually got the memory. - if (buf == NULL) { - return 0; - } - buf = (char *) hoardHeap::align ((unsigned long) buf); + buf = (char *)hoardHeap::align((unsigned long)buf); - // Make sure this buffer is double-word aligned. - assert (buf == (char *) hoardHeap::align ((unsigned long) buf)); - assert ((((unsigned long) buf) & hoardHeap::ALIGNMENT_MASK) == 0); + // Make sure this buffer is double-word aligned. + assert(buf == (char *)hoardHeap::align((unsigned long)buf)); + assert((((unsigned long)buf) & hoardHeap::ALIGNMENT_MASK) == 0); - // Instantiate the new superblock in the buffer. - superblock * sb = new (buf) superblock (numBlocks, sizeclass, NULL); - - return sb; + // Instantiate the new superblock in the buffer. + return new(buf) superblock(numBlocks, sizeclass, NULL); } diff --git a/src/kernel/libroot/posix/malloc/superblock.h b/src/kernel/libroot/posix/malloc/superblock.h index e9a917ebfb..1e1ffad0ec 100644 --- a/src/kernel/libroot/posix/malloc/superblock.h +++ b/src/kernel/libroot/posix/malloc/superblock.h @@ -23,7 +23,7 @@ The superblock class controls a number of blocks (which are allocatable units of memory). ------------------------------------------------------------------------ - @(#) $Id: superblock.h,v 1.1 2002/10/05 17:13:30 axeld Exp $ + @(#) $Id$ ------------------------------------------------------------------------ Emery Berger | Department of Computer Sciences | @@ -44,244 +44,262 @@ #include "arch-specific.h" #include "block.h" -class hoardHeap; // forward declaration -class processHeap; // forward declaration + +namespace BPrivate { + +class hoardHeap; // forward declaration +class processHeap; // forward declaration class superblock { + public: + // Construct a superblock for a given size class and set the heap + // owner. + superblock(int numblocks, int sizeclass, hoardHeap *owner); + ~superblock(void) {} -public: + // Make (allocate or re-use) a superblock for a given size class. + static superblock *makeSuperblock(int sizeclass, processHeap *pHeap); - // Construct a superblock for a given size class and set the heap - // owner. - superblock (int numblocks, - int sizeclass, - hoardHeap * owner); + // Find out who allocated this superblock. + inline hoardHeap *getOwner(void); - ~superblock (void) - {} + // Set the superblock's owner. + inline void setOwner(hoardHeap *o); - // Make (allocate or re-use) a superblock for a given size class. - static superblock * makeSuperblock (int sizeclass, processHeap * pHeap); + // Get a block from the superblock. + inline block *getBlock(void); - // Find out who allocated this superblock. - inline hoardHeap * getOwner (void); + // Put a block back in the superblock. + inline void putBlock(block *b); - // Set the superblock's owner. - inline void setOwner (hoardHeap * o); + // How many blocks are available? + inline int getNumAvailable(void); - // Get a block from the superblock. - inline block * getBlock (void); + // How many blocks are there, in total? + inline int getNumBlocks(void); - // Put a block back in the superblock. - inline void putBlock (block * b); + // What size class are blocks in this superblock? + inline int getBlockSizeClass(void); - // How many blocks are available? - inline int getNumAvailable (void); + // Insert this superblock before the next one. + inline void insertBefore(superblock *nextSb); - // How many blocks are there, in total? - inline int getNumBlocks (void); + // Return the next pointer (to the next superblock in the list). + inline superblock *const getNext(void); - // What size class are blocks in this superblock? - inline int getBlockSizeClass (void); + // Return the prev pointer (to the previous superblock in the list). + inline superblock *const getPrev(void); - // Insert this superblock before the next one. - inline void insertBefore (superblock * nextSb); + // Compute the 'fullness' of this superblock. + inline void computeFullness(void); - // Return the next pointer (to the next superblock in the list). - inline superblock * const getNext (void); - - // Return the prev pointer (to the previous superblock in the list). - inline superblock * const getPrev (void); - - // Compute the 'fullness' of this superblock. - inline void computeFullness (void); - - // Return the 'fullness' of this superblock. - inline int getFullness (void); + // Return the 'fullness' of this superblock. + inline int getFullness(void); #if HEAP_FRAG_STATS - // Return the amount of waste in every allocated block. - int getMaxInternalFragmentation (void); + // Return the amount of waste in every allocated block. + int getMaxInternalFragmentation(void); #endif - // Remove this superblock from its linked list. - inline void remove (void); + // Remove this superblock from its linked list. + inline void remove(void); - // Is this superblock valid? (i.e., - // does it have the right magic number?) - inline int isValid (void); + // Is this superblock valid? (i.e., + // does it have the right magic number?) + inline int isValid(void); - void upLock (void) { - hoardLock (_upLock); - } + void + upLock(void) + { + hoardLock(_upLock); + } - void upUnlock (void) { - hoardUnlock (_upLock); - } + void + upUnlock(void) + { + hoardUnlock(_upLock); + } -private: + private: + // Disable copying and assignment. - // Disable copying and assignment. + superblock(const superblock &); + const superblock & operator=(const superblock &); - superblock (const superblock&); - const superblock& operator= (const superblock&); - - // Used for sanity checking. - enum { SUPERBLOCK_MAGIC = 0xCAFEBABE }; + // Used for sanity checking. + enum { SUPERBLOCK_MAGIC = 0xCAFEBABE }; #if HEAP_DEBUG - unsigned long _magic; + unsigned long _magic; #endif - const int _sizeClass; // The size class of blocks in the superblock. - const int _numBlocks; // The number of blocks in the superblock. - int _numAvailable; // The number of blocks available. - int _fullness; // How full is this superblock? - // (which SUPERBLOCK_FULLNESS group is it in) - block * _freeList; // A pointer to the first free block. - hoardHeap * _owner; // The heap who owns this superblock. - superblock * _next; // The next superblock in the list. - superblock * _prev; // The previous superblock in the list. + const int _sizeClass; // The size class of blocks in the superblock. + const int _numBlocks; // The number of blocks in the superblock. + int _numAvailable; // The number of blocks available. + int _fullness; // How full is this superblock? + // (which SUPERBLOCK_FULLNESS group is it in) + block *_freeList; // A pointer to the first free block. + hoardHeap *_owner; // The heap who owns this superblock. + superblock *_next; // The next superblock in the list. + superblock *_prev; // The previous superblock in the list. - hoardLockType _upLock; // Lock this when moving a superblock to the global (process) heap. + hoardLockType _upLock; // Lock this when moving a superblock to the global (process) heap. - // We insert a cache pad here to prevent false sharing with the - // first block (which immediately follows the superblock). - - double _pad[CACHE_LINE / sizeof(double)]; + // We insert a cache pad here to prevent false sharing with the + // first block (which immediately follows the superblock). + double _pad[CACHE_LINE / sizeof(double)]; }; -hoardHeap * superblock::getOwner (void) +hoardHeap * +superblock::getOwner(void) { - assert (isValid()); - hoardHeap * o = _owner; - return o; + assert(isValid()); + hoardHeap *o = _owner; + return o; } -void superblock::setOwner (hoardHeap * o) +void +superblock::setOwner(hoardHeap *o) { - assert (isValid()); - _owner = o; + assert(isValid()); + _owner = o; } -block * superblock::getBlock (void) +block * +superblock::getBlock(void) { - assert (isValid()); - // Pop off a block from this superblock's freelist, - // if there is one available. - if (_freeList == NULL) { - // The freelist is empty. - assert (getNumAvailable() == 0); - return NULL; - } - assert (getNumAvailable() > 0); - block * b = _freeList; - _freeList = _freeList->getNext(); - _numAvailable--; + assert(isValid()); + // Pop off a block from this superblock's freelist, + // if there is one available. + if (_freeList == NULL) { + // The freelist is empty. + assert(getNumAvailable() == 0); + return NULL; + } - b->setNext(NULL); + assert(getNumAvailable() > 0); + block *b = _freeList; + _freeList = _freeList->getNext(); + _numAvailable--; - computeFullness(); + b->setNext(NULL); - return b; + computeFullness(); + return b; } -void superblock::putBlock (block * b) +void +superblock::putBlock(block *b) { - assert (isValid()); - // Push a block onto the superblock's freelist. - assert (b->isValid()); - assert (b->getSuperblock() == this); - assert (getNumAvailable() < getNumBlocks()); - b->setNext (_freeList); - _freeList = b; - _numAvailable++; - computeFullness(); + assert(isValid()); + // Push a block onto the superblock's freelist. + assert(b->isValid()); + assert(b->getSuperblock() == this); + assert(getNumAvailable() < getNumBlocks()); + b->setNext(_freeList); + _freeList = b; + _numAvailable++; + computeFullness(); } -int superblock::getNumAvailable (void) + +int +superblock::getNumAvailable(void) { - assert (isValid()); - return _numAvailable; + assert(isValid()); + return _numAvailable; } -int superblock::getNumBlocks (void) +int +superblock::getNumBlocks(void) { - assert (isValid()); - return _numBlocks; + assert(isValid()); + return _numBlocks; } -int superblock::getBlockSizeClass (void) +int +superblock::getBlockSizeClass(void) { - assert (isValid()); - return _sizeClass; + assert(isValid()); + return _sizeClass; } -superblock * const superblock::getNext (void) +superblock * const +superblock::getNext(void) { - assert (isValid()); - return _next; + assert(isValid()); + return _next; } -superblock * const superblock::getPrev (void) +superblock * const +superblock::getPrev(void) { - assert (isValid()); - return _prev; + assert(isValid()); + return _prev; } -void superblock::insertBefore (superblock * nextSb) { - assert (isValid()); - // Insert this superblock before the next one (nextSb). - assert (nextSb != this); - _next = nextSb; - if (nextSb) { - _prev = nextSb->_prev; - nextSb->_prev = this; - } -} - - -void superblock::remove (void) { - // Remove this superblock from a doubly-linked list. - if (_next) { - _next->_prev = _prev; - } - if (_prev) { - _prev->_next = _next; - } - _prev = NULL; - _next = NULL; -} - - -int superblock::isValid (void) +void +superblock::insertBefore(superblock * nextSb) { - assert (_numBlocks > 0); - assert (_numAvailable <= _numBlocks); - assert (_sizeClass >= 0); - return 1; + assert(isValid()); + // Insert this superblock before the next one (nextSb). + assert(nextSb != this); + _next = nextSb; + if (nextSb) { + _prev = nextSb->_prev; + nextSb->_prev = this; + } } -void superblock::computeFullness (void) +void +superblock::remove(void) { - assert (isValid()); - _fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1) + // Remove this superblock from a doubly-linked list. + if (_next) + _next->_prev = _prev; + if (_prev) + _prev->_next = _next; + + _prev = NULL; + _next = NULL; +} + + +int +superblock::isValid(void) +{ + assert(_numBlocks > 0); + assert(_numAvailable <= _numBlocks); + assert(_sizeClass >= 0); + return 1; +} + + +void +superblock::computeFullness(void) +{ + assert(isValid()); + _fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1) * (getNumBlocks() - getNumAvailable())) / getNumBlocks()); } -int superblock::getFullness (void) + +int +superblock::getFullness(void) { - assert (isValid()); - return _fullness; + assert(isValid()); + return _fullness; } +} // namespace BPrivate + #endif // _SUPERBLOCK_H_ diff --git a/src/kernel/libroot/posix/malloc/threadheap.cpp b/src/kernel/libroot/posix/malloc/threadheap.cpp index 40675dcaa3..3e1bb901de 100644 --- a/src/kernel/libroot/posix/malloc/threadheap.cpp +++ b/src/kernel/libroot/posix/malloc/threadheap.cpp @@ -26,10 +26,13 @@ #include "threadheap.h" #include "processheap.h" +using namespace BPrivate; -threadHeap::threadHeap (void) - : _pHeap (0) -{} + +threadHeap::threadHeap(void) + :_pHeap(0) +{ +} // malloc (sz): @@ -38,73 +41,74 @@ threadHeap::threadHeap (void) // side effects: allocates a block from a superblock; // may call sbrk() (via makeSuperblock). -void * threadHeap::malloc (const size_t size) +void * +threadHeap::malloc(const size_t size) { - const int sizeclass = sizeClass (size); - block * b = NULL; + const int sizeclass = sizeClass(size); + block *b = NULL; - lock(); + lock(); - // Look for a free block. - // We usually have memory locally so we first look for space in the - // superblock list. + // Look for a free block. + // We usually have memory locally so we first look for space in the + // superblock list. - superblock * sb = findAvailableSuperblock (sizeclass, b, _pHeap); + superblock *sb = findAvailableSuperblock(sizeclass, b, _pHeap); - if (sb == NULL) { + if (sb == NULL) { + // We don't have memory locally. + // Try to get more from the process heap. - // We don't have memory locally. - // Try to get more from the process heap. + assert(_pHeap); + sb = _pHeap->acquire((int)sizeclass, this); - assert (_pHeap); - sb = _pHeap->acquire ((int) sizeclass, this); - - // If we didn't get any memory from the process heap, - // we'll have to allocate our own superblock. - if (sb == NULL) { - sb = superblock::makeSuperblock (sizeclass, _pHeap); - if (sb == NULL) { - // We're out of memory! - unlock (); - return NULL; - } + // If we didn't get any memory from the process heap, + // we'll have to allocate our own superblock. + if (sb == NULL) { + sb = superblock::makeSuperblock(sizeclass, _pHeap); + if (sb == NULL) { + // We're out of memory! + unlock(); + return NULL; + } #if HEAP_LOG - // Record the memory allocation. - MemoryRequest m; - m.allocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); - _pHeap->getLog(getIndex()).append(m); + // Record the memory allocation. + MemoryRequest m; + m.allocate((int)sb->getNumBlocks() * + (int)sizeFromClass(sb->getBlockSizeClass())); + _pHeap->getLog(getIndex()).append(m); #endif #if HEAP_FRAG_STATS - _pHeap->setAllocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); + _pHeap->setAllocated(0, + sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); #endif - } + } + // Get a block from the superblock. + b = sb->getBlock(); + assert(b != NULL); - // Get a block from the superblock. - b = sb->getBlock (); - assert (b != NULL); + // Insert the superblock into our list. + insertSuperblock(sizeclass, sb, _pHeap); + } - // Insert the superblock into our list. - insertSuperblock (sizeclass, sb, _pHeap); - } + assert(b != NULL); + assert(b->isValid()); + assert(sb->isValid()); - assert (b != NULL); - assert (b->isValid()); - assert (sb->isValid()); - - b->markAllocated(); + b->markAllocated(); #if HEAP_LOG - MemoryRequest m; - m.malloc ((void *) (b + 1), align(size)); - _pHeap->getLog(getIndex()).append(m); + MemoryRequest m; + m.malloc((void *)(b + 1), align(size)); + _pHeap->getLog(getIndex()).append(m); #endif #if HEAP_FRAG_STATS - b->setRequestedSize (align(size)); - _pHeap->setAllocated (align(size), 0); + b->setRequestedSize(align(size)); + _pHeap->setAllocated(align(size), 0); #endif - unlock(); + unlock(); - // Skip past the block header and return the pointer. - return (void *) (b + 1); + // Skip past the block header and return the pointer. + return (void *)(b + 1); } diff --git a/src/kernel/libroot/posix/malloc/threadheap.h b/src/kernel/libroot/posix/malloc/threadheap.h index 2f113b272b..9c4083f1ed 100644 --- a/src/kernel/libroot/posix/malloc/threadheap.h +++ b/src/kernel/libroot/posix/malloc/threadheap.h @@ -26,143 +26,138 @@ #include "heap.h" -class processHeap; // forward declaration +namespace BPrivate { + +class processHeap; // forward declaration // // We use one threadHeap for each thread (processor). // class threadHeap : public hoardHeap { + public: + threadHeap(void); -public: + // Memory allocation routines. + void *malloc(const size_t sz); + inline void *memalign(size_t alignment, size_t sz); - threadHeap (void); + // Find out how large an allocated object is. + inline static size_t objectSize(void *ptr); - // Memory allocation routines. - void * malloc (const size_t sz); - inline void * memalign (size_t alignment, size_t sz); + // Set our process heap. + inline void setpHeap(processHeap *p); - // Find out how large an allocated object is. - inline static size_t objectSize (void * ptr); + private: + // Prevent copying and assignment. + threadHeap(const threadHeap &); + const threadHeap &operator=(const threadHeap &); - // Set our process heap. - inline void setpHeap (processHeap * p); + // Our process heap. + processHeap *_pHeap; -private: - - // Prevent copying and assignment. - threadHeap (const threadHeap&); - const threadHeap& operator= (const threadHeap&); - - // Our process heap. - processHeap * _pHeap; - - // We insert a cache pad here to avoid false sharing (the - // processHeap holds an array of threadHeaps, and we don't want - // these to share any cache lines). - double _pad[CACHE_LINE / sizeof(double)]; + // We insert a cache pad here to avoid false sharing (the + // processHeap holds an array of threadHeaps, and we don't want + // these to share any cache lines). + double _pad[CACHE_LINE / sizeof(double)]; }; -void * threadHeap::memalign (size_t alignment, - size_t size) +void * +threadHeap::memalign(size_t alignment, size_t size) { - // Calculate the amount of space we need - // to satisfy the alignment requirements. + // Calculate the amount of space we need + // to satisfy the alignment requirements. - size_t newSize; + size_t newSize; - // If the alignment is less than the required alignment, - // just call malloc. - if (alignment <= ALIGNMENT) { - return this->malloc (size); - } + // If the alignment is less than the required alignment, + // just call malloc. + if (alignment <= ALIGNMENT) + return this->malloc(size); - if (alignment < sizeof(block)) { - alignment = sizeof(block); - } + if (alignment < sizeof(block)) + alignment = sizeof(block); - // Alignment must be a power of two! - assert ((alignment & (alignment - 1)) == 0); + // Alignment must be a power of two! + assert((alignment & (alignment - 1)) == 0); - // Leave enough room to align the block within the malloced space. - newSize = size + sizeof(block) + alignment; + // Leave enough room to align the block within the malloced space. + newSize = size + sizeof(block) + alignment; - // Now malloc the space up with a little extra (we'll put the block - // pointer in right behind the allocated space). + // Now malloc the space up with a little extra (we'll put the block + // pointer in right behind the allocated space). - void * ptr = this->malloc (newSize); - if ((((unsigned long) ptr) & -((long) alignment)) == 0) { - // ptr is already aligned, so return it. - assert (((unsigned long) ptr % alignment) == 0); - return ptr; + void *ptr = this->malloc(newSize); + if ((((unsigned long) ptr) & -((long) alignment)) == 0) { + // ptr is already aligned, so return it. + assert(((unsigned long) ptr % alignment) == 0); + return ptr; + } else { + // Align ptr. + char *newptr = (char *)(((unsigned long)ptr + alignment - 1) & -((long)alignment)); - } else { + // If there's not enough room for the block header, skip to the + // next aligned space within the block.. + if ((unsigned long)newptr - (unsigned long)ptr < sizeof(block)) + newptr += alignment; - // Align ptr. - char * newptr = (char *) - (((unsigned long) ptr + alignment - 1) & -((long) alignment)); + assert(((unsigned long)newptr % alignment) == 0); - // If there's not enough room for the block header, skip to the - // next aligned space within the block.. - if ((unsigned long) newptr - (unsigned long) ptr < sizeof(block)) { - newptr += alignment; - } - assert (((unsigned long) newptr % alignment) == 0); + // Copy the block from the start of the allocated memory. + block *b = ((block *)ptr - 1); - // Copy the block from the start of the allocated memory. - block * b = ((block *) ptr - 1); + assert(b->isValid()); + assert(b->getSuperblock()->isValid()); - assert (b->isValid()); - assert (b->getSuperblock()->isValid()); + // Make sure there's enough room for the block header. + assert(((unsigned long)newptr - (unsigned long)ptr) >= + sizeof(block)); - // Make sure there's enough room for the block header. - assert (((unsigned long) newptr - (unsigned long) ptr) >= sizeof(block)); + block *p = ((block *)newptr - 1); - block * p = ((block *) newptr - 1); + // Make sure there's enough room allocated for size bytes. + assert(((unsigned long)p - sizeof(block)) >= (unsigned long)b); - // Make sure there's enough room allocated for size bytes. - assert (((unsigned long) p - sizeof(block)) >= (unsigned long) b); + if (p != b) { + assert((unsigned long)newptr > (unsigned long)ptr); + // Copy the block header. + *p = *b; + assert(p->isValid()); + assert(p->getSuperblock()->isValid()); - if (p != b) { - assert ((unsigned long) newptr > (unsigned long) ptr); - // Copy the block header. - *p = *b; - assert (p->isValid()); - assert (p->getSuperblock()->isValid()); + // Set the next pointer to point to b with the 1 bit set. + // When this block is freed, it will be treated specially. + p->setNext((block *)((unsigned long)b | 1)); + } else + assert(ptr != newptr); - // Set the next pointer to point to b with the 1 bit set. - // When this block is freed, it will be treated specially. - p->setNext ((block *) ((unsigned long) b | 1)); - - } else { - assert (ptr != newptr); - } - - assert (((unsigned long) ptr + newSize) >= ((unsigned long) newptr + size)); - return newptr; - } + assert(((unsigned long)ptr + newSize) >= + ((unsigned long)newptr + size)); + return newptr; + } } -size_t threadHeap::objectSize (void * ptr) +size_t +threadHeap::objectSize(void *ptr) { - // Find the superblock pointer. + // Find the superblock pointer. + block *b = ((block *)ptr - 1); + assert(b->isValid()); + superblock *sb = b->getSuperblock(); + assert(sb); - block * b = ((block *) ptr - 1); - assert (b->isValid()); - superblock * sb = b->getSuperblock (); - assert (sb); - - // Return the size. - return sizeFromClass (sb->getBlockSizeClass()); + // Return the size. + return sizeFromClass(sb->getBlockSizeClass()); } -void threadHeap::setpHeap (processHeap * p) +void threadHeap::setpHeap(processHeap *p) { - _pHeap = p; + _pHeap = p; } -#endif // _THREADHEAP_H_ +} // namespace BPrivate +#endif // _THREADHEAP_H_ diff --git a/src/kernel/libroot/posix/malloc/wrapper.cpp b/src/kernel/libroot/posix/malloc/wrapper.cpp index e9d52c9d71..54f01660ca 100644 --- a/src/kernel/libroot/posix/malloc/wrapper.cpp +++ b/src/kernel/libroot/posix/malloc/wrapper.cpp @@ -23,11 +23,14 @@ */ #include + #include "config.h" #include "threadheap.h" #include "processheap.h" #include "arch-specific.h" +using namespace BPrivate; + inline static processHeap * getAllocator(void) @@ -38,21 +41,7 @@ getAllocator(void) return theAllocator; } -#define HOARD_MALLOC(x) malloc(x) -#define HOARD_FREE(x) free(x) -#define HOARD_REALLOC(x,y) realloc(x,y) -#define HOARD_CALLOC(x,y) calloc(x,y) -#define HOARD_MEMALIGN(x,y) memalign(x,y) -#define HOARD_VALLOC(x) valloc(x) - -extern "C" void * HOARD_MALLOC(size_t); -extern "C" void HOARD_FREE(void *); -extern "C" void * HOARD_REALLOC(void *, size_t); -extern "C" void * HOARD_CALLOC(size_t, size_t); -extern "C" void * HOARD_MEMALIGN(size_t, size_t); -extern "C" void * HOARD_VALLOC(size_t); - - +#if 0 void * operator new (size_t size) { return HOARD_MALLOC (size); @@ -80,6 +69,7 @@ void operator delete[] (void * ptr) { HOARD_FREE (ptr); } +#endif extern "C" void * @@ -133,7 +123,7 @@ extern "C" void * realloc(void *ptr, size_t sz) { if (ptr == NULL) - return HOARD_MALLOC (sz); + return malloc(sz); if (sz == 0) { free(ptr); @@ -148,7 +138,6 @@ realloc(void *ptr, size_t sz) return ptr; // Allocate a new block of size sz. - void *buffer = malloc(sz); // Copy the contents of the original object @@ -158,7 +147,6 @@ realloc(void *ptr, size_t sz) memcpy(buffer, ptr, minSize); // Free the old block. - free(ptr); // Return a pointer to the new one.