00001 00002 // 00003 // The Hoard Multiprocessor Memory Allocator 00004 // www.hoard.org 00005 // 00006 // Author: Emery Berger, http://www.cs.utexas.edu/users/emery 00007 // 00008 // Copyright (c) 1998-2001, The University of Texas at Austin. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Library General Public License as 00012 // published by the Free Software Foundation, http://www.fsf.org. 00013 // 00014 // This library is distributed in the hope that it will be useful, but 00015 // WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Library General Public License for more details. 00018 // 00020 00021 /* 00022 superblock.h 00023 ------------------------------------------------------------------------ 00024 The superblock class controls a number of blocks (which are 00025 allocatable units of memory). 00026 ------------------------------------------------------------------------ 00027 @(#) $Id: superblock.h,v 1.41 2001/12/20 15:36:20 emery Exp $ 00028 ------------------------------------------------------------------------ 00029 Emery Berger | <http://www.cs.utexas.edu/users/emery> 00030 Department of Computer Sciences | <http://www.cs.utexas.edu> 00031 University of Texas at Austin | <http://www.utexas.edu> 00032 ======================================================================== 00033 */ 00034 00035 #ifndef _SUPERBLOCK_H_ 00036 #define _SUPERBLOCK_H_ 00037 00038 #include "config.h" 00039 00040 #include "arch-specific.h" 00041 #include "block.h" 00042 #include "persistentsuperblock.h" 00043 00044 class hoardHeap; // forward declaration 00045 class processHeap; // forward declaration 00046 class persistentHeap; // forward declaration 00047 00048 class superblock { 00049 00050 public: 00051 00052 // Construct a superblock for a given size class and set the heap 00053 // owner. 00054 superblock (int numblocks, 00055 int sizeclass, 00056 hoardHeap * owner, 00057 persistentSuperblock *psb); 00058 00059 ~superblock (void) 00060 { 00061 hoardLockDestroy (_upLock); 00062 } 00063 00064 // Make (allocate or re-use) a superblock for a given size class. 00065 static superblock * makeSuperblock (int sizeclass, persistentSuperblock *pSuperblock); 00066 static superblock * makeSuperblock (persistentSuperblock *pSuperblock); 00067 00068 // Find out who allocated this superblock. 00069 inline hoardHeap * getOwner (void); 00070 00071 // Set the superblock's owner. 00072 inline void setOwner (hoardHeap * o); 00073 00074 // Get (allocate) a block from the superblock. 00075 inline block * acquireBlock (void); 00076 00077 // Put a block back in the superblock. 00078 inline void putBlock (block * b); 00079 00080 // Get a pointer to the block identified by id. 00081 block * getBlock (int id); 00082 00083 // How many blocks are available? 00084 inline int getNumAvailable (void); 00085 00086 // How many blocks are there, in total? 00087 inline int getNumBlocks (void); 00088 00089 // What size class are blocks in this superblock? 00090 inline int getBlockSizeClass (void); 00091 00092 // Insert this superblock before the next one. 00093 inline void insertBefore (superblock * nextSb); 00094 00095 // Return the next pointer (to the next superblock in the list). 00096 inline superblock * getNext (void); 00097 00098 // Return the prev pointer (to the previous superblock in the list). 00099 inline superblock * getPrev (void); 00100 00101 // Return the 'fullness' of this superblock. 00102 inline int getFullness (void); 00103 00104 #if HEAP_FRAG_STATS 00105 // Return the amount of waste in every allocated block. 00106 int getMaxInternalFragmentation (void); 00107 #endif 00108 00109 // Remove this superblock from its linked list. 00110 inline void remove (void); 00111 00112 // Is this superblock valid? (i.e., 00113 // does it have the right magic number?) 00114 inline int isValid (void); 00115 00116 inline void upLock (void) { 00117 hoardLock (_upLock); 00118 } 00119 00120 inline void upUnlock (void) { 00121 hoardUnlock (_upLock); 00122 } 00123 00124 // Compute the 'fullness' of this superblock. 00125 inline void computeFullness (void); 00126 00127 inline persistentSuperblock *getPersistentSuperblock(void); 00128 inline void *getBlockRegion(int id); 00129 private: 00130 00131 00132 // Disable copying and assignment. 00133 00134 superblock (const superblock&); 00135 const superblock& operator= (const superblock&); 00136 00137 // Used for sanity checking. 00138 enum { SUPERBLOCK_MAGIC = 0xCAFEBABE }; 00139 00140 #if HEAP_DEBUG 00141 unsigned long _magic; 00142 #endif 00143 00144 const int _sizeClass; // The size class of blocks in the superblock. 00145 const int _numBlocks; // The number of blocks in the superblock. 00146 int _numAvailable; // The number of blocks available. 00147 int _fullness; // How full is this superblock? 00148 // (which SUPERBLOCK_FULLNESS group is it in) 00149 block * _freeList; // A pointer to the first free block. 00150 hoardHeap * _owner; // The heap who owns this superblock. 00151 superblock * _next; // The next superblock in the list. 00152 superblock * _prev; // The previous superblock in the list. 00153 00154 persistentSuperblock *_psb; // The persistent superblock backing this volatile superblock header. 00155 bool dirtyFullness; 00156 00157 hoardLockType _upLock; // Lock this when moving a superblock to the global (process) heap. 00158 00159 // We insert a cache pad here to prevent false sharing with the 00160 // first block (which immediately follows the superblock). 00161 00162 double _pad[CACHE_LINE / sizeof(double)]; 00163 }; 00164 00165 00166 hoardHeap * superblock::getOwner (void) 00167 { 00168 assert (isValid()); 00169 hoardHeap * o = _owner; 00170 return o; 00171 } 00172 00173 00174 void superblock::setOwner (hoardHeap * o) 00175 { 00176 assert (isValid()); 00177 _owner = o; 00178 } 00179 00180 00181 block * superblock::acquireBlock (void) 00182 { 00183 assert (isValid()); 00184 // Pop off a block from this superblock's freelist, 00185 // if there is one available. 00186 if (_freeList == NULL) { 00187 // The freelist is empty. 00188 assert (getNumAvailable() == 0); 00189 return NULL; 00190 } 00191 assert (getNumAvailable() > 0); 00192 block * b = _freeList; 00193 _freeList = _freeList->getNext(); 00194 _numAvailable--; 00195 _psb->allocBlock(b->getId()); 00196 00197 b->setNext(NULL); 00198 00199 dirtyFullness = true; 00200 // computeFullness(); 00201 00202 return b; 00203 } 00204 00205 00206 void superblock::putBlock (block * b) 00207 { 00208 assert (isValid()); 00209 // Push a block onto the superblock's freelist. 00210 assert (b->isValid()); 00211 assert (b->getSuperblock() == this); 00212 assert (getNumAvailable() < getNumBlocks()); 00213 b->setNext (_freeList); 00214 _freeList = b; 00215 _numAvailable++; 00216 _psb->freeBlock(b->getId()); 00217 00218 dirtyFullness = true; 00219 // computeFullness(); 00220 } 00221 00222 00223 00224 int superblock::getNumAvailable (void) 00225 { 00226 assert (isValid()); 00227 return _numAvailable; 00228 } 00229 00230 00231 int superblock::getNumBlocks (void) 00232 { 00233 assert (isValid()); 00234 return _numBlocks; 00235 } 00236 00237 00238 int superblock::getBlockSizeClass (void) 00239 { 00240 assert (isValid()); 00241 return _sizeClass; 00242 } 00243 00244 00245 superblock * superblock::getNext (void) 00246 { 00247 assert (isValid()); 00248 return _next; 00249 } 00250 00251 superblock * superblock::getPrev (void) 00252 { 00253 assert (isValid()); 00254 return _prev; 00255 } 00256 00257 00258 void superblock::insertBefore (superblock * nextSb) { 00259 assert (isValid()); 00260 // Insert this superblock before the next one (nextSb). 00261 assert (nextSb != this); 00262 _next = nextSb; 00263 if (nextSb) { 00264 _prev = nextSb->_prev; 00265 nextSb->_prev = this; 00266 } 00267 } 00268 00269 00270 void superblock::remove (void) { 00271 // Remove this superblock from a doubly-linked list. 00272 if (_next) { 00273 _next->_prev = _prev; 00274 } 00275 if (_prev) { 00276 _prev->_next = _next; 00277 } 00278 _prev = NULL; 00279 _next = NULL; 00280 } 00281 00282 00283 int superblock::isValid (void) 00284 { 00285 assert (_numBlocks > 0); 00286 assert (_numAvailable <= _numBlocks); 00287 assert (_sizeClass >= 0); 00288 return 1; 00289 } 00290 00291 00292 void superblock::computeFullness (void) 00293 { 00294 assert (isValid()); 00295 _fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1) 00296 * (getNumBlocks() - getNumAvailable())) / getNumBlocks()); 00297 } 00298 00299 int superblock::getFullness (void) 00300 { 00301 assert (isValid()); 00302 if (dirtyFullness) { 00303 computeFullness(); 00304 dirtyFullness = false; 00305 } 00306 return _fullness; 00307 } 00308 00309 persistentSuperblock *superblock::getPersistentSuperblock(void) 00310 { 00311 return _psb; 00312 } 00313 00314 void *superblock::getBlockRegion(int id) 00315 { 00316 return _psb->getBlockRegion(id); 00317 } 00318 00319 00320 #endif // _SUPERBLOCK_H_