usermode/library/malloc-hoard-old/src/hoardheap.h

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   heap.h
00023   ------------------------------------------------------------------------
00024   hoardHeap, the base class for threadHeap and processHeap.
00025   ------------------------------------------------------------------------
00026   @(#) $Id: hoardheap.h,v 1.79 2001/12/20 15:36:18 emery Exp $
00027   ------------------------------------------------------------------------
00028   Emery Berger                    | <http://www.cs.utexas.edu/users/emery>
00029   Department of Computer Sciences |             <http://www.cs.utexas.edu>
00030   University of Texas at Austin   |                <http://www.utexas.edu>
00031   ========================================================================
00032 */
00033 
00034 
00035 #ifndef _HEAP_H_
00036 #define _HEAP_H_
00037 
00038 #include "config.h"
00039 
00040 #include "arch-specific.h"
00041 #include "superblock.h"
00042 #include "heapstats.h"
00043 
00044 class persistentHeap; // forward declaration
00045 
00046 class hoardHeap {
00047 public:
00048 
00049   hoardHeap (void);
00050 
00051   // A thread heap must be at least 1/EMPTY_FRACTION empty before we
00052   // start returning superblocks to the process heap.
00053   enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 };
00054 
00055   // Reset value for the least-empty bin.  The last bin
00056   // (SUPERBLOCK_FULLNESS_GROUP-1) is for completely full superblocks,
00057   // so we use the next-to-last bin.
00058   enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 };
00059 
00060   // The number of empty superblocks that we allow any thread heap to
00061   // hold once the thread heap has fallen below 1/EMPTY_FRACTION
00062   // empty.
00063   enum { MAX_EMPTY_SUPERBLOCKS = 1 } ; // EMPTY_FRACTION / 2 };
00064 
00065   // The maximum number of thread heaps we allow.  (NOT the maximum
00066   // number of threads -- Hoard imposes no such limit.)  This must be
00067   // a power of two! NB: This number is twice the maximum number of
00068   // PROCESSORS supported by Hoard.
00069   enum { MAX_HEAPS = 1 };
00070 
00071   // ANDing with this rounds to MAX_HEAPS.
00072   enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 };
00073 
00074   //
00075   // The number of size classes.
00076   //
00077 
00078   enum { SIZE_CLASSES = 132 };
00079 
00080   // Every object is aligned so that it can always hold a double.
00081   enum { ALIGNMENT = sizeof(double) };
00082 
00083   // ANDing with this rounds to ALIGNMENT.
00084   enum { ALIGNMENT_MASK = ALIGNMENT - 1};
00085 
00086   // Used for sanity checking.
00087   enum { HEAP_MAGIC = 0x0badcafe };
00088 
00089   // Get the usage and allocated statistics.
00090   inline void getStats (int sizeclass, int& U, int& A);
00091 
00092 
00093 #if HEAP_STATS
00094   // How much is the maximum ever in use for this size class?
00095   inline int maxInUse (int sizeclass);
00096 
00097   // How much is the maximum memory allocated for this size class?
00098   inline int maxAllocated (int sizeclass);
00099 #endif
00100 
00101   //FIXME: Move findAvailableSuperblock under processHeap and persistentHeap?
00102 
00103   // Insert a superblock into our list.
00104   void insertSuperblock (int sizeclass,
00105                          superblock * sb,
00106                          persistentHeap * persistentheap);
00107 
00108   // Insert a superblock into our list.
00109   void insertSuperblock (int sizeclass,
00110                          superblock * sb,
00111                          processHeap * pHeap);
00112 
00113 
00114   // Remove the superblock with the most free space.
00115   superblock * removeMaxSuperblock (int sizeclass);
00116 
00117   // Remove a superblock of some given fullness.
00118   superblock * removePartiallyFullSuperblock (int fullness, int sizeclass);
00119 
00120   // Find an available superblock (i.e., with some space in it).
00121   superblock * findAvailableSuperblock (int sizeclass,
00122                                         block *& b,
00123                                         persistentHeap * persistentheap);
00124 
00125   // Lock this heap.
00126   inline void lock (void);
00127 
00128   // Unlock this heap.
00129   inline void unlock (void);
00130 
00131   // Set our index number (which heap we are).
00132   inline void setIndex (int i);
00133 
00134   // Get our index number (which heap we are).
00135   inline int getIndex (void);
00136 
00137   // Free a block into a superblock.
00138   // This is used by processHeap::free().
00139   // Returns 1 iff the superblock was munmapped.
00140   int freeBlock (block *& b,
00141                  superblock *& sb,
00142                  int sizeclass,
00143                  persistentHeap * persistentheap);
00144 
00146 
00147   // Return the size class for a given size.
00148   inline static int sizeClass (const size_t sz);
00149 
00150   // Return the size corresponding to a given size class.
00151   inline static size_t sizeFromClass (const int sizeclass);
00152 
00153   // Return the release threshold corresponding to a given size class.
00154   inline static int getReleaseThreshold (const int sizeclass);
00155 
00156   // Return how many blocks of a given size class fit into a superblock.
00157   inline static int numBlocks (const int sizeclass);
00158 
00159   // Align a value.
00160   inline static size_t align (const size_t sz);
00161 
00162   void printSuperblockList();
00163 private:
00164 
00165   // Disable copying and assignment.
00166 
00167   hoardHeap (const hoardHeap&);
00168   const hoardHeap& operator= (const hoardHeap&);
00169 
00170   // Recycle a superblock.
00171   inline void recycle (superblock *);
00172 
00173   // Reuse a superblock (if one is available).
00174   inline superblock * reuse (int sizeclass);
00175 
00176   // Remove a particular superblock.
00177   inline void removeSuperblock (superblock *, int sizeclass);
00178 
00179 public:
00180         // Move a particular superblock from one bin to another.
00181   void moveSuperblock (superblock *,
00182                        int sizeclass,
00183                        int fromBin,
00184                        int toBin);
00185 private:
00186 
00187   // Update memory in-use and allocated statistics.
00188   // (*UStats = just update U.)
00189   inline void incStats (int sizeclass, int updateU, int updateA);
00190 
00191 public:
00192   inline void incUStats (int sizeclass);
00193 private:
00194 
00195   inline void decStats (int sizeclass, int updateU, int updateA);
00196   inline void decUStats (int sizeclass);
00197 
00199 
00200 #if HEAP_DEBUG
00201   // For sanity checking.
00202   const unsigned long _magic;
00203 #else
00204   #define _magic HEAP_MAGIC
00205 #endif
00206 
00207   // Heap statistics.
00208   heapStats     _stats[SIZE_CLASSES];
00209 
00210   // The per-heap lock.
00211   hoardLockType _lock;
00212 
00213   // Which heap this is (0 = the process (global) heap).
00214   int _index;
00215 
00216   // Reusable superblocks.
00217   superblock *  _reusableSuperblocks;
00218   int           _reusableSuperblocksCount;
00219 
00220   // Lists of superblocks.
00221   superblock *  _superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES];
00222 
00223   // The current least-empty superblock bin.
00224   int   _leastEmptyBin[SIZE_CLASSES];
00225 
00226   // The lookup table for size classes.
00227   static size_t _sizeTable[SIZE_CLASSES];
00228 
00229   // The lookup table for release thresholds.
00230   static size_t _threshold[SIZE_CLASSES];
00231 
00232 public:
00233   // A little helper class that we use to define some statics.
00234   class _initNumProcs {
00235   public:
00236         _initNumProcs(void);
00237   };
00238 
00239   friend class _initNumProcs;
00240 protected:
00241   // number of CPUs, cached
00242   static int _numProcessors;
00243   static int _numProcessorsMask;
00244 };
00245 
00246 
00247 
00248 void hoardHeap::incStats (int sizeclass, int updateU, int updateA) {
00249   assert (_magic == HEAP_MAGIC);
00250   assert (updateU >= 0);
00251   assert (updateA >= 0);
00252   assert (sizeclass >= 0);
00253   assert (sizeclass < SIZE_CLASSES);
00254   _stats[sizeclass].incStats (updateU, updateA);
00255 }
00256 
00257 
00258 
00259 void hoardHeap::incUStats (int sizeclass) {
00260   assert (_magic == HEAP_MAGIC);
00261   assert (sizeclass >= 0);
00262   assert (sizeclass < SIZE_CLASSES);
00263   _stats[sizeclass].incUStats ();
00264 }
00265 
00266 
00267 void hoardHeap::decStats (int sizeclass, int updateU, int updateA) {
00268   assert (_magic == HEAP_MAGIC);
00269   assert (updateU >= 0);
00270   assert (updateA >= 0);
00271   assert (sizeclass >= 0);
00272   assert (sizeclass < SIZE_CLASSES);
00273   _stats[sizeclass].decStats (updateU, updateA);
00274 }
00275 
00276 
00277 void hoardHeap::decUStats (int sizeclass)
00278 {
00279   assert (_magic == HEAP_MAGIC);
00280   assert (sizeclass >= 0);
00281   assert (sizeclass < SIZE_CLASSES);
00282   _stats[sizeclass].decUStats();
00283 }
00284 
00285 
00286 void hoardHeap::getStats (int sizeclass, int& U, int& A) {
00287   assert (_magic == HEAP_MAGIC);
00288   assert (sizeclass >= 0);
00289   assert (sizeclass < SIZE_CLASSES);
00290   _stats[sizeclass].getStats (U, A);
00291 }
00292 
00293 
00294 #if HEAP_STATS
00295 int hoardHeap::maxInUse (int sizeclass) {
00296   assert (_magic == HEAP_MAGIC);
00297   return _stats[sizeclass].getUmax();
00298 }
00299 
00300 
00301 int hoardHeap::maxAllocated (int sizeclass) {
00302   assert (_magic == HEAP_MAGIC);
00303   return _stats[sizeclass].getAmax(); 
00304 }
00305 #endif
00306 
00307 
00308 int hoardHeap::sizeClass (const size_t sz) {
00309   // Find the size class for a given object size
00310   // (the smallest i such that _sizeTable[i] >= sz).
00311   int sizeclass = 0;
00312   while (_sizeTable[sizeclass] < sz) 
00313     {
00314       sizeclass++;
00315       assert (sizeclass < SIZE_CLASSES);
00316     }
00317   return sizeclass;
00318 }
00319 
00320 
00321 size_t hoardHeap::sizeFromClass (const int sizeclass) {
00322   assert (sizeclass >= 0);
00323   assert (sizeclass < SIZE_CLASSES);
00324   return _sizeTable[sizeclass];
00325 }
00326 
00327 
00328 int hoardHeap::getReleaseThreshold (const int sizeclass) {
00329   assert (sizeclass >= 0);
00330   assert (sizeclass < SIZE_CLASSES);
00331   return _threshold[sizeclass];
00332 }
00333 
00334 
00335 int hoardHeap::numBlocks (const int sizeclass) {
00336   assert (sizeclass >= 0);
00337   assert (sizeclass < SIZE_CLASSES);
00338   const size_t s = sizeFromClass (sizeclass);
00339   assert (s > 0);
00340   const int blksize = align (s);
00341   // Compute the number of blocks that will go into this superblock.
00342   int nb =  MAX (1, ((SUPERBLOCK_SIZE) / blksize));
00343   return nb;
00344 }
00345 
00346 
00347 void hoardHeap::lock (void) 
00348 {
00349   assert (_magic == HEAP_MAGIC);
00350   hoardLock (_lock);
00351 }
00352 
00353 
00354 void hoardHeap::unlock (void) {
00355   assert (_magic == HEAP_MAGIC);
00356   hoardUnlock (_lock);
00357 }
00358 
00359 
00360 size_t hoardHeap::align (const size_t sz)
00361 {
00362   // Align sz up to the nearest multiple of ALIGNMENT.
00363   // This is much faster than using multiplication
00364   // and division.
00365   return (sz + ALIGNMENT_MASK) & ~((size_t) ALIGNMENT_MASK);
00366 }
00367 
00368 
00369 void hoardHeap::setIndex (int i) 
00370 {
00371   _index = i; 
00372 }
00373 
00374 
00375 int hoardHeap::getIndex (void)
00376 {
00377   return _index;
00378 }
00379 
00380 
00381 
00382 
00383 void hoardHeap::recycle (superblock * sb)
00384 {
00385   assert (sb != NULL);
00386   assert (sb->getOwner() == this);
00387   assert (sb->getNumBlocks() > 1);
00388   assert (sb->getNext() == NULL);
00389   assert (sb->getPrev() == NULL);
00390   assert (hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1);
00391   sb->insertBefore (_reusableSuperblocks);
00392   _reusableSuperblocks = sb;
00393   ++_reusableSuperblocksCount;
00394   // printf ("count: %d => %d\n", getIndex(), _reusableSuperblocksCount);
00395 }
00396 
00397 
00398 superblock * hoardHeap::reuse (int sizeclass)
00399 { 
00400   persistentSuperblock *psb;
00401 
00402   if (_reusableSuperblocks == NULL) {
00403     return NULL;
00404   }
00405 
00406   // Make sure that we aren't using a sizeclass
00407   // that is too big for a 'normal' superblock.
00408   if (hoardHeap::numBlocks(sizeclass) <= 1) {
00409     return NULL;
00410   }
00411 
00412   // Pop off a superblock from the reusable-superblock list.
00413   assert (_reusableSuperblocksCount > 0);
00414   superblock * sb = _reusableSuperblocks;
00415   _reusableSuperblocks = sb->getNext();
00416   sb->remove();
00417   psb = sb->getPersistentSuperblock();
00418   assert (psb != NULL);
00419   assert (sb->getNumBlocks() > 1);
00420   --_reusableSuperblocksCount;
00421 
00422   // Reformat the superblock if necessary.
00423   if (sb->getBlockSizeClass() != sizeclass) {
00424     decStats (sb->getBlockSizeClass(),
00425               sb->getNumBlocks() - sb->getNumAvailable(),
00426               sb->getNumBlocks());
00427 
00428 
00429     sb->superblock::~superblock();
00430     
00431         //FIXME: what to do with stats inc/dec? do I need to reflect those to the persistent superblock?
00432         //FIXME: what to do with the persistent superblock? keep the same
00433         assert(psb->isFree() == true); // persistent superblock must be free to change its sizeclass
00434         int new_blksize = sizeFromClass(sizeclass);
00435         psb->setBlockSize(new_blksize);
00436     sb = new ((char *) sb) superblock (numBlocks(sizeclass), sizeclass, this, psb);
00437     psb->setSuperblock(sb);
00438 
00439     incStats (sizeclass,
00440               sb->getNumBlocks() - sb->getNumAvailable(),
00441               sb->getNumBlocks());
00442   }
00443 
00444   assert (sb->getOwner() == this);
00445   assert (sb->getBlockSizeClass() == sizeclass);
00446   return sb;
00447 }
00448 
00449 #endif // _HEAP_H_

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7