#include <string.h>
#include <stdio.h>
#include "config.h"
#if USE_PRIVATE_HEAPS
# include "privateheap.h"
# define HEAPTYPE privateHeap
#else
# define HEAPTYPE threadHeap
# include "threadheap.h"
#endif
#include "processheap.h"
using namespace BPrivate;
processHeap::processHeap()
:
theap((HEAPTYPE*)hoardSbrk(sizeof(HEAPTYPE) * fMaxThreadHeaps)),
#if HEAP_FRAG_STATS
_currentAllocated(0),
_currentRequested(0),
_maxAllocated(0),
_inUseAtMaxAllocated(0),
_maxRequested(0),
#endif
#if HEAP_LOG
_log((Log<MemoryRequest>*)
hoardSbrk(sizeof(Log<MemoryRequest>) * (fMaxThreadHeaps + 1))),
#endif
_buffer(NULL),
_bufferCount(0)
{
if (theap == NULL)
return;
new(theap) HEAPTYPE[fMaxThreadHeaps];
#if HEAP_LOG
if (_log == NULL)
return;
new(_log) Log<MemoryRequest>[fMaxThreadHeaps + 1];
#endif
int i;
setIndex(0);
for (i = 0; i < fMaxThreadHeaps; i++) {
theap[i].setpHeap(this);
theap[i].setIndex(i + 1);
}
#if HEAP_LOG
for (i = 0; i < fMaxThreadHeaps + 1; i++) {
char fname[255];
sprintf(fname, "log%d", i);
unlink(fname);
_log[i].open(fname);
}
#endif
#if HEAP_FRAG_STATS
hoardLockInit(_statsLock, "hoard stats");
#endif
hoardLockInit(_bufferLock, "hoard buffer");
}
void
processHeap::stats(void)
{
#if HEAP_STATS
int umax = 0;
int amax = 0;
for (int j = 0; j < fMaxThreadHeaps; j++) {
for (int i = 0; i < SIZE_CLASSES; i++) {
amax += theap[j].maxAllocated(i) * sizeFromClass(i);
umax += theap[j].maxInUse(i) * sizeFromClass(i);
}
}
printf("Amax <= %d, Umax <= %d\n", amax, umax);
#if HEAP_FRAG_STATS
amax = getMaxAllocated();
umax = getMaxRequested();
printf
("Maximum allocated = %d\nMaximum in use = %d\nIn use at max allocated = %d\n",
amax, umax, getInUseAtMaxAllocated());
printf("Still in use = %d\n", _currentRequested);
printf("Fragmentation (3) = %f\n",
(float)amax / (float)getInUseAtMaxAllocated());
printf("Fragmentation (4) = %f\n", (float)amax / (float)umax);
#endif
#endif
#if HEAP_LOG
printf("closing logs.\n");
fflush(stdout);
for (int i = 0; i < fMaxThreadHeaps + 1; i++) {
_log[i].close();
}
#endif
}
#if HEAP_FRAG_STATS
void
processHeap::setAllocated(int requestedSize, int actualSize)
{
hoardLock(_statsLock);
_currentRequested += requestedSize;
_currentAllocated += actualSize;
if (_currentRequested > _maxRequested) {
_maxRequested = _currentRequested;
}
if (_currentAllocated > _maxAllocated) {
_maxAllocated = _currentAllocated;
_inUseAtMaxAllocated = _currentRequested;
}
hoardUnlock(_statsLock);
}
void
processHeap::setDeallocated(int requestedSize, int actualSize)
{
hoardLock(_statsLock);
_currentRequested -= requestedSize;
_currentAllocated -= actualSize;
hoardUnlock(_statsLock);
}
#endif
void
processHeap::free(void *ptr)
{
if (ptr == 0)
return;
block *b = (block *) ptr - 1;
assert(b->isValid());
if (((unsigned long)b->getNext() & 1) == 1) {
b = (block *) ((unsigned long)b->getNext() & ~1);
assert(b->isValid());
}
b->markFree();
superblock *sb = b->getSuperblock();
assert(sb);
assert(sb->isValid());
const int sizeclass = sb->getBlockSizeClass();
hoardHeap *owner;
sb->upLock();
while (1) {
owner = sb->getOwner();
owner->lock();
if (owner == sb->getOwner()) {
break;
} else {
owner->unlock();
}
hoardYield();
}
#if HEAP_LOG
MemoryRequest m;
m.free(ptr);
getLog(owner->getIndex()).append(m);
#endif
#if HEAP_FRAG_STATS
setDeallocated(b->getRequestedSize(), 0);
#endif
int sbUnmapped = owner->freeBlock(b, sb, sizeclass, this);
owner->unlock();
if (!sbUnmapped)
sb->upUnlock();
}