⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heap.h

📁 newos is new operation system
💻 H
字号:
///-*-C++-*-////////////////////////////////////////////////////////////////////// Hoard: A Fast, Scalable, and Memory-Efficient Allocator//        for Shared-Memory Multiprocessors// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery//// Copyright (c) 1998-2000, The University of Texas at Austin.//// This library is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as// published by the Free Software Foundation, http://www.fsf.org.//// This library is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// Library General Public License for more details./////////////////////////////////////////////////////////////////////////////////*  heap.h  ------------------------------------------------------------------------  hoardHeap, the base class for threadHeap and processHeap.  ------------------------------------------------------------------------  @(#) $Id: heap.h,v 1.69 2001/03/22 22:10:36 emery Exp $  ------------------------------------------------------------------------  Emery Berger                    | <http://www.cs.utexas.edu/users/emery>  Department of Computer Sciences |             <http://www.cs.utexas.edu>  University of Texas at Austin   |                <http://www.utexas.edu>  ========================================================================*/#ifndef _HEAP_H_#define _HEAP_H_#include "config.h"//include <assert.h>//#include <math.h>#include "arch-specific.h"#include "superblock.h"#include "heapstats.h"class processHeap; // forward declarationclass hoardHeap {public:  hoardHeap (void);  // A superblock that holds more than one object must hold at least  // this many bytes.  enum { SUPERBLOCK_SIZE = 8192 };  // 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 };  // 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 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 };  // 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 = 128 };  // 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.#if MAX_INTERNAL_FRAGMENTATION == 2  enum { SIZE_CLASSES = 115 };#elif MAX_INTERNAL_FRAGMENTATION == 6  enum { SIZE_CLASSES = 46 };#elif MAX_INTERNAL_FRAGMENTATION == 10  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) };  // ANDing with this rounds to ALIGNMENT.  enum { ALIGNMENT_MASK = ALIGNMENT - 1};  // Used for sanity checking.  enum { HEAP_MAGIC = 0x0badcafe };  // 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 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);  // 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);  // Lock this heap.  inline void lock (void);  // Unlock this heap.  inline void unlock (void);  // 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);  // 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 ////  // 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 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);  // Align a value.  inline static size_t align (const size_t sz);private:  // Disable copying and assignment.  hoardHeap (const hoardHeap&);  const hoardHeap& operator= (const hoardHeap&);  // Recycle a superblock.  inline void recycle (superblock *);  // Reuse a superblock (if one is available).  inline superblock * reuse (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);  // 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);  //// Members ////#if HEAP_DEBUG  // For sanity checking.  const unsigned long _magic;#else  #define _magic HEAP_MAGIC#endif  // Heap statistics.  heapStats	_stats[SIZE_CLASSES];  // The per-heap lock.  hoardLockType _lock;  // Which heap this is (0 = the process (global) heap).  int _index;  // Reusable superblocks.  superblock *	_reusableSuperblocks;  int		_reusableSuperblocksCount;  // Lists of superblocks.  superblock *	_superblocks[SUPERBLOCK_FULLNESS_GROUP][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 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);  };  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){  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_STATSint 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();}#endifsuperblock * 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;    }  }#endif  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();    // Now get a block from the superblock.    // This superblock must have space available.    b = sb->getBlock();    assert (b != NULL);    // 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 (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));  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){  assert (_magic == HEAP_MAGIC);  hoardLock (_lock);}void hoardHeap::unlock (void) {  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;}#endif // _HEAP_H_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -