made the pool allocator thread safe
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13248 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+117
-163
@@ -1,31 +1,14 @@
|
|||||||
/*------------------------------------------------------------------------------
|
/*
|
||||||
// Copyright (c) 2001-2002, Haiku, Inc.
|
* Copyright 2001-2005, Haiku, Inc. All rights reserved.
|
||||||
//
|
* Distributed under the terms of the MIT License.
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
* Authors: John Walker <[email protected]>
|
||||||
// to deal in the Software without restriction, including without limitation
|
* DarkWyrm <[email protected]>
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* Stephan Aßmus <[email protected]>
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
*
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
* BGET pool allocator
|
||||||
//
|
*
|
||||||
// The above copyright notice and this permission notice shall be included in
|
*/
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
// File Name: bget++.cpp
|
|
||||||
// Author: John Walker <[email protected]>
|
|
||||||
// DarkWyrm <[email protected]>
|
|
||||||
// Description: public domain BGET pool allocator converted to C++
|
|
||||||
// Distributed with Haiku under MIT license
|
|
||||||
//
|
|
||||||
//------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This class is based on the BGET pool allocator. Original code was in standard
|
This class is based on the BGET pool allocator. Original code was in standard
|
||||||
@@ -51,54 +34,10 @@
|
|||||||
// Declare the interface, including the requested buffer size type, ssize_t.
|
// Declare the interface, including the requested buffer size type, ssize_t.
|
||||||
#include "BGet++.h"
|
#include "BGet++.h"
|
||||||
|
|
||||||
// Queue links
|
// some handy short cuts
|
||||||
struct qlinks
|
#define BH(p) ((bhead*) (p))
|
||||||
{
|
#define BDH(p) ((bdhead*) (p))
|
||||||
struct bfhead *flink; // Forward link
|
#define BFH(p) ((bfhead*) (p))
|
||||||
struct bfhead *blink; // Backward link
|
|
||||||
};
|
|
||||||
|
|
||||||
// Header in allocated and free buffers
|
|
||||||
struct bhead
|
|
||||||
{
|
|
||||||
// Relative link back to previous free buffer in memory or 0 if previous
|
|
||||||
// buffer is allocated.
|
|
||||||
ssize_t prevfree;
|
|
||||||
|
|
||||||
// Buffer size: positive if free, negative if allocated.
|
|
||||||
ssize_t bsize;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BH(p) ((struct bhead *) (p))
|
|
||||||
|
|
||||||
// Header in directly allocated buffers (by acqfcn)
|
|
||||||
struct bdhead
|
|
||||||
{
|
|
||||||
ssize_t tsize; // Total size, including overhead
|
|
||||||
struct bhead bh; // Common header
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BDH(p) ((struct bdhead *) (p))
|
|
||||||
|
|
||||||
// Header in free buffers
|
|
||||||
struct bfhead
|
|
||||||
{
|
|
||||||
// Common allocated/free header
|
|
||||||
struct bhead bh;
|
|
||||||
|
|
||||||
// Links on free list
|
|
||||||
struct qlinks ql;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BFH(p) ((struct bfhead *) (p))
|
|
||||||
|
|
||||||
static struct bfhead freelist =
|
|
||||||
{
|
|
||||||
// List of free buffers
|
|
||||||
{0, 0},
|
|
||||||
{&freelist, &freelist}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Minimum allocation quantum:
|
// Minimum allocation quantum:
|
||||||
#define QLSize (sizeof(struct qlinks))
|
#define QLSize (sizeof(struct qlinks))
|
||||||
@@ -110,31 +49,31 @@ static struct bfhead freelist =
|
|||||||
#define ESent ((ssize_t) (-(((1L << (sizeof(ssize_t) * 8 - 2)) - 1) * 2) - 2))
|
#define ESent ((ssize_t) (-(((1L << (sizeof(ssize_t) * 8 - 2)) - 1) * 2) - 2))
|
||||||
|
|
||||||
|
|
||||||
MemPool::MemPool(void)
|
MemPool::MemPool()
|
||||||
: totalloc(0),
|
: fTotalAlloced(0),
|
||||||
numget(0),
|
fGetCount(0),
|
||||||
numrel(0),
|
fReleaseCount(0),
|
||||||
numpblk(0),
|
fNumpblk(0),
|
||||||
numpget(0),
|
fNumpget(0),
|
||||||
numprel(0),
|
fNumprel(0),
|
||||||
numdget(0),
|
fNumdget(0),
|
||||||
numdrel(0),
|
fNumdrel(0),
|
||||||
exp_incr(0),
|
fExpIncr(0),
|
||||||
pool_len(0)
|
fPoolLength(0)
|
||||||
{
|
{
|
||||||
|
fFreeList.bh = (bhead){ 0, 0 };
|
||||||
|
fFreeList.ql = (qlinks){ &fFreeList, &fFreeList };
|
||||||
}
|
}
|
||||||
|
|
||||||
MemPool::~MemPool(void)
|
MemPool::~MemPool()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a buffer from the available space in the memory pool
|
// Allocate a buffer from the available space in the memory pool
|
||||||
void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
void*
|
||||||
|
MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
||||||
{
|
{
|
||||||
ssize_t size = requested_size;
|
ssize_t size = requested_size;
|
||||||
struct bfhead *b;
|
|
||||||
|
|
||||||
struct bfhead *best;
|
|
||||||
void *buf;
|
void *buf;
|
||||||
|
|
||||||
int compactseq = 0;
|
int compactseq = 0;
|
||||||
@@ -154,23 +93,25 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
// Add overhead in allocated buffer to size required.
|
// Add overhead in allocated buffer to size required.
|
||||||
size += sizeof(struct bhead);
|
size += sizeof(struct bhead);
|
||||||
|
|
||||||
|
bfhead *b;
|
||||||
|
bfhead *best;
|
||||||
// If a compact function was provided in the call to bectl(), wrap
|
// If a compact function was provided in the call to bectl(), wrap
|
||||||
// a loop around the allocation process to allow compaction to
|
// a loop around the allocation process to allow compaction to
|
||||||
// intervene in case we don't find a suitable buffer in the chain.
|
// intervene in case we don't find a suitable buffer in the chain.
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
b = freelist.ql.flink;
|
b = fFreeList.ql.flink;
|
||||||
best = &freelist;
|
best = &fFreeList;
|
||||||
|
|
||||||
|
|
||||||
// Scan the free list searching for the first buffer big enough
|
// Scan the free list searching for the first buffer big enough
|
||||||
// to hold the requested size buffer.
|
// to hold the requested size buffer.
|
||||||
|
|
||||||
while (b != &freelist)
|
while (b != &fFreeList)
|
||||||
{
|
{
|
||||||
if (b->bh.bsize >= size)
|
if (b->bh.bsize >= size)
|
||||||
{
|
{
|
||||||
if ((best == &freelist) || (b->bh.bsize < best->bh.bsize))
|
if ((best == &fFreeList) || (b->bh.bsize < best->bh.bsize))
|
||||||
{
|
{
|
||||||
best = b;
|
best = b;
|
||||||
}
|
}
|
||||||
@@ -180,7 +121,7 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
}
|
}
|
||||||
b = best;
|
b = best;
|
||||||
|
|
||||||
while (b != &freelist)
|
while (b != &fFreeList)
|
||||||
{
|
{
|
||||||
if ((ssize_t) b->bh.bsize >= size)
|
if ((ssize_t) b->bh.bsize >= size)
|
||||||
{
|
{
|
||||||
@@ -212,8 +153,8 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
// Mark buffer after this one not preceded by free block.
|
// Mark buffer after this one not preceded by free block.
|
||||||
bn->prevfree = 0;
|
bn->prevfree = 0;
|
||||||
|
|
||||||
totalloc += size;
|
fTotalAlloced += size;
|
||||||
numget++; // Increment number of GetBuffer() calls
|
fGetCount++; // Increment number of GetBuffer() calls
|
||||||
|
|
||||||
buf = (void *) ((((char *) ba) + sizeof(struct bhead)));
|
buf = (void *) ((((char *) ba) + sizeof(struct bhead)));
|
||||||
return buf;
|
return buf;
|
||||||
@@ -233,8 +174,8 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
b->ql.blink->ql.flink = b->ql.flink;
|
b->ql.blink->ql.flink = b->ql.flink;
|
||||||
b->ql.flink->ql.blink = b->ql.blink;
|
b->ql.flink->ql.blink = b->ql.blink;
|
||||||
|
|
||||||
totalloc += b->bh.bsize;
|
fTotalAlloced += b->bh.bsize;
|
||||||
numget++; // Increment number of GetBuffer() calls
|
fGetCount++; // Increment number of GetBuffer() calls
|
||||||
|
|
||||||
// Negate size to mark buffer allocated.
|
// Negate size to mark buffer allocated.
|
||||||
b->bh.bsize = -(b->bh.bsize);
|
b->bh.bsize = -(b->bh.bsize);
|
||||||
@@ -263,7 +204,7 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
// No buffer available with requested size free.
|
// No buffer available with requested size free.
|
||||||
|
|
||||||
// Don't give up yet -- look in the reserve supply.
|
// Don't give up yet -- look in the reserve supply.
|
||||||
if (size > (ssize_t)(exp_incr - sizeof(struct bhead)))
|
if (size > (ssize_t)(fExpIncr - sizeof(struct bhead)))
|
||||||
{
|
{
|
||||||
// Request is too large to fit in a single expansion
|
// Request is too large to fit in a single expansion
|
||||||
// block. Try to satisy it by a direct buffer acquisition.
|
// block. Try to satisy it by a direct buffer acquisition.
|
||||||
@@ -278,13 +219,13 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
bdh->bh.prevfree = 0;
|
bdh->bh.prevfree = 0;
|
||||||
bdh->tsize = size;
|
bdh->tsize = size;
|
||||||
|
|
||||||
totalloc += size;
|
fTotalAlloced += size;
|
||||||
|
|
||||||
// Increment number of GetBuffer() calls
|
// Increment number of GetBuffer() calls
|
||||||
numget++;
|
fGetCount++;
|
||||||
|
|
||||||
// Direct GetBuffer() call count
|
// Direct GetBuffer() call count
|
||||||
numdget++;
|
fNumdget++;
|
||||||
|
|
||||||
buf = (void *) (bdh + 1);
|
buf = (void *) (bdh + 1);
|
||||||
return buf;
|
return buf;
|
||||||
@@ -297,9 +238,9 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
// Try to obtain a new expansion block
|
// Try to obtain a new expansion block
|
||||||
void *newpool;
|
void *newpool;
|
||||||
|
|
||||||
if ((newpool = AcquireMem((ssize_t) exp_incr)) != NULL)
|
if ((newpool = AcquireMem((ssize_t) fExpIncr)) != NULL)
|
||||||
{
|
{
|
||||||
AddToPool(newpool, exp_incr);
|
AddToPool(newpool, fExpIncr);
|
||||||
|
|
||||||
// This can't, I say, can't get into a loop
|
// This can't, I say, can't get into a loop
|
||||||
buf = GetBuffer(requested_size);
|
buf = GetBuffer(requested_size);
|
||||||
@@ -346,7 +287,8 @@ void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
|||||||
// Reallocate a buffer. This is a minimal implementation, simply in terms
|
// Reallocate a buffer. This is a minimal implementation, simply in terms
|
||||||
// of ReleaseBuffer() and GetBuffer(). It could be enhanced to allow the
|
// of ReleaseBuffer() and GetBuffer(). It could be enhanced to allow the
|
||||||
// buffer to grow into adjacent free blocks and to avoid moving data unnecessarily.
|
// buffer to grow into adjacent free blocks and to avoid moving data unnecessarily.
|
||||||
void *MemPool::ReallocateBuffer(void *buf, ssize_t size)
|
void*
|
||||||
|
MemPool::ReallocateBuffer(void *buf, ssize_t size)
|
||||||
{
|
{
|
||||||
void *nbuf;
|
void *nbuf;
|
||||||
|
|
||||||
@@ -386,14 +328,15 @@ void *MemPool::ReallocateBuffer(void *buf, ssize_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BREL -- Release a buffer.
|
// BREL -- Release a buffer.
|
||||||
void MemPool::ReleaseBuffer(void *buf)
|
void
|
||||||
|
MemPool::ReleaseBuffer(void *buf)
|
||||||
{
|
{
|
||||||
struct bfhead *b, *bn;
|
struct bfhead *b, *bn;
|
||||||
|
|
||||||
b = BFH(((char *) buf) - sizeof(struct bhead));
|
b = BFH(((char *) buf) - sizeof(struct bhead));
|
||||||
|
|
||||||
// Increment number of ReleaseBuffer() calls
|
// Increment number of ReleaseBuffer() calls
|
||||||
numrel++;
|
fReleaseCount++;
|
||||||
|
|
||||||
assert(buf != NULL);
|
assert(buf != NULL);
|
||||||
|
|
||||||
@@ -405,11 +348,11 @@ void MemPool::ReleaseBuffer(void *buf)
|
|||||||
bdh = BDH(((char *) buf) - sizeof(struct bdhead));
|
bdh = BDH(((char *) buf) - sizeof(struct bdhead));
|
||||||
assert(b->bh.prevfree == 0);
|
assert(b->bh.prevfree == 0);
|
||||||
|
|
||||||
totalloc -= bdh->tsize;
|
fTotalAlloced -= bdh->tsize;
|
||||||
assert(totalloc >= 0);
|
assert(fTotalAlloced >= 0);
|
||||||
|
|
||||||
// Number of direct releases
|
// Number of direct releases
|
||||||
numdrel++;
|
fNumdrel++;
|
||||||
|
|
||||||
memset((char *) buf, 0x55, (int) (bdh->tsize - sizeof(struct bdhead)));
|
memset((char *) buf, 0x55, (int) (bdh->tsize - sizeof(struct bdhead)));
|
||||||
|
|
||||||
@@ -429,8 +372,8 @@ void MemPool::ReleaseBuffer(void *buf)
|
|||||||
// Back pointer in next buffer must be zero, indicating the same thing:
|
// Back pointer in next buffer must be zero, indicating the same thing:
|
||||||
assert(BH((char *) b - b->bh.bsize)->prevfree == 0);
|
assert(BH((char *) b - b->bh.bsize)->prevfree == 0);
|
||||||
|
|
||||||
totalloc += b->bh.bsize;
|
fTotalAlloced += b->bh.bsize;
|
||||||
assert(totalloc >= 0);
|
assert(fTotalAlloced >= 0);
|
||||||
|
|
||||||
|
|
||||||
// If the back link is nonzero, the previous buffer is free.
|
// If the back link is nonzero, the previous buffer is free.
|
||||||
@@ -453,11 +396,11 @@ void MemPool::ReleaseBuffer(void *buf)
|
|||||||
{
|
{
|
||||||
// The previous buffer isn't allocated. Insert this buffer on the
|
// The previous buffer isn't allocated. Insert this buffer on the
|
||||||
// free list as an isolated free block.
|
// free list as an isolated free block.
|
||||||
assert(freelist.ql.blink->ql.flink == &freelist);
|
assert(fFreeList.ql.blink->ql.flink == &fFreeList);
|
||||||
assert(freelist.ql.flink->ql.blink == &freelist);
|
assert(fFreeList.ql.flink->ql.blink == &fFreeList);
|
||||||
b->ql.flink = &freelist;
|
b->ql.flink = &fFreeList;
|
||||||
b->ql.blink = freelist.ql.blink;
|
b->ql.blink = fFreeList.ql.blink;
|
||||||
freelist.ql.blink = b;
|
fFreeList.ql.blink = b;
|
||||||
b->ql.blink->ql.flink = b;
|
b->ql.blink->ql.flink = b;
|
||||||
b->bh.bsize = -b->bh.bsize;
|
b->bh.bsize = -b->bh.bsize;
|
||||||
}
|
}
|
||||||
@@ -497,11 +440,11 @@ void MemPool::ReleaseBuffer(void *buf)
|
|||||||
bn->bh.prevfree = b->bh.bsize;
|
bn->bh.prevfree = b->bh.bsize;
|
||||||
|
|
||||||
// If a block-release function is defined, and this free buffer
|
// If a block-release function is defined, and this free buffer
|
||||||
// constitutes the entire block, release it. Note that pool_len
|
// constitutes the entire block, release it. Note that fPoolLength
|
||||||
// is defined in such a way that the test will fail unless all
|
// is defined in such a way that the test will fail unless all
|
||||||
// pool blocks are the same size.
|
// pool blocks are the same size.
|
||||||
|
|
||||||
if (((ssize_t) b->bh.bsize) == (ssize_t)(pool_len - sizeof(struct bhead)))
|
if (((ssize_t) b->bh.bsize) == (ssize_t)(fPoolLength - sizeof(struct bhead)))
|
||||||
{
|
{
|
||||||
assert(b->bh.prevfree == 0);
|
assert(b->bh.prevfree == 0);
|
||||||
assert(BH((char *) b + b->bh.bsize)->bsize == ESent);
|
assert(BH((char *) b + b->bh.bsize)->bsize == ESent);
|
||||||
@@ -514,38 +457,39 @@ void MemPool::ReleaseBuffer(void *buf)
|
|||||||
ReleaseMem(b);
|
ReleaseMem(b);
|
||||||
|
|
||||||
// Nr of expansion block releases
|
// Nr of expansion block releases
|
||||||
numprel++;
|
fNumprel++;
|
||||||
|
|
||||||
// Total number of blocks
|
// Total number of blocks
|
||||||
numpblk--;
|
fNumpblk--;
|
||||||
assert(numpblk == numpget - numprel);
|
assert(fNumpblk == fNumpget - fNumprel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a region of memory to the buffer pool.
|
// Add a region of memory to the buffer pool.
|
||||||
void MemPool::AddToPool(void *buf, ssize_t len)
|
void
|
||||||
|
MemPool::AddToPool(void *buf, ssize_t len)
|
||||||
{
|
{
|
||||||
struct bfhead *b = BFH(buf);
|
struct bfhead *b = BFH(buf);
|
||||||
struct bhead *bn;
|
struct bhead *bn;
|
||||||
|
|
||||||
len &= ~(SizeQuant - 1);
|
len &= ~(SizeQuant - 1);
|
||||||
|
|
||||||
if (pool_len == 0)
|
if (fPoolLength == 0)
|
||||||
{
|
{
|
||||||
pool_len = len;
|
fPoolLength = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (len != pool_len)
|
if (len != fPoolLength)
|
||||||
{
|
{
|
||||||
pool_len = -1;
|
fPoolLength = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of block acquisitions
|
// Number of block acquisitions
|
||||||
numpget++;
|
fNumpget++;
|
||||||
|
|
||||||
// Number of blocks total
|
// Number of blocks total
|
||||||
numpblk++;
|
fNumpblk++;
|
||||||
assert(numpblk == numpget - numprel);
|
assert(fNumpblk == fNumpget - fNumprel);
|
||||||
|
|
||||||
// Since the block is initially occupied by a single free buffer,
|
// Since the block is initially occupied by a single free buffer,
|
||||||
// it had better not be (much) larger than the largest buffer
|
// it had better not be (much) larger than the largest buffer
|
||||||
@@ -558,11 +502,11 @@ void MemPool::AddToPool(void *buf, ssize_t len)
|
|||||||
b->bh.prevfree = 0;
|
b->bh.prevfree = 0;
|
||||||
|
|
||||||
// Chain the new block to the free list.
|
// Chain the new block to the free list.
|
||||||
assert(freelist.ql.blink->ql.flink == &freelist);
|
assert(fFreeList.ql.blink->ql.flink == &fFreeList);
|
||||||
assert(freelist.ql.flink->ql.blink == &freelist);
|
assert(fFreeList.ql.flink->ql.blink == &fFreeList);
|
||||||
b->ql.flink = &freelist;
|
b->ql.flink = &fFreeList;
|
||||||
b->ql.blink = freelist.ql.blink;
|
b->ql.blink = fFreeList.ql.blink;
|
||||||
freelist.ql.blink = b;
|
fFreeList.ql.blink = b;
|
||||||
b->ql.blink->ql.flink = b;
|
b->ql.blink->ql.flink = b;
|
||||||
|
|
||||||
// Create a dummy allocated buffer at the end of the pool. This dummy
|
// Create a dummy allocated buffer at the end of the pool. This dummy
|
||||||
@@ -588,17 +532,18 @@ void MemPool::AddToPool(void *buf, ssize_t len)
|
|||||||
|
|
||||||
|
|
||||||
// Return buffer allocation free space statistics.
|
// Return buffer allocation free space statistics.
|
||||||
void MemPool::Stats(ssize_t *curalloc, ssize_t *totfree, ssize_t *maxfree,
|
void
|
||||||
long *nget, long *nrel)
|
MemPool::Stats(ssize_t *curalloc, ssize_t *totfree, ssize_t *maxfree,
|
||||||
|
long *nget, long *nrel)
|
||||||
{
|
{
|
||||||
struct bfhead *b = freelist.ql.flink;
|
struct bfhead *b = fFreeList.ql.flink;
|
||||||
|
|
||||||
*nget = numget;
|
*nget = fGetCount;
|
||||||
*nrel = numrel;
|
*nrel = fReleaseCount;
|
||||||
*curalloc = totalloc;
|
*curalloc = fTotalAlloced;
|
||||||
*totfree = 0;
|
*totfree = 0;
|
||||||
*maxfree = -1;
|
*maxfree = -1;
|
||||||
while (b != &freelist)
|
while (b != &fFreeList)
|
||||||
{
|
{
|
||||||
assert(b->bh.bsize > 0);
|
assert(b->bh.bsize > 0);
|
||||||
*totfree += b->bh.bsize;
|
*totfree += b->bh.bsize;
|
||||||
@@ -614,15 +559,16 @@ void MemPool::Stats(ssize_t *curalloc, ssize_t *totfree, ssize_t *maxfree,
|
|||||||
|
|
||||||
|
|
||||||
// Return extended statistics
|
// Return extended statistics
|
||||||
void MemPool::ExtendedStats(ssize_t *pool_incr, long *npool, long *npget, long *nprel,
|
void
|
||||||
long *ndget, long *ndrel)
|
MemPool::ExtendedStats(ssize_t *pool_incr, long *npool, long *npget, long *nprel,
|
||||||
|
long *ndget, long *ndrel)
|
||||||
{
|
{
|
||||||
*pool_incr = (pool_len < 0) ? -exp_incr : exp_incr;
|
*pool_incr = (fPoolLength < 0) ? -fExpIncr : fExpIncr;
|
||||||
*npool = numpblk;
|
*npool = fNumpblk;
|
||||||
*npget = numpget;
|
*npget = fNumpget;
|
||||||
*nprel = numprel;
|
*nprel = fNumprel;
|
||||||
*ndget = numdget;
|
*ndget = fNumdget;
|
||||||
*ndrel = numdrel;
|
*ndrel = fNumdrel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -630,7 +576,8 @@ void MemPool::ExtendedStats(ssize_t *pool_incr, long *npool, long *npget, long *
|
|||||||
// Dump the data in a buffer. This is called with the user data pointer,
|
// Dump the data in a buffer. This is called with the user data pointer,
|
||||||
// and backs up to the buffer header. It will dump either a free block
|
// and backs up to the buffer header. It will dump either a free block
|
||||||
// or an allocated one.
|
// or an allocated one.
|
||||||
void MemPool::BufferDump(void *buf)
|
void
|
||||||
|
MemPool::BufferDump(void *buf)
|
||||||
{
|
{
|
||||||
struct bfhead *b;
|
struct bfhead *b;
|
||||||
unsigned char *bdump;
|
unsigned char *bdump;
|
||||||
@@ -696,7 +643,8 @@ void MemPool::BufferDump(void *buf)
|
|||||||
// nonzero, the contents of allocated buffers are dumped. If DUMPFREE is
|
// nonzero, the contents of allocated buffers are dumped. If DUMPFREE is
|
||||||
// nonzero, free blocks are dumped as well. If FreeWipe checking is enabled,
|
// nonzero, free blocks are dumped as well. If FreeWipe checking is enabled,
|
||||||
// free blocks which have been clobbered will always be dumped.
|
// free blocks which have been clobbered will always be dumped.
|
||||||
void MemPool::PoolDump(void *buf, bool dumpalloc, bool dumpfree)
|
void
|
||||||
|
MemPool::PoolDump(void *buf, bool dumpalloc, bool dumpfree)
|
||||||
{
|
{
|
||||||
struct bfhead *b = BFH(buf);
|
struct bfhead *b = BFH(buf);
|
||||||
|
|
||||||
@@ -745,7 +693,8 @@ void MemPool::PoolDump(void *buf, bool dumpalloc, bool dumpfree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate a buffer pool.
|
// Validate a buffer pool.
|
||||||
int MemPool::Validate(void *buf)
|
int
|
||||||
|
MemPool::Validate(void *buf)
|
||||||
{
|
{
|
||||||
struct bfhead *b = BFH(buf);
|
struct bfhead *b = BFH(buf);
|
||||||
|
|
||||||
@@ -791,30 +740,34 @@ int MemPool::Validate(void *buf)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *MemPool::CompactMem(ssize_t sizereq, int sequence)
|
int*
|
||||||
|
MemPool::CompactMem(ssize_t sizereq, int sequence)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MemPool::AcquireMem(ssize_t size)
|
void*
|
||||||
|
MemPool::AcquireMem(ssize_t size)
|
||||||
{
|
{
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemPool::ReleaseMem(void *buffer)
|
void
|
||||||
|
MemPool::ReleaseMem(void *buffer)
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
AreaPool::AreaPool(void)
|
AreaPool::AreaPool()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AreaPool::~AreaPool(void)
|
AreaPool::~AreaPool()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void *AreaPool::AcquireMem(ssize_t size)
|
void*
|
||||||
|
AreaPool::AcquireMem(ssize_t size)
|
||||||
{
|
{
|
||||||
long areasize=0;
|
long areasize=0;
|
||||||
area_id a;
|
area_id a;
|
||||||
@@ -842,7 +795,8 @@ void *AreaPool::AcquireMem(ssize_t size)
|
|||||||
return parea;
|
return parea;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AreaPool::ReleaseMem(void *buffer)
|
void
|
||||||
|
AreaPool::ReleaseMem(void *buffer)
|
||||||
{
|
{
|
||||||
area_id trash=area_for(buffer);
|
area_id trash=area_for(buffer);
|
||||||
|
|
||||||
|
|||||||
+89
-38
@@ -1,53 +1,104 @@
|
|||||||
#ifndef HGET_H_
|
/*
|
||||||
#define HGET_H_
|
* Copyright 2001-2005, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
|
||||||
|
* Authors: John Walker <[email protected]>
|
||||||
|
* DarkWyrm <[email protected]>
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*
|
||||||
|
* BGET pool allocator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEM_POOL_H
|
||||||
|
#define MEM_POOL_H
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
class MemPool
|
class MemPool {
|
||||||
{
|
public:
|
||||||
public:
|
MemPool();
|
||||||
MemPool(void);
|
virtual ~MemPool();
|
||||||
virtual ~MemPool(void);
|
|
||||||
|
|
||||||
void AddToPool(void *buffer, ssize_t len);
|
void AddToPool(void* buffer, ssize_t len);
|
||||||
void *GetBuffer(ssize_t size, bool zero=false);
|
void* GetBuffer(ssize_t size, bool zero = false);
|
||||||
void *ReallocateBuffer(void *buffer, ssize_t size);
|
void* ReallocateBuffer(void* buffer, ssize_t size);
|
||||||
void ReleaseBuffer(void *buffer);
|
void ReleaseBuffer(void* buffer);
|
||||||
|
|
||||||
virtual int *CompactMem(ssize_t sizereq, int sequence);
|
virtual int* CompactMem(ssize_t sizereq, int sequence);
|
||||||
virtual void *AcquireMem(ssize_t size);
|
virtual void* AcquireMem(ssize_t size);
|
||||||
virtual void ReleaseMem(void *buffer);
|
virtual void ReleaseMem(void* buffer);
|
||||||
void SetPoolIncrement(ssize_t increment);
|
|
||||||
ssize_t PoolIncrement(void);
|
|
||||||
|
|
||||||
void Stats(ssize_t *curalloc, ssize_t *totfree, ssize_t *maxfree,
|
void SetPoolIncrement(ssize_t increment);
|
||||||
long *nget, long *nrel);
|
ssize_t PoolIncrement();
|
||||||
|
|
||||||
void ExtendedStats(ssize_t *pool_incr, long *npool, long *npget,
|
// debugging
|
||||||
long *nprel, long *ndget, long *ndrel);
|
void Stats(ssize_t* curalloc, ssize_t* totfree,
|
||||||
|
ssize_t* maxfree, long* nget, long* nrel);
|
||||||
|
|
||||||
void BufferDump(void *buf);
|
void ExtendedStats(ssize_t* pool_incr, long* npool,
|
||||||
void PoolDump(void *pool, bool dumpalloc, bool dumpfree);
|
long* npget, long* nprel,
|
||||||
int Validate(void *buffer);
|
long* ndget, long* ndrel);
|
||||||
|
|
||||||
private:
|
void BufferDump(void* buf);
|
||||||
ssize_t totalloc;
|
void PoolDump(void* pool, bool dumpalloc,
|
||||||
long numget, numrel;
|
bool dumpfree);
|
||||||
long numpblk;
|
|
||||||
long numpget, numprel;
|
|
||||||
long numdget, numdrel;
|
|
||||||
ssize_t exp_incr;
|
|
||||||
ssize_t pool_len;
|
|
||||||
|
|
||||||
|
int Validate(void* buffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Header in allocated and free buffers
|
||||||
|
struct bhead {
|
||||||
|
// Relative link back to previous free buffer in memory or 0 if previous
|
||||||
|
// buffer is allocated.
|
||||||
|
ssize_t prevfree;
|
||||||
|
// Buffer size: positive if free, negative if allocated.
|
||||||
|
ssize_t bsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Header in directly allocated buffers (by acqfcn)
|
||||||
|
struct bdhead {
|
||||||
|
ssize_t tsize; // Total size, including overhead
|
||||||
|
bhead bh; // Common header
|
||||||
|
};
|
||||||
|
|
||||||
|
// Queue links
|
||||||
|
struct bfhead;
|
||||||
|
struct qlinks {
|
||||||
|
bfhead *flink; // Forward link
|
||||||
|
bfhead *blink; // Backward link
|
||||||
|
};
|
||||||
|
|
||||||
|
// Header in free buffers
|
||||||
|
struct bfhead {
|
||||||
|
// Common allocated/free header
|
||||||
|
bhead bh;
|
||||||
|
// Links on free list
|
||||||
|
qlinks ql;
|
||||||
|
};
|
||||||
|
|
||||||
|
ssize_t fTotalAlloced;
|
||||||
|
long fGetCount;
|
||||||
|
long fReleaseCount;
|
||||||
|
long fNumpblk;
|
||||||
|
long fNumpget;
|
||||||
|
long fNumprel;
|
||||||
|
long fNumdget;
|
||||||
|
long fNumdrel;
|
||||||
|
ssize_t fExpIncr;
|
||||||
|
ssize_t fPoolLength;
|
||||||
|
// List of free buffers
|
||||||
|
bfhead fFreeList;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AreaPool : public MemPool
|
class AreaPool : public MemPool {
|
||||||
{
|
public:
|
||||||
public:
|
AreaPool();
|
||||||
AreaPool(void);
|
virtual ~AreaPool();
|
||||||
virtual ~AreaPool(void);
|
|
||||||
virtual void *AcquireMem(ssize_t size);
|
virtual void* AcquireMem(ssize_t size);
|
||||||
virtual void ReleaseMem(void *buffer);
|
virtual void ReleaseMem(void* buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user