Exemplo n.º 1
0
int HGSMIHeapSetup (HGSMIHEAP *pHeap,
                    void *pvBase,
                    HGSMISIZE cbArea,
                    HGSMIOFFSET offBase,
                    bool fOffsetBased)
{
    if (   !pHeap
        || !pvBase)
    {
        return VERR_INVALID_PARAMETER;
    }

    int rc = HGSMIAreaInitialize (&pHeap->area, pvBase, cbArea, offBase);

    if (RT_SUCCESS (rc))
    {
        if (!fOffsetBased)
            rc = RTHeapSimpleInit (&pHeap->u.hPtr, pvBase, cbArea);
        else
            rc = RTHeapOffsetInit (&pHeap->u.hOff, pvBase, cbArea);

        if (RT_SUCCESS (rc))
        {
            pHeap->cRefs = 0;
            pHeap->fOffsetBased = fOffsetBased;
        }
        else
        {
            HGSMIAreaClear (&pHeap->area);
        }
    }

    return rc;
}
Exemplo n.º 2
0
/**
 * Donate read+write+execute memory to the exec heap.
 *
 * This API is specific to AMD64 and Linux/GNU. A kernel module that desires to
 * use RTMemExecAlloc on AMD64 Linux/GNU will have to donate some statically
 * allocated memory in the module if it wishes for GCC generated code to work.
 * GCC can only generate modules that work in the address range ~2GB to ~0
 * currently.
 *
 * The API only accept one single donation.
 *
 * @returns IPRT status code.
 * @param   pvMemory    Pointer to the memory block.
 * @param   cb          The size of the memory block.
 */
