STATUS hybridCreateHeap()

in src/heap/src/HybridHeap.c [24:131]


STATUS hybridCreateHeap(PHeap pHeap, UINT32 spillRatio, UINT32 behaviorFlags, PHybridHeap* ppHybridHeap)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;
    PHybridHeap pHybridHeap = NULL;
    PBaseHeap pBaseHeap = NULL;
    PVOID handle = NULL;
    VramInit vramInit = NULL;
    VramAlloc vramAlloc = NULL;
    VramFree vramFree = NULL;
    VramLock vramLock = NULL;
    VramUnlock vramUnlock = NULL;
    VramUninit vramUninit = NULL;
    VramGetMax vramGetMax = NULL;
    BOOL reopenVramLibrary = ((behaviorFlags & FLAGS_REOPEN_VRAM_LIBRARY) != HEAP_FLAGS_NONE);

    CHK(pHeap != NULL, STATUS_NULL_ARG);
    CHK(spillRatio <= 100, STATUS_INVALID_ARG);

    // Load the library.
    // NOTE: The library will only be present on VRAM allocation capable devices
    // We will try to load the library with the name first and then with full path
    if (NULL == (handle = DLOPEN((PCHAR) VRAM_LIBRARY_NAME, RTLD_NOW | RTLD_GLOBAL)) &&
        NULL == (handle = DLOPEN((PCHAR) VRAM_LIBRARY_FULL_PATH, RTLD_NOW | RTLD_GLOBAL))) {
        CHK_ERR(FALSE, STATUS_HEAP_VRAM_LIB_MISSING, "Failed to load library %s with %s", VRAM_LIBRARY_NAME, DLERROR());
    }

    // HACK Reopening the vram library to increment the ref count, because for some unknown reason in heapRelease we
    // get a SIGSEGV on DLCLOSE as the library seems to be already closed, https://jira2.amazon.com/browse/AIVPLAYERS-5111.
    if (reopenVramLibrary && NULL == (handle = DLOPEN((PCHAR) VRAM_LIBRARY_NAME, RTLD_NOW | RTLD_GLOBAL)) &&
        NULL == (handle = DLOPEN((PCHAR) VRAM_LIBRARY_FULL_PATH, RTLD_NOW | RTLD_GLOBAL))) {
        CHK_ERR(FALSE, STATUS_HEAP_VRAM_LIB_REOPEN, "Failed to re-open library %s with %s", VRAM_LIBRARY_NAME, DLERROR());
    }

    // Load the functions and store the pointers
    CHK_ERR(NULL != (vramInit = (VramInit) DLSYM(handle, (PCHAR) VRAM_INIT_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_INIT_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_INIT_FUNC_SYMBOL_NAME, DLERROR());
    CHK_ERR(NULL != (vramAlloc = (VramAlloc) DLSYM(handle, (PCHAR) VRAM_ALLOC_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_ALLOC_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_ALLOC_FUNC_SYMBOL_NAME, DLERROR());
    CHK_ERR(NULL != (vramFree = (VramFree) DLSYM(handle, (PCHAR) VRAM_FREE_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_FREE_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_FREE_FUNC_SYMBOL_NAME, DLERROR());
    CHK_ERR(NULL != (vramLock = (VramLock) DLSYM(handle, (PCHAR) VRAM_LOCK_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_LOCK_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_LOCK_FUNC_SYMBOL_NAME, DLERROR());
    CHK_ERR(NULL != (vramUnlock = (VramUnlock) DLSYM(handle, (PCHAR) VRAM_UNLOCK_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_UNLOCK_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_UNLOCK_FUNC_SYMBOL_NAME, DLERROR());
    CHK_ERR(NULL != (vramUninit = (VramUninit) DLSYM(handle, (PCHAR) VRAM_UNINIT_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_UNINIT_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_UNINIT_FUNC_SYMBOL_NAME, DLERROR());
    CHK_ERR(NULL != (vramGetMax = (VramGetMax) DLSYM(handle, (PCHAR) VRAM_GETMAX_FUNC_SYMBOL_NAME)), STATUS_HEAP_VRAM_GETMAX_FUNC_SYMBOL,
            "Failed to load exported function %s with %s", VRAM_GETMAX_FUNC_SYMBOL_NAME, DLERROR());

    DLOGS("Creating hybrid heap with spill ratio %d", spillRatio);

    CHK_STATUS(commonHeapCreate((PHeap*) &pHybridHeap, SIZEOF(HybridHeap)));

    // Set the values
    pHybridHeap->pMemHeap = (PBaseHeap) pHeap;
    pHybridHeap->spillRatio = (DOUBLE) spillRatio / 100;
    pHybridHeap->vramInit = vramInit;
    pHybridHeap->vramAlloc = vramAlloc;
    pHybridHeap->vramFree = vramFree;
    pHybridHeap->vramLock = vramLock;
    pHybridHeap->vramUnlock = vramUnlock;
    pHybridHeap->vramUninit = vramUninit;
    pHybridHeap->vramGetMax = vramGetMax;
    pHybridHeap->libHandle = handle;
    pHybridHeap->vramInitialized = FALSE;

    // Return hybrid heap
    *ppHybridHeap = pHybridHeap;

    // Set the function pointers
    pBaseHeap = (PBaseHeap) pHybridHeap;
    pBaseHeap->heapInitializeFn = hybridHeapInit;
    pBaseHeap->heapReleaseFn = hybridHeapRelease;
    pBaseHeap->heapGetSizeFn = commonHeapGetSize; // Use the common heap functionality
    pBaseHeap->heapAllocFn = hybridHeapAlloc;
    pBaseHeap->heapFreeFn = hybridHeapFree;
    pBaseHeap->heapGetAllocSizeFn = hybridHeapGetAllocSize;
    pBaseHeap->heapSetAllocSizeFn = hybridHeapSetAllocSize;
    pBaseHeap->heapMapFn = hybridHeapMap;
    pBaseHeap->heapUnmapFn = hybridHeapUnmap;
    pBaseHeap->heapDebugCheckAllocatorFn = hybridHeapDebugCheckAllocator;
    pBaseHeap->getAllocationSizeFn = hybridGetAllocationSize;
    pBaseHeap->getAllocationHeaderSizeFn = hybridGetAllocationHeaderSize;
    pBaseHeap->getAllocationFooterSizeFn = hybridGetAllocationFooterSize;
    pBaseHeap->getAllocationAlignedSizeFn = hybridGetAllocationAlignedSize;
    pBaseHeap->getHeapLimitsFn = hybridGetHeapLimits;

CleanUp:
    if (STATUS_FAILED(retStatus)) {
        if (handle != NULL) {
            DLCLOSE(handle);
        }

        if (pHybridHeap != NULL) {
            // Ensure it doesn't get closed again
            pHybridHeap->libHandle = NULL;

            // Base heap will be released by the common heap
            pHybridHeap->pMemHeap = NULL;

            hybridHeapRelease((PHeap) pHybridHeap);
        }
    }

    LEAVES();
    return retStatus;
}