Example #1
0
static void
applyMemoryPool(const char* pathname)
{
	struct stat st;

	stat(pathname, &st);

	initMemoryPool(st.st_size);
}
Example #2
0
void* allocate(size_t size) {
    if (!pool) {
        initMemoryPool(32, 1024);
    }

#ifdef LOG_ALLOCATIONS
    LOG("Allocating %d bytes...", size);
#endif

    //  add padding to compensate for alignment and add the size of the header
    size += (((size % ALIGNMENT) > 0) ? ALIGNMENT - (size % ALIGNMENT) : 0);
    size += sizeof(AllocationHeader);

    //  calculate pages and tracking units needed
    unsigned int pagesRequested = size / pageSize + ((size % pageSize) ? 1 : 0);
    unsigned int trackingUnitsRequested = pagesRequested / PAGES_PER_UNIT + ((pagesRequested % PAGES_PER_UNIT) ? 1 : 0);

    //  make sure it isn't more than the entire pool
    if (trackingUnitsRequested > numTrackingUnits) {
        return NULL;
    }

    //  search through all tracking units
    unsigned int beginningTrackingUnit = 0;
    while (beginningTrackingUnit < numTrackingUnits) {
        unsigned int preOffset = 0;
        TrackingUnit preBitMask = 0;

        if (pagesRequested < PAGES_PER_UNIT) {
            //  build a bitmask that will find contiguous pages within a tracking unit
            preBitMask = ALL_PAGES_IN_USE << (PAGES_PER_UNIT - pagesRequested);
        } else {
            preBitMask = ALL_PAGES_IN_USE;
        }

        for (; preOffset < PAGES_PER_UNIT; ++preOffset) {
            if ((~(trackingBits[beginningTrackingUnit]) & preBitMask) == preBitMask) {
                //  found a bitmask with enough contiguous pages
                break;
            }
            preBitMask = preBitMask >> 1;
        }

        if (preOffset == PAGES_PER_UNIT) {
            beginningTrackingUnit++;
            //  skip subsequent fully used tracking units
            while (trackingBits[beginningTrackingUnit] == ALL_PAGES_IN_USE) {
                beginningTrackingUnit++;
            }
            continue;
        }

        TrackingUnit remainingPagesNeeded = ((pagesRequested >= (PAGES_PER_UNIT - preOffset)) ? (pagesRequested - (PAGES_PER_UNIT - preOffset)) : 0);

        //  check if all the required pages have been found
        if (remainingPagesNeeded == 0) {
            //  mark the tracking unit as used
            trackingBits[beginningTrackingUnit] |= preBitMask;

            //  calculate the memory address
            unsigned int address = ((beginningTrackingUnit * PAGES_PER_UNIT) + preOffset) * pageSize;

            //  write the allocation header
            *(unsigned int*)((unsigned int)(const_cast<void*>(pool)) + address) = size;

            //  return the memory!
            return (void*)((unsigned int)(const_cast<void*>(pool)) + address + sizeof(AllocationHeader));
        }

        //  uhm... early out
        unsigned int nextTrackingUnit = (beginningTrackingUnit + 1) % numTrackingUnits;
        if (nextTrackingUnit < beginningTrackingUnit) {
            return NULL;
        }

        //  look for contiguous unused tracking units
        unsigned int contiguousTrackingUnitsAvailable = 0;
        unsigned int contiguousTrackingUnitsNeeded = remainingPagesNeeded / PAGES_PER_UNIT;
        for (unsigned int i = nextTrackingUnit; i < numTrackingUnits && contiguousTrackingUnitsAvailable < contiguousTrackingUnitsNeeded; ++i) {
            if (trackingBits[i] == 0) {
                contiguousTrackingUnitsAvailable++;
            } else {
                //  not gonna fit... bail!
                contiguousTrackingUnitsAvailable = 0;
                beginningTrackingUnit = i;
                break;
            }
        }

        //  make sure we found enough...
        if (contiguousTrackingUnitsAvailable < contiguousTrackingUnitsNeeded) {
            continue;
        }

        remainingPagesNeeded = remainingPagesNeeded - (contiguousTrackingUnitsAvailable * PAGES_PER_UNIT);

        if (remainingPagesNeeded == 0) {
            trackingBits[beginningTrackingUnit] |= preBitMask;
            for (unsigned int i = nextTrackingUnit; i < (nextTrackingUnit + contiguousTrackingUnitsAvailable); ++i) {
                trackingBits[i] |= ALL_PAGES_IN_USE;

                //  calculate the memory address
                unsigned int address = ((beginningTrackingUnit * PAGES_PER_UNIT) + preOffset) * pageSize;

                //  write the allocation header
                *(unsigned int*)((unsigned int)(const_cast<void*>(pool)) + address) = size;

                //  return the memory!
                return (void*)((unsigned int)(const_cast<void*>(pool)) + address + sizeof(AllocationHeader));
            }
        }

        //  again.. uhm... early out
        nextTrackingUnit = (nextTrackingUnit + contiguousTrackingUnitsAvailable) % numTrackingUnits;
        if (nextTrackingUnit <= beginningTrackingUnit) {
            return NULL;
        }

        //  build a bitmask for finding the last batch of contiguous pages within a tracking unit
        TrackingUnit postBitMask = ALL_PAGES_IN_USE << (PAGES_PER_UNIT - remainingPagesNeeded);


        if ((~(trackingBits[nextTrackingUnit]) & postBitMask) == postBitMask) {
            //  mark the pages used
            trackingBits[beginningTrackingUnit] |= preBitMask;
            for (unsigned int i = (beginningTrackingUnit + 1); i < nextTrackingUnit; ++i) {
                trackingBits[i] = ALL_PAGES_IN_USE;
            }
            trackingBits[nextTrackingUnit] |= postBitMask;

            //  calculate the memory address
            unsigned int address = ((beginningTrackingUnit * PAGES_PER_UNIT) + preOffset) * pageSize;

            //  write the allocation header
            *(unsigned int*)((unsigned int)(const_cast<void*>(pool)) + address) = size;

            //  return the memory!
            return (void*)((unsigned int)(const_cast<void*>(pool)) + address + sizeof(AllocationHeader));
        }

        //  set the next tracking unit
        beginningTrackingUnit = nextTrackingUnit;

    }   //  finish loop through tracking bits

    return NULL;
}