RTR0DECL(int) RTR0MemExecDonate(void *pvMemory, size_t cb)
{
    int rc;
    AssertReturn(g_HeapExec == NIL_RTHEAPSIMPLE, VERR_WRONG_ORDER);

    rc = RTSpinlockCreate(&g_HeapExecSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTR0MemExecDonate");
    if (RT_SUCCESS(rc))
    {
        rc = RTHeapSimpleInit(&g_HeapExec, pvMemory, cb);
        if (RT_FAILURE(rc))
            rtR0MemExecCleanup();
    }
    return rc;
}
Exemplo n.º 3
0
/***
 * Worker for mmR3UkHeapAlloc that creates and adds a new sub-heap.
 *
 * @returns Pointer to the new sub-heap.
 * @param   pHeap       The heap
 * @param   cbSubHeap   The size of the sub-heap.
 */
static PMMUKHEAPSUB mmR3UkHeapAddSubHeap(PMMUKHEAP pHeap, size_t cbSubHeap)
{
    PMMUKHEAPSUB pSubHeap = (PMMUKHEAPSUB)MMR3HeapAllocU(pHeap->pUVM, MM_TAG_MM/*_UK_HEAP*/, sizeof(*pSubHeap));
    if (pSubHeap)
    {
        pSubHeap->cb = cbSubHeap;
        int rc = SUPR3PageAllocEx(pSubHeap->cb >> PAGE_SHIFT, 0, &pSubHeap->pv, &pSubHeap->pvR0, NULL);
        if (RT_SUCCESS(rc))
        {
            rc = RTHeapSimpleInit(&pSubHeap->hSimple, pSubHeap->pv, pSubHeap->cb);
            if (RT_SUCCESS(rc))
            {
                pSubHeap->pNext = pHeap->pSubHeapHead;
                pHeap->pSubHeapHead = pSubHeap;
                return pSubHeap;
            }

            /* bail out */
            SUPR3PageFreeEx(pSubHeap->pv, pSubHeap->cb >> PAGE_SHIFT);
        }
        MMR3HeapFree(pSubHeap);
    }
    return NULL;
}
Exemplo n.º 4
0
int main(int argc, char *argv[])
{
    /*
     * Init runtime.
     */
    RTTEST hTest;
    int rc = RTTestInitAndCreate("tstRTHeapSimple", &hTest);
    if (rc)
        return rc;
    RTTestBanner(hTest);

    /*
     * Create a heap.
     */
    RTTestSub(hTest, "Basics");
    static uint8_t s_abMem[128*1024];
    RTHEAPSIMPLE Heap;
    RTTESTI_CHECK_RC(rc = RTHeapSimpleInit(&Heap, &s_abMem[1], sizeof(s_abMem) - 1), VINF_SUCCESS);
    if (RT_FAILURE(rc))
        return RTTestSummaryAndDestroy(hTest);

    /*
     * Try allocate.
     */
    static struct TstHeapSimpleOps
    {
        size_t      cb;
        unsigned    uAlignment;
        void       *pvAlloc;
        unsigned    iFreeOrder;
    } s_aOps[] =
    {
        {        16,          0,    NULL,  0 },  // 0
        {        16,          4,    NULL,  1 },
        {        16,          8,    NULL,  2 },
        {        16,         16,    NULL,  5 },
        {        16,         32,    NULL,  4 },
        {        32,          0,    NULL,  3 },  // 5
        {        31,          0,    NULL,  6 },
        {      1024,          0,    NULL,  8 },
        {      1024,         32,    NULL, 10 },
        {      1024,         32,    NULL, 12 },
        { PAGE_SIZE,  PAGE_SIZE,    NULL, 13 },  // 10
        {      1024,         32,    NULL,  9 },
        { PAGE_SIZE,         32,    NULL, 11 },
        { PAGE_SIZE,  PAGE_SIZE,    NULL, 14 },
        {        16,          0,    NULL, 15 },
        {        9,           0,    NULL,  7 },  // 15
        {        16,          0,    NULL,  7 },
        {        36,          0,    NULL,  7 },
        {        16,          0,    NULL,  7 },
        {     12344,          0,    NULL,  7 },
        {        50,          0,    NULL,  7 },  // 20
        {        16,          0,    NULL,  7 },
    };
    unsigned i;
    RTHeapSimpleDump(Heap, (PFNRTHEAPSIMPLEPRINTF)RTPrintf); /** @todo Add some detail info output with a signature identical to RTPrintf. */
    size_t cbBefore = RTHeapSimpleGetFreeSize(Heap);
    static char szFill[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /* allocate */
    for (i = 0; i < RT_ELEMENTS(s_aOps); i++)
    {
        s_aOps[i].pvAlloc = RTHeapSimpleAlloc(Heap, s_aOps[i].cb, s_aOps[i].uAlignment);
        RTTESTI_CHECK_MSG(s_aOps[i].pvAlloc, ("RTHeapSimpleAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i));
        if (!s_aOps[i].pvAlloc)
            return RTTestSummaryAndDestroy(hTest);

        memset(s_aOps[i].pvAlloc, szFill[i], s_aOps[i].cb);
        RTTESTI_CHECK_MSG(RT_ALIGN_P(s_aOps[i].pvAlloc, (s_aOps[i].uAlignment ? s_aOps[i].uAlignment : 8)) == s_aOps[i].pvAlloc,
                          ("RTHeapSimpleAlloc(%p, %#x, %#x,) -> %p\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i));
        if (!s_aOps[i].pvAlloc)
            return RTTestSummaryAndDestroy(hTest);
    }

    /* free and allocate the same node again. */
    for (i = 0; i < RT_ELEMENTS(s_aOps); i++)
    {
        if (!s_aOps[i].pvAlloc)
            continue;
        //RTPrintf("debug: i=%d pv=%#x cb=%#zx align=%#zx cbReal=%#zx\n", i, s_aOps[i].pvAlloc,
        //         s_aOps[i].cb, s_aOps[i].uAlignment, RTHeapSimpleSize(Heap, s_aOps[i].pvAlloc));
        size_t cbBeforeSub = RTHeapSimpleGetFreeSize(Heap);
        RTHeapSimpleFree(Heap, s_aOps[i].pvAlloc);
        size_t cbAfterSubFree = RTHeapSimpleGetFreeSize(Heap);

        void *pv;
        pv = RTHeapSimpleAlloc(Heap, s_aOps[i].cb, s_aOps[i].uAlignment);
        RTTESTI_CHECK_MSG(pv, ("RTHeapSimpleAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i));
        if (!pv)
            return RTTestSummaryAndDestroy(hTest);
        //RTPrintf("debug: i=%d pv=%p cbReal=%#zx cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx \n", i, pv, RTHeapSimpleSize(Heap, pv),
        //         cbBeforeSub, cbAfterSubFree, RTHeapSimpleGetFreeSize(Heap));
        if (pv != s_aOps[i].pvAlloc)
            RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: Free+Alloc returned different address. new=%p old=%p i=%d\n", pv, s_aOps[i].pvAlloc, i);
        s_aOps[i].pvAlloc = pv;
        size_t cbAfterSubAlloc = RTHeapSimpleGetFreeSize(Heap);
        if (cbBeforeSub != cbAfterSubAlloc)
        {
            RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx. i=%d\n",
                          cbBeforeSub, cbAfterSubFree, cbAfterSubAlloc, i);
            //return 1; - won't work correctly until we start creating free block instead of donating memory on alignment.
        }
    }

    /* make a copy of the heap and the to-be-freed list. */
    static uint8_t s_abMemCopy[sizeof(s_abMem)];
    memcpy(s_abMemCopy, s_abMem, sizeof(s_abMem));
    uintptr_t    offDelta  = (uintptr_t)&s_abMemCopy[0] - (uintptr_t)&s_abMem[0];
    RTHEAPSIMPLE hHeapCopy = (RTHEAPSIMPLE)((uintptr_t)Heap + offDelta);
    static struct TstHeapSimpleOps s_aOpsCopy[RT_ELEMENTS(s_aOps)];
    memcpy(&s_aOpsCopy[0], &s_aOps[0], sizeof(s_aOps));

    /* free it in a specific order. */
    int cFreed = 0;
    for (i = 0; i < RT_ELEMENTS(s_aOps); i++)
    {
        unsigned j;
        for (j = 0; j < RT_ELEMENTS(s_aOps); j++)
        {
            if (    s_aOps[j].iFreeOrder != i
                ||  !s_aOps[j].pvAlloc)
                continue;
            //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapSimpleGetFreeSize(Heap), s_aOps[j].cb, s_aOps[j].pvAlloc);
            RTHeapSimpleFree(Heap, s_aOps[j].pvAlloc);
            s_aOps[j].pvAlloc = NULL;
            cFreed++;
        }
    }
    RTTESTI_CHECK(cFreed == RT_ELEMENTS(s_aOps));
    RTTestIPrintf(RTTESTLVL_ALWAYS, "i=done free=%d\n", RTHeapSimpleGetFreeSize(Heap));

    /* check that we're back at the right amount of free memory. */
    size_t cbAfter = RTHeapSimpleGetFreeSize(Heap);
    if (cbBefore != cbAfter)
    {
        RTTestIPrintf(RTTESTLVL_ALWAYS,
                      "Warning: Either we've split out an alignment chunk at the start, or we've got\n"
                      "         an alloc/free accounting bug: cbBefore=%d cbAfter=%d\n", cbBefore, cbAfter);
        RTHeapSimpleDump(Heap, (PFNRTHEAPSIMPLEPRINTF)RTPrintf);
    }

    /* relocate and free the bits in heap2 now. */
    RTTestSub(hTest, "RTHeapSimpleRelocate");
    rc = RTHeapSimpleRelocate(hHeapCopy, offDelta);
    RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
    if (RT_SUCCESS(rc))
    {
        /* free it in a specific order. */
        int cFreed2 = 0;
        for (i = 0; i < RT_ELEMENTS(s_aOpsCopy); i++)
        {
            unsigned j;
            for (j = 0; j < RT_ELEMENTS(s_aOpsCopy); j++)
            {
                if (    s_aOpsCopy[j].iFreeOrder != i
                    ||  !s_aOpsCopy[j].pvAlloc)
                    continue;
                //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapSimpleGetFreeSize(hHeapCopy), s_aOpsCopy[j].cb, s_aOpsCopy[j].pvAlloc);
                RTHeapSimpleFree(hHeapCopy, (uint8_t *)s_aOpsCopy[j].pvAlloc + offDelta);
                s_aOpsCopy[j].pvAlloc = NULL;
                cFreed2++;
            }
        }
        RTTESTI_CHECK(cFreed2 == RT_ELEMENTS(s_aOpsCopy));

        /* check that we're back at the right amount of free memory. */
        size_t cbAfterCopy = RTHeapSimpleGetFreeSize(hHeapCopy);
        RTTESTI_CHECK_MSG(cbAfterCopy == cbAfter, ("cbAfterCopy=%zu cbAfter=%zu\n", cbAfterCopy, cbAfter));
    }


    return RTTestSummaryAndDestroy(hTest);
}