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, processHeap * pHeap, persistentHeap *persistentHeap); 00066 static superblock * makeSuperblock (int sizeclass, persistentSuperblock *pSuperblock); 00067 static superblock * makeSuperblock (persistentSuperblock *pSuperblock); 00068 00069 // Find out who allocated this superblock. 00070 inline hoardHeap * getOwner (void); 00071 00072 // Set the superblock's owner. 00073 inline void setOwner (hoardHeap * o); 00074 00075 // Get (allocate) a block from the superblock. 00076 inline block * acquireBlock (void); 00077 00078 // Put a block back in the superblock. 00079 inline void putBlock (block * b); 00080 00081 // Get a pointer to the block identified by id. 00082 block * getBlock (int id); 00083 00084 // How many blocks are available? 00085 inline int getNumAvailable (void); 00086 00087 // How many blocks are there, in total? 00088 inline int getNumBlocks (void); 00089 00090 // What size class are blocks in this superblock? 00091 inline int getBlockSizeClass (void); 00092 00093 // Insert this superblock before the next one. 00094 inline void insertBefore (superblock * nextSb); 00095 00096 // Return the next pointer (to the next superblock in the list). 00097 inline superblock * getNext (void); 00098 00099 // Return the prev pointer (to the previous superblock in the list). 00100 inline superblock * getPrev (void); 00101 00102 // Return the 'fullness' of this superblock. 00103 inline int getFullness (void); 00104 00105 #if HEAP_FRAG_STATS 00106 // Return the amount of waste in every allocated block. 00107 int getMaxInternalFragmentation (void); 00108 #endif 00109 00110 // Remove this superblock from its linked list. 00111 inline void remove (void); 00112 00113 // Is this superblock valid? (i.e., 00114 // does it have the right magic number?) 00115 inline int isValid (void); 00116 00117 inline void upLock (void) { 00118 hoardLock (_upLock); 00119 } 00120 00121 inline void upUnlock (void) { 00122 hoardUnlock (_upLock); 00123 } 00124 00125 // Compute the 'fullness' of this superblock. 00126 inline void computeFullness (void); 00127 00128 inline persistentSuperblock *getPersistentSuperblock(void); 00129 inline void *getBlockRegion(int id); 00130 private: 00131 00132 00133 // Disable copying and assignment. 00134 00135 superblock (const superblock&); 00136 const superblock& operator= (const superblock&); 00137 00138 // Used for sanity checking. 00139 enum { SUPERBLOCK_MAGIC = 0xCAFEBABE }; 00140 00141 #if HEAP_DEBUG 00142 unsigned long _magic; 00143 #endif 00144 00145 const int _sizeClass; // The size class of blocks in the superblock. 00146 const int _numBlocks; // The number of blocks in the superblock. 00147 int _numAvailable; // The number of blocks available. 00148 int _fullness; // How full is this superblock? 00149 // (which SUPERBLOCK_FULLNESS group is it in) 00150 block * _freeList; // A pointer to the first free block. 00151 hoardHeap * _owner; // The heap who owns this superblock. 00152 superblock * _next; // The next superblock in the list. 00153 superblock * _prev; // The previous superblock in the list. 00154 00155 persistentSuperblock *_psb; // The persistent superblock backing this volatile superblock header. 00156 bool dirtyFullness; 00157 00158 hoardLockType _upLock; // Lock this when moving a superblock to the global (process) heap. 00159 00160 // We insert a cache pad here to prevent false sharing with the 00161 // first block (which immediately follows the superblock). 00162 00163 double _pad[CACHE_LINE / sizeof(double)]; 00164 }; 00165 00166 00167 hoardHeap * superblock::getOwner (void) 00168 { 00169 assert (isValid()); 00170 hoardHeap * o = _owner; 00171 return o; 00172 } 00173 00174 00175 void superblock::setOwner (hoardHeap * o) 00176 { 00177 assert (isValid()); 00178 _owner = o; 00179 } 00180 00181 00182 block * superblock::acquireBlock (void) 00183 { 00184 assert (isValid()); 00185 // Pop off a block from this superblock's freelist, 00186 // if there is one available. 00187 if (_freeList == NULL) { 00188 // The freelist is empty. 00189 assert (getNumAvailable() == 0); 00190 return NULL; 00191 } 00192 assert (getNumAvailable() > 0); 00193 block * b = _freeList; 00194 _freeList = _freeList->getNext(); 00195 _numAvailable--; 00196 _psb->allocBlock(b->getId()); 00197 00198 b->setNext(NULL); 00199 00200 dirtyFullness = true; 00201 // computeFullness(); 00202 00203 return b; 00204 } 00205 00206 00207 void superblock::putBlock (block * b) 00208 { 00209 assert (isValid()); 00210 // Push a block onto the superblock's freelist. 00211 assert (b->isValid()); 00212 assert (b->getSuperblock() == this); 00213 assert (getNumAvailable() < getNumBlocks()); 00214 b->setNext (_freeList); 00215 _freeList = b; 00216 _numAvailable++; 00217 _psb->freeBlock(b->getId()); 00218 00219 dirtyFullness = true; 00220 // computeFullness(); 00221 } 00222 00223 00224 00225 int superblock::getNumAvailable (void) 00226 { 00227 assert (isValid()); 00228 return _numAvailable; 00229 } 00230 00231 00232 int superblock::getNumBlocks (void) 00233 { 00234 assert (isValid()); 00235 return _numBlocks; 00236 } 00237 00238 00239 int superblock::getBlockSizeClass (void) 00240 { 00241 assert (isValid()); 00242 return _sizeClass; 00243 } 00244 00245 00246 superblock * superblock::getNext (void) 00247 { 00248 assert (isValid()); 00249 return _next; 00250 } 00251 00252 superblock * superblock::getPrev (void) 00253 { 00254 assert (isValid()); 00255 return _prev; 00256 } 00257 00258 00259 void superblock::insertBefore (superblock * nextSb) { 00260 assert (isValid()); 00261 // Insert this superblock before the next one (nextSb). 00262 assert (nextSb != this); 00263 _next = nextSb; 00264 if (nextSb) { 00265 _prev = nextSb->_prev; 00266 nextSb->_prev = this; 00267 } 00268 } 00269 00270 00271 void superblock::remove (void) { 00272 // Remove this superblock from a doubly-linked list. 00273 if (_next) { 00274 _next->_prev = _prev; 00275 } 00276 if (_prev) { 00277 _prev->_next = _next; 00278 } 00279 _prev = NULL; 00280 _next = NULL; 00281 } 00282 00283 00284 int superblock::isValid (void) 00285 { 00286 assert (_numBlocks > 0); 00287 assert (_numAvailable <= _numBlocks); 00288 assert (_sizeClass >= 0); 00289 return 1; 00290 } 00291 00292 00293 void superblock::computeFullness (void) 00294 { 00295 assert (isValid()); 00296 _fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1) 00297 * (getNumBlocks() - getNumAvailable())) / getNumBlocks()); 00298 } 00299 00300 int superblock::getFullness (void) 00301 { 00302 assert (isValid()); 00303 if (dirtyFullness) { 00304 computeFullness(); 00305 dirtyFullness = false; 00306 } 00307 return _fullness; 00308 } 00309 00310 persistentSuperblock *superblock::getPersistentSuperblock(void) 00311 { 00312 return _psb; 00313 } 00314 00315 void *superblock::getBlockRegion(int id) 00316 { 00317 return _psb->getBlockRegion(id); 00318 } 00319 00320 00321 #endif // _SUPERBLOCK_H_