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