From a4a684e4332400c4c38649375135b0023985112d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 29 Jan 2003 18:38:11 +0000 Subject: [PATCH] Initial checkin of pool allocator library git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5429 91177308-0d34-0410-b5e6-96231b3b80d8 --- runtime/GCCLibraries/libpoolalloc/Makefile | 4 + .../libpoolalloc/PoolAllocatorChained.c | 166 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 runtime/GCCLibraries/libpoolalloc/Makefile create mode 100644 runtime/GCCLibraries/libpoolalloc/PoolAllocatorChained.c diff --git a/runtime/GCCLibraries/libpoolalloc/Makefile b/runtime/GCCLibraries/libpoolalloc/Makefile new file mode 100644 index 00000000000..2788fb27309 --- /dev/null +++ b/runtime/GCCLibraries/libpoolalloc/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../.. +LIBNAME = poolalloc +include ../Makefile.libs + diff --git a/runtime/GCCLibraries/libpoolalloc/PoolAllocatorChained.c b/runtime/GCCLibraries/libpoolalloc/PoolAllocatorChained.c new file mode 100644 index 00000000000..eb5656c1ee8 --- /dev/null +++ b/runtime/GCCLibraries/libpoolalloc/PoolAllocatorChained.c @@ -0,0 +1,166 @@ +#include +#include + +#undef assert +#define assert(X) + + +#define NODES_PER_SLAB 512 + +typedef struct PoolTy { + void *Data; + unsigned NodeSize; +} PoolTy; + +/* PoolSlab Structure - Hold NODES_PER_SLAB objects of the current node type. + * Invariants: FirstUnused <= LastUsed+1 + */ +typedef struct PoolSlab { + unsigned FirstUnused; /* First empty node in slab */ + int LastUsed; /* Last allocated node in slab */ + struct PoolSlab *Next; + unsigned char AllocatedBitVector[NODES_PER_SLAB/8]; + char Data[1]; /* Buffer to hold data in this slab... variable sized */ +} PoolSlab; + +#define NODE_ALLOCATED(POOLSLAB, NODENUM) \ + ((POOLSLAB)->AllocatedBitVector[(NODENUM) >> 3] & (1 << ((NODENUM) & 7))) +#define MARK_NODE_ALLOCATED(POOLSLAB, NODENUM) \ + (POOLSLAB)->AllocatedBitVector[(NODENUM) >> 3] |= 1 << ((NODENUM) & 7) +#define MARK_NODE_FREE(POOLSLAB, NODENUM) \ + (POOLSLAB)->AllocatedBitVector[(NODENUM) >> 3] &= ~(1 << ((NODENUM) & 7)) + + +/* poolinit - Initialize a pool descriptor to empty + */ +void poolinit(PoolTy *Pool, unsigned Size) { + assert(Pool && "Null pool pointer passed in!"); + + Pool->NodeSize = Size; + Pool->Data = 0; +} + +/* pooldestroy - Release all memory allocated for a pool + */ +void pooldestroy(PoolTy *Pool) { + PoolSlab *PS = (PoolSlab*)Pool->Data; + while (PS) { + PoolSlab *Next = PS->Next; + free(PS); + PS = Next; + } +} + +static void *FindSlabEntry(PoolSlab *PS, unsigned NodeSize) { + /* Loop through all of the slabs looking for one with an opening */ + for (; PS; PS = PS->Next) { + /* Check to see if there are empty entries at the end of the slab... */ + if (PS->LastUsed < NODES_PER_SLAB-1) { + /* Mark the returned entry used */ + MARK_NODE_ALLOCATED(PS, PS->LastUsed+1); + + /* If we are allocating out the first unused field, bump its index also */ + if (PS->FirstUnused == PS->LastUsed+1) + PS->FirstUnused++; + + /* Return the entry, increment LastUsed field. */ + return &PS->Data[0] + ++PS->LastUsed * NodeSize; + } + + /* If not, check to see if this node has a declared "FirstUnused" value that + * is less than the number of nodes allocated... + */ + if (PS->FirstUnused < NODES_PER_SLAB) { + /* Successfully allocate out the first unused node */ + unsigned Idx = PS->FirstUnused; + + /* Increment FirstUnused to point to the new first unused value... */ + do { + ++PS->FirstUnused; + } while (PS->FirstUnused < NODES_PER_SLAB && + NODE_ALLOCATED(PS, PS->FirstUnused)); + + return &PS->Data[0] + Idx*NodeSize; + } + } + + /* No empty nodes available, must grow # slabs! */ + return 0; +} + +char *poolalloc(PoolTy *Pool) { + unsigned NodeSize = Pool->NodeSize; + PoolSlab *PS = (PoolSlab*)Pool->Data; + void *Result; + + if ((Result = FindSlabEntry(PS, NodeSize))) + return Result; + + /* Otherwise we must allocate a new slab and add it to the list */ + PS = (PoolSlab*)malloc(sizeof(PoolSlab)+NodeSize*NODES_PER_SLAB-1); + + /* Initialize the slab to indicate that the first element is allocated */ + PS->FirstUnused = 1; + PS->LastUsed = 0; + PS->AllocatedBitVector[0] = 1; + + /* Add the slab to the list... */ + PS->Next = (PoolSlab*)Pool->Data; + Pool->Data = PS; + return &PS->Data[0]; +} + +void poolfree(PoolTy *Pool, char *Node) { + unsigned NodeSize = Pool->NodeSize, Idx; + PoolSlab *PS = (PoolSlab*)Pool->Data; + PoolSlab **PPS = (PoolSlab**)&Pool->Data; + + /* Seach for the slab that contains this node... */ + while (&PS->Data[0] > Node || &PS->Data[NodeSize*NODES_PER_SLAB] < Node) { + assert(PS && "free'd node not found in allocation pool specified!"); + PPS = &PS->Next; + PS = PS->Next; + } + + Idx = (Node-&PS->Data[0])/NodeSize; + assert(Idx < NODES_PER_SLAB && "Pool slab searching loop broken!"); + + /* Update the first free field if this node is below the free node line */ + if (Idx < PS->FirstUnused) PS->FirstUnused = Idx; + + /* If we are not freeing the last element in a slab... */ + if (Idx != PS->LastUsed) { + MARK_NODE_FREE(PS, Idx); + return; + } + + /* Otherwise we are freeing the last element in a slab... shrink the + * LastUsed marker down to last used node. + */ + do { + --PS->LastUsed; + /* Fixme, this should scan the allocated array an entire byte at a time for + * performance! + */ + } while (PS->LastUsed >= 0 && (!NODE_ALLOCATED(PS, PS->LastUsed))); + + assert(PS->FirstUnused <= PS->LastUsed+1 && + "FirstUnused field was out of date!"); + + /* Ok, if this slab is empty, we unlink it from the of slabs and either move + * it to the head of the list, or free it, depending on whether or not there + * is already an empty slab at the head of the list. + */ + if (PS->LastUsed == -1) { /* Empty slab? */ + PoolSlab *HeadSlab; + *PPS = PS->Next; /* Unlink from the list of slabs... */ + + HeadSlab = (PoolSlab*)Pool->Data; + if (HeadSlab && HeadSlab->LastUsed == -1){/* List already has empty slab? */ + free(PS); /* Free memory for slab */ + } else { + PS->Next = HeadSlab; /* No empty slab yet, add this */ + Pool->Data = PS; /* one to the head of the list */ + } + } +}