superblock.h
------------------------------------------------------------------------
The superblock class controls a number of blocks (which are
allocatable units of memory).
------------------------------------------------------------------------
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 _SUPERBLOCK_H_
#define _SUPERBLOCK_H_
#include "config.h"
#include "arch-specific.h"
#include "block.h"
namespace BPrivate {
class hoardHeap;
class processHeap;
class superblock {
public:
superblock(int numblocks, int sizeclass, hoardHeap *owner);
~superblock(void) {}
static superblock *makeSuperblock(int sizeclass, processHeap *pHeap);
inline hoardHeap *getOwner(void);
inline void setOwner(hoardHeap *o);
inline block *getBlock(void);
inline void putBlock(block *b);
inline int getNumAvailable(void);
inline int getNumBlocks(void);
inline int getBlockSizeClass(void);
inline void insertBefore(superblock *nextSb);
inline superblock *const getNext(void);
inline superblock *const getPrev(void);
inline void computeFullness(void);
inline int getFullness(void);
#if HEAP_FRAG_STATS
int getMaxInternalFragmentation(void);
#endif
inline void remove(void);
inline int isValid(void);
void
upLock(void)
{
hoardLock(_upLock);
}
void
upUnlock(void)
{
hoardUnlock(_upLock);
}
private:
superblock(const superblock &);
const superblock & operator=(const superblock &);
enum { SUPERBLOCK_MAGIC = 0xCAFEBABE };
#if HEAP_DEBUG
unsigned long _magic;
#endif
const int _sizeClass;
const int _numBlocks;
int _numAvailable;
int _fullness;
block *_freeList;
hoardHeap *_owner;
superblock *_next;
superblock *_prev;
hoardLockType _upLock;
double _pad[CACHE_LINE / sizeof(double)];
};
hoardHeap *
superblock::getOwner(void)
{
assert(isValid());
hoardHeap *o = _owner;
return o;
}
void
superblock::setOwner(hoardHeap *o)
{
assert(isValid());
_owner = o;
}
block *
superblock::getBlock(void)
{
assert(isValid());
if (_freeList == NULL) {
assert(getNumAvailable() == 0);
return NULL;
}
assert(getNumAvailable() > 0);
block *b = _freeList;
_freeList = _freeList->getNext();
_numAvailable--;
b->setNext(NULL);
computeFullness();
return b;
}
void
superblock::putBlock(block *b)
{
assert(isValid());
assert(b->isValid());
assert(b->getSuperblock() == this);
assert(getNumAvailable() < getNumBlocks());
b->setNext(_freeList);
_freeList = b;
_numAvailable++;
computeFullness();
}
int
superblock::getNumAvailable(void)
{
assert(isValid());
return _numAvailable;
}
int
superblock::getNumBlocks(void)
{
assert(isValid());
return _numBlocks;
}
int
superblock::getBlockSizeClass(void)
{
assert(isValid());
return _sizeClass;
}
superblock * const
superblock::getNext(void)
{
assert(isValid());
return _next;
}
superblock * const
superblock::getPrev(void)
{
assert(isValid());
return _prev;
}
void
superblock::insertBefore(superblock * nextSb)
{
assert(isValid());
assert(nextSb != this);
_next = nextSb;
if (nextSb) {
_prev = nextSb->_prev;
nextSb->_prev = this;
}
}
void
superblock::remove(void)
{
if (_next)
_next->_prev = _prev;
if (_prev)
_prev->_next = _next;
_prev = NULL;
_next = NULL;
}
int
superblock::isValid(void)
{
assert(_numBlocks > 0);
assert(_numAvailable <= _numBlocks);
assert(_sizeClass >= 0);
return 1;
}
void
superblock::computeFullness(void)
{
assert(isValid());
_fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1)
* (getNumBlocks() - getNumAvailable())) / getNumBlocks());
}
int
superblock::getFullness(void)
{
assert(isValid());
return _fullness;
}
}
#endif