From 4df0449906209a805c4fc1e9a5af296162975fb0 Mon Sep 17 00:00:00 2001 From: Mushegh Malkhasyan <33669149+MushMal@users.noreply.github.com> Date: Fri, 1 Jan 2021 21:23:48 -0800 Subject: [PATCH] File backed hybrid heap implementation (#101) * File backed hybrid heap implementation * Fix mem leak on system hybrid heap test as the heap release doesn't free the allocations. Fixing Windows build. * Fixing test leak with system heap in hybrid heap test. This was not caught locally by the tools (odd) Fixing Windows build issue with missing header Fixing some warnings with unreferenced params that were only triggered by Windows VC compiler Fixing some warnings with type cast loss of precision warnings triggered by Windows VC compiler --- src/client/src/Client.c | 1 + src/client/src/Stream.c | 6 +- src/client/src/StreamEvent.c | 4 +- .../kinesis/video/common/CommonDefs.h | 6 +- .../amazonaws/kinesis/video/heap/Include.h | 5 +- src/heap/src/Common.c | 8 +- src/heap/src/Common.h | 1 + src/heap/src/Heap.c | 12 +- src/heap/src/HybridFileHeap.c | 598 ++++++++++++++++++ src/heap/src/HybridFileHeap.h | 131 ++++ src/heap/src/HybridHeap.c | 32 +- src/heap/src/Include_i.h | 1 + src/heap/tst/HeapApiFunctionalityTest.cpp | 38 +- src/heap/tst/HeapApiTest.cpp | 157 +++-- src/heap/tst/HeapPerfTest.cpp | 12 +- src/heap/tst/HeapTestFixture.cpp | 13 +- src/heap/tst/HeapTestFixture.h | 1 - src/heap/tst/HybridFileHeapTest.cpp | 172 +++++ src/heap/tst/HybridHeapTest.cpp | 275 ++++---- src/mkvgen/src/SpsParser.c | 3 +- .../amazonaws/kinesis/video/utils/Include.h | 2 + src/utils/src/FileIo.c | 114 +++- 22 files changed, 1379 insertions(+), 213 deletions(-) create mode 100644 src/heap/src/HybridFileHeap.c create mode 100644 src/heap/src/HybridFileHeap.h create mode 100644 src/heap/tst/HybridFileHeapTest.cpp diff --git a/src/client/src/Client.c b/src/client/src/Client.c index fb1cb40e0..ba57bc7ff 100644 --- a/src/client/src/Client.c +++ b/src/client/src/Client.c @@ -187,6 +187,7 @@ STATUS createKinesisVideoClient(PDeviceInfo pDeviceInfo, PClientCallbacks pClien CHK_STATUS(heapInitialize(pKinesisVideoClient->deviceInfo.storageInfo.storageSize, pKinesisVideoClient->deviceInfo.storageInfo.spillRatio, heapFlags, + pKinesisVideoClient->deviceInfo.storageInfo.rootDirectory, &pKinesisVideoClient->pHeap)); // Using content store allocator if needed diff --git a/src/client/src/Stream.c b/src/client/src/Stream.c index 9133e0531..cb2b27b2e 100644 --- a/src/client/src/Stream.c +++ b/src/client/src/Stream.c @@ -742,7 +742,7 @@ STATUS putFrame(PKinesisVideoStream pKinesisVideoStream, PFrame pFrame) UINT64 remainingSize = 0, remainingDuration = 0, thresholdPercent = 0, duration = 0, viewByteSize = 0, allocSize = 0; PBYTE pAlloc = NULL; UINT32 trackIndex, packagedSize = 0, packagedMetadataSize = 0, overallSize = 0, - itemFlags = ITEM_FLAG_NONE, clusterOverhead; + itemFlags = ITEM_FLAG_NONE; BOOL streamLocked = FALSE, clientLocked = FALSE, freeOnError = TRUE; EncodedFrameInfo encodedFrameInfo; MKV_STREAM_STATE generatorState = MKV_STATE_START_BLOCK; @@ -2061,7 +2061,7 @@ STATUS resetCurrentViewItemStreamStart(PKinesisVideoStream pKinesisVideoStream) STATUS retStatus = STATUS_SUCCESS; PViewItem pViewItem = NULL; BOOL streamLocked = FALSE, clientLocked = FALSE; - UINT32 clusterHeaderSize, packagedSize, overallSize, dataOffset; + UINT32 packagedSize, overallSize, dataOffset; UINT64 allocSize; PBYTE pFrame = NULL; PKinesisVideoClient pKinesisVideoClient = NULL; @@ -2329,7 +2329,7 @@ VOID deleteStreamUploadInfo(PKinesisVideoStream pKinesisVideoStream, PUploadHand if (currentTime >= pUploadHandleInfo->createTime) { UINT64 uptime = currentTime - pUploadHandleInfo->createTime; - pKinesisVideoStream->diagnostics.avgSessionDuration = EMA_ACCUMULATOR_GET_NEXT(pKinesisVideoStream->diagnostics.avgSessionDuration, uptime); + pKinesisVideoStream->diagnostics.avgSessionDuration = (UINT64) EMA_ACCUMULATOR_GET_NEXT(pKinesisVideoStream->diagnostics.avgSessionDuration, uptime); } MEMFREE(pUploadHandleInfo); diff --git a/src/client/src/StreamEvent.c b/src/client/src/StreamEvent.c index 6079e9f13..0c0cd2847 100644 --- a/src/client/src/StreamEvent.c +++ b/src/client/src/StreamEvent.c @@ -966,9 +966,9 @@ STATUS calculateCallLatency(PKinesisVideoStream pKinesisVideoStream, BOOL cplApi // Exponential mean averaging if (cplApiCall) { - pKinesisVideoStream->diagnostics.cplApiCallLatency = EMA_ACCUMULATOR_GET_NEXT(pKinesisVideoStream->diagnostics.cplApiCallLatency, latency); + pKinesisVideoStream->diagnostics.cplApiCallLatency = (UINT64) EMA_ACCUMULATOR_GET_NEXT(pKinesisVideoStream->diagnostics.cplApiCallLatency, latency); } else { - pKinesisVideoStream->diagnostics.dataApiCallLatency = EMA_ACCUMULATOR_GET_NEXT(pKinesisVideoStream->diagnostics.dataApiCallLatency, latency); + pKinesisVideoStream->diagnostics.dataApiCallLatency = (UINT64) EMA_ACCUMULATOR_GET_NEXT(pKinesisVideoStream->diagnostics.dataApiCallLatency, latency); } CleanUp: diff --git a/src/common/include/com/amazonaws/kinesis/video/common/CommonDefs.h b/src/common/include/com/amazonaws/kinesis/video/common/CommonDefs.h index 8348e0602..0dfbc98ff 100644 --- a/src/common/include/com/amazonaws/kinesis/video/common/CommonDefs.h +++ b/src/common/include/com/amazonaws/kinesis/video/common/CommonDefs.h @@ -492,7 +492,11 @@ typedef CID* PCID; #include #endif -#if defined _WIN32 || defined _WIN64 || defined __CYGWIN__ +#if defined __WINDOWS_BUILD__ + +// Include the posix IO +#include +#include #include "dlfcn_win_stub.h" diff --git a/src/heap/include/com/amazonaws/kinesis/video/heap/Include.h b/src/heap/include/com/amazonaws/kinesis/video/heap/Include.h index 28b83ad31..e8f0d00ba 100644 --- a/src/heap/include/com/amazonaws/kinesis/video/heap/Include.h +++ b/src/heap/include/com/amazonaws/kinesis/video/heap/Include.h @@ -118,7 +118,7 @@ typedef struct /** * Error values */ -#define STATUS_HEAP_BASE 0x010000000 +#define STATUS_HEAP_BASE 0x10000000 #define STATUS_HEAP_FLAGS_ERROR STATUS_HEAP_BASE + 0x00000001 #define STATUS_HEAP_NOT_INITIALIZED STATUS_HEAP_BASE + 0x00000002 #define STATUS_HEAP_CORRUPTED STATUS_HEAP_BASE + 0x00000003 @@ -141,6 +141,7 @@ typedef struct #define STATUS_HEAP_VRAM_UNINIT_FAILED STATUS_HEAP_BASE + 0x00000014 #define STATUS_INVALID_ALLOCATION_SIZE STATUS_HEAP_BASE + 0x00000015 #define STATUS_HEAP_REALLOC_ERROR STATUS_HEAP_BASE + 0x00000016 +#define STATUS_HEAP_FILE_HEAP_FILE_CORRUPT STATUS_HEAP_BASE + 0x00000017 ////////////////////////////////////////////////////////////////////////// // Public functions @@ -148,7 +149,7 @@ typedef struct /** * Creates and initializes the heap */ -PUBLIC_API STATUS heapInitialize(UINT64, UINT32, UINT32, PHeap*); +PUBLIC_API STATUS heapInitialize(UINT64, UINT32, UINT32, PCHAR, PHeap*); /** * Releases the entire heap. diff --git a/src/heap/src/Common.c b/src/heap/src/Common.c index 0ff864428..2b32007f9 100644 --- a/src/heap/src/Common.c +++ b/src/heap/src/Common.c @@ -187,8 +187,8 @@ DEFINE_HEAP_SET_ALLOC_SIZE(commonHeapSetAllocSize) // Check if the larger size can spill over the heap limit if (newSize > size) { diff = newSize - size; - CHK_ERR(diff + pHeap->heapSize <= pHeap->heapLimit, STATUS_NOT_ENOUGH_MEMORY, - "Allocating %" PRIu64 " bytes failed due to heap limit", newSize); + CHK_WARN(diff + pHeap->heapSize <= pHeap->heapLimit, STATUS_NOT_ENOUGH_MEMORY, + "Allocating %" PRIu64 " bytes failed due to heap limit", newSize); // Increment the current allocations size pHeap->heapSize += diff; } else { @@ -234,8 +234,8 @@ DEFINE_HEAP_ALLOC(commonHeapAlloc) overallSize = pBaseHeap->getAllocationHeaderSizeFn() + pBaseHeap->getAllocationAlignedSizeFn(size) + pBaseHeap->getAllocationFooterSizeFn(); - CHK_ERR(overallSize + pHeap->heapSize <= pHeap->heapLimit, STATUS_NOT_ENOUGH_MEMORY, - "Allocating %" PRIu64 " bytes failed due to heap limit", size); + CHK_WARN(overallSize + pHeap->heapSize <= pHeap->heapLimit, STATUS_NOT_ENOUGH_MEMORY, + "Allocating %" PRIu64 " bytes failed due to heap limit", size); // Validate the heap CHK_STATUS(validateHeap(pHeap)); diff --git a/src/heap/src/Common.h b/src/heap/src/Common.h index ee2a0a4bf..4156be0b6 100644 --- a/src/heap/src/Common.h +++ b/src/heap/src/Common.h @@ -38,6 +38,7 @@ typedef struct union { UINT32 vramHandle; UINT32 flags; + UINT32 fileHandle; }; #ifdef HEAP_DEBUG diff --git a/src/heap/src/Heap.c b/src/heap/src/Heap.c index 383b5867b..370359f1c 100644 --- a/src/heap/src/Heap.c +++ b/src/heap/src/Heap.c @@ -33,14 +33,16 @@ STATUS heapDebugCheckAllocator(PHeap pHeap, BOOL dump) * @heapLimit - The overall size of the heap * @spillRatio - Spill ratio in percentage of direct allocation RAM vs. vRAM in the hybrid heap scenario * @behaviorFlags - Flags controlling the behavior/type of the heap + * @pRootDirectoru - Optional path to the root directory in case of the file-based heap * @ppHeap - The returned pointer to the Heap object */ -STATUS heapInitialize(UINT64 heapLimit, UINT32 spillRatio, UINT32 behaviorFlags, PHeap* ppHeap) +STATUS heapInitialize(UINT64 heapLimit, UINT32 spillRatio, UINT32 behaviorFlags, PCHAR pRootDirectory, PHeap* ppHeap) { ENTERS(); STATUS retStatus = STATUS_SUCCESS; PHeap pHeap = NULL; PHybridHeap pHybridHeap = NULL; + PHybridFileHeap pFileHeap = NULL; UINT32 heapTypeFlags = (behaviorFlags & (FLAGS_USE_AIV_HEAP | FLAGS_USE_SYSTEM_HEAP)); CHK(ppHeap != NULL, STATUS_NULL_ARG); @@ -74,6 +76,12 @@ STATUS heapInitialize(UINT64 heapLimit, UINT32 spillRatio, UINT32 behaviorFlags, // Store the hybrid heap as the returned heap object pHeap = (PHeap) pHybridHeap; + } else if ((behaviorFlags & FLAGS_USE_HYBRID_FILE_HEAP) != HEAP_FLAGS_NONE) { + DLOGI("Creating hybrid file heap with flags: 0x%08x", behaviorFlags); + CHK_STATUS(hybridFileCreateHeap(pHeap, spillRatio, pRootDirectory, &pFileHeap)); + + // Store the file hybrid heap as the returned heap object + pHeap = (PHeap) pFileHeap; } // Just in case - validate the final heap object @@ -92,7 +100,7 @@ STATUS heapInitialize(UINT64 heapLimit, UINT32 spillRatio, UINT32 behaviorFlags, // Clean up if we failed if (STATUS_FAILED(retStatus)) { DLOGE("Failed to initialize native heap."); - // The call is indempotent anyway + // The call is idempotent anyway heapRelease(pHeap); } diff --git a/src/heap/src/HybridFileHeap.c b/src/heap/src/HybridFileHeap.c new file mode 100644 index 000000000..1ee02f2ad --- /dev/null +++ b/src/heap/src/HybridFileHeap.c @@ -0,0 +1,598 @@ +/** + * Implementation of a heap based on Hybrid file-based heap + */ + +#define LOG_CLASS "HybridFileHeap" +#include "Include_i.h" + +#ifdef HEAP_DEBUG + ALLOCATION_HEADER gFileHeader = {0, FILE_ALLOCATION_TYPE, 0, ALLOCATION_HEADER_MAGIC}; +#else + ALLOCATION_HEADER gFileHeader = {0, FILE_ALLOCATION_TYPE, 0}; +#define FILE_ALLOCATION_FOOTER_SIZE 0 +#endif + +// No footer for the file allocations +ALLOCATION_FOOTER gFileFooter = {0}; + +#define FILE_ALLOCATION_HEADER_SIZE SIZEOF(gFileHeader) + +STATUS hybridFileCreateHeap(PHeap pHeap, UINT32 spillRatio, PCHAR pRootDirectory, PHybridFileHeap* ppHybridHeap) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = NULL; + PBaseHeap pBaseHeap = NULL; + BOOL exists; + + CHK(pHeap != NULL, STATUS_NULL_ARG); + CHK(spillRatio <= 100, STATUS_INVALID_ARG); + + DLOGS("Creating hybrid file heap with spill ratio %d", spillRatio); + + CHK_STATUS(commonHeapCreate((PHeap*) &pHybridHeap, SIZEOF(HybridFileHeap))); + + // Set the values + pHybridHeap->pMemHeap = (PBaseHeap) pHeap; + pHybridHeap->spillRatio = (DOUBLE)spillRatio / 100; + + // IMPORTANT: We should start from a non-zero handle num to avoid a collision with the invalid handle value + pHybridHeap->handleNum = FILE_HEAP_STARTING_FILE_INDEX; + + // Set the root path. Use default if not specified + if (pRootDirectory == NULL || pRootDirectory[0] == '\0') { + MEMCPY(pHybridHeap->rootDirectory, FILE_HEAP_DEFAULT_ROOT_DIRECTORY, SIZEOF(FILE_HEAP_DEFAULT_ROOT_DIRECTORY)); + } else { + CHK(STRNLEN(pRootDirectory, MAX_PATH_LEN + 1) <= FILE_HEAP_MAX_ROOT_DIR_LEN, STATUS_INVALID_ARG_LEN); + STRCPY(pHybridHeap->rootDirectory, pRootDirectory); + } + + // Check if the directory exists + CHK_STATUS(fileExists(pHybridHeap->rootDirectory, &exists)); + CHK(exists, STATUS_NOT_FOUND); + + // Return hybrid heap + *ppHybridHeap = pHybridHeap; + + // Set the function pointers + pBaseHeap = (PBaseHeap) pHybridHeap; + pBaseHeap->heapInitializeFn = hybridFileHeapInit; + pBaseHeap->heapReleaseFn = hybridFileHeapRelease; + pBaseHeap->heapGetSizeFn = commonHeapGetSize; // Use the common heap functionality + pBaseHeap->heapAllocFn = hybridFileHeapAlloc; + pBaseHeap->heapFreeFn = hybridFileHeapFree; + pBaseHeap->heapGetAllocSizeFn = hybridFileHeapGetAllocSize; + pBaseHeap->heapSetAllocSizeFn = hybridFileHeapSetAllocSize; + pBaseHeap->heapMapFn = hybridFileHeapMap; + pBaseHeap->heapUnmapFn = hybridFileHeapUnmap; + pBaseHeap->heapDebugCheckAllocatorFn = hybridFileHeapDebugCheckAllocator; + pBaseHeap->getAllocationSizeFn = hybridFileGetAllocationSize; + pBaseHeap->getAllocationHeaderSizeFn = hybridFileGetAllocationHeaderSize; + pBaseHeap->getAllocationFooterSizeFn = hybridFileGetAllocationFooterSize; + pBaseHeap->getAllocationAlignedSizeFn = hybridFileGetAllocationAlignedSize; + pBaseHeap->getHeapLimitsFn = hybridFileGetHeapLimits; + +CleanUp: + + if (STATUS_FAILED(retStatus) && pHybridHeap != NULL) { + // Set the base heap to NULL to avoid releasing again in the caller common function + pHybridHeap->pMemHeap = NULL; + + hybridFileHeapRelease((PHeap) pHybridHeap); + } + + LEAVES(); + return retStatus; +} + +/** + * Debug print analytics information + */ +DEFINE_HEAP_CHK(hybridFileHeapDebugCheckAllocator) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + + // Try the contained heap first + CHK_STATUS(pHybridHeap->pMemHeap->heapDebugCheckAllocatorFn((PHeap) pHybridHeap->pMemHeap, dump)); + + // Delegate the call directly + CHK_STATUS(commonHeapDebugCheckAllocator(pHeap, dump)); + +CleanUp: + LEAVES(); + return retStatus; +} + +/** + * Initialize the heap + */ +DEFINE_INIT_HEAP(hybridFileHeapInit) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + UINT64 memHeapLimit, fileHeapLimit; + + // Calling base "class" functionality first + CHK_STATUS(commonHeapInit(pHeap, heapLimit)); + + // Calculate the in-memory and file based heap sizes + memHeapLimit = (UINT64) (heapLimit * pHybridHeap->spillRatio); + fileHeapLimit = heapLimit - memHeapLimit; + + CHK_ERR(fileHeapLimit < MAX_LARGE_HEAP_SIZE, + STATUS_NOT_ENOUGH_MEMORY, + "Can't reserve File heap with size %" PRIu64 ". Max allowed is %" PRIu64 " bytes", + fileHeapLimit, + MAX_LARGE_HEAP_SIZE); + + // Initialize the encapsulated heap + CHK_STATUS_ERR(pHybridHeap->pMemHeap->heapInitializeFn((PHeap) pHybridHeap->pMemHeap, memHeapLimit), + STATUS_HEAP_DIRECT_MEM_INIT, + "Failed to initialize the in-memory heap with limit size %" PRIu64, + memHeapLimit); + + // Initialize the file hybrid heap + +CleanUp: + + LEAVES(); + return retStatus; +} + +/** + * Free the hybrid heap + */ +DEFINE_RELEASE_HEAP(hybridFileHeapRelease) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + STATUS memHeapStatus = STATUS_SUCCESS; + STATUS hybridHeapStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + + // The call should be idempotent + CHK (pHeap != NULL, STATUS_SUCCESS); + + // Regardless of the status (heap might be corrupted) we still want to free the memory + retStatus = commonHeapRelease(pHeap); + + // Release the direct memory heap + if (pHybridHeap->pMemHeap != NULL && STATUS_FAILED(memHeapStatus = pHybridHeap->pMemHeap->heapReleaseFn((PHeap) pHybridHeap->pMemHeap))) { + DLOGW("Failed to release in-memory heap with 0x%08x", memHeapStatus); + } + + // Remove all of the lingering files if any + if (STATUS_FAILED(hybridHeapStatus = traverseDirectory(pHybridHeap->rootDirectory, (UINT64) pHybridHeap, FALSE, removeHeapFile))) { + DLOGW("Failed to clear file heap remaining files with 0x%08x", hybridHeapStatus); + } + + // Free the allocation itself + MEMFREE(pHeap); + +CleanUp: + LEAVES(); + return retStatus | memHeapStatus | hybridHeapStatus; +} + +/** + * Allocate from the heap + */ +DEFINE_HEAP_ALLOC(hybridFileHeapAlloc) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + + // overall allocation size + UINT64 allocationSize = size + FILE_ALLOCATION_HEADER_SIZE + FILE_ALLOCATION_FOOTER_SIZE; + CHAR filePath[MAX_PATH_LEN + 1]; + ALLOCATION_HEADER allocationHeader; + ALLOCATION_HANDLE handle; + + // Call the base class for the accounting + retStatus = commonHeapAlloc(pHeap, size, pHandle); + CHK(retStatus == STATUS_NOT_ENOUGH_MEMORY || retStatus == STATUS_SUCCESS, retStatus); + if (retStatus == STATUS_NOT_ENOUGH_MEMORY) { + // If we are out of memory then we don't need to return a failure - just + // Early return with success + CHK(FALSE, STATUS_SUCCESS); + } + + DLOGS("Trying to allocate from direct memory heap."); + // Try to allocate from the memory first. pHandle is not NULL if we have passed the base checks + // Check for the pHandle not being null for successful allocation + CHK_STATUS(pHybridHeap->pMemHeap->heapAllocFn((PHeap) pHybridHeap->pMemHeap, size, pHandle)); + + // See if we succeeded allocating the buffer + if (*pHandle != INVALID_ALLOCATION_HANDLE_VALUE) { + // We have successfully allocated memory from the in-memory heap + DLOGS("Successfully allocated from direct memory."); + + // Early exit with success + CHK(FALSE, STATUS_SUCCESS); + } + + DLOGS("Allocating from File heap"); + + // Try to allocate from file storage + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, pHybridHeap->handleNum); + + // Create a file with the overall size + CHK_STATUS(createFile(filePath, allocationSize)); + + // Return the file handle number and increment it + handle = FROM_FILE_HANDLE(pHybridHeap->handleNum); + + // map, write, unmap + // Set the header - no footer for file heap + allocationHeader = gFileHeader; + allocationHeader.size = size; + allocationHeader.fileHandle = pHybridHeap->handleNum; + CHK_STATUS(updateFile(filePath, TRUE, (PBYTE) &allocationHeader, 0, FILE_ALLOCATION_HEADER_SIZE)); + + // Setting the return handle + *pHandle = handle; + + // Increment the handle number + pHybridHeap->handleNum++; + +CleanUp: + + LEAVES(); + return retStatus; +} + +/** + * Free the allocation + */ +DEFINE_HEAP_FREE(hybridFileHeapFree) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + CHAR filePath[MAX_PATH_LEN + 1]; + UINT32 fileHandle; + INT32 retCode; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + + // Calling the base first - this should do the accounting + CHK_STATUS(commonHeapFree(pHeap, handle)); + + // If this is a direct allocation then we handle that separately + if (IS_DIRECT_ALLOCATION_HANDLE(handle)) { + DLOGS("Direct allocation"); + CHK_STATUS(pHybridHeap->pMemHeap->heapFreeFn((PHeap) pHybridHeap->pMemHeap, handle)); + + // Exit on success + CHK(FALSE, STATUS_SUCCESS); + } + + // In case it's a direct allocation handle use the encapsulated direct memory heap + DLOGS("Indirect allocation"); + // Convert the handle and create the file path + fileHandle = TO_FILE_HANDLE(handle); + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, fileHandle); + + retCode = FREMOVE(filePath); + + if (retCode != 0) { + switch (errno) { + case EACCES: + retStatus = STATUS_DIRECTORY_ACCESS_DENIED; + break; + + case ENOENT: + retStatus = STATUS_DIRECTORY_MISSING_PATH; + break; + + default: + retStatus = STATUS_REMOVE_FILE_FAILED; + } + } + +CleanUp: + LEAVES(); + return retStatus; +} + +/** + * Gets the allocation size + */ +DEFINE_HEAP_GET_ALLOC_SIZE(hybridFileHeapGetAllocSize) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + ALLOCATION_HEADER allocationHeader; + CHAR filePath[MAX_PATH_LEN + 1]; + UINT32 fileHandle; + + // Call the base class to ensure the params are ok and set the default ret values + CHK_STATUS(commonHeapGetAllocSize(pHeap, handle, pAllocSize)); + + // In case it's a direct allocation handle use the encapsulated direct memory heap + if (IS_DIRECT_ALLOCATION_HANDLE(handle)) { + DLOGS("Direct allocation 0x%016" PRIx64, handle); + CHK_STATUS(pHybridHeap->pMemHeap->heapGetAllocSizeFn((PHeap) pHybridHeap->pMemHeap, handle, pAllocSize)); + + // Exit on success + CHK(FALSE, STATUS_SUCCESS); + } + + // Convert the handle + fileHandle = TO_FILE_HANDLE(handle); + DLOGS("File heap allocation. Handle 0x%016" PRIx64 " File handle 0x%08x", handle, fileHandle); + + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, fileHandle); + CHK_STATUS(readFileSegment(filePath, TRUE, (PBYTE) &allocationHeader, 0, FILE_ALLOCATION_HEADER_SIZE)); + + // Set the values and return + *pAllocSize = allocationHeader.size; + +CleanUp: + LEAVES(); + return retStatus; +} + +/** + * Sets the allocation size + */ +DEFINE_HEAP_SET_ALLOC_SIZE(hybridFileHeapSetAllocSize) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + ALLOCATION_HANDLE handle; + ALLOCATION_HEADER allocationHeader; + CHAR filePath[MAX_PATH_LEN + 1]; + UINT32 fileHandle; + UINT64 overallSize; + + // Call the base class to ensure the params are ok and set the default ret values + CHK_STATUS(commonHeapSetAllocSize(pHeap, pHandle, size, newSize)); + + // overall allocation size + overallSize = FILE_ALLOCATION_HEADER_SIZE + newSize + FILE_ALLOCATION_FOOTER_SIZE; + + handle = *pHandle; + // In case it's a direct allocation handle use the encapsulated direct memory heap + if (IS_DIRECT_ALLOCATION_HANDLE(handle)) { + DLOGS("Direct allocation 0x%016" PRIx64, handle); + retStatus = pHybridHeap->pMemHeap->heapSetAllocSizeFn((PHeap) pHybridHeap->pMemHeap, pHandle, size, newSize); + CHK(retStatus == STATUS_SUCCESS || retStatus == STATUS_HEAP_REALLOC_ERROR, retStatus); + + // Exit on success + CHK(!STATUS_SUCCEEDED(retStatus), STATUS_SUCCESS); + + // Reset the status + retStatus = STATUS_SUCCESS; + } + + // Perform in-place file size change + fileHandle = TO_FILE_HANDLE(handle); + DLOGS("Sets new allocation size %\" PRIu64 \" for handle 0x%016" + PRIx64, newSize, handle); + + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, fileHandle); + + // Set the file size + CHK_STATUS(setFileLength(filePath, overallSize)); + + // Write the new size + allocationHeader = gFileHeader; + allocationHeader.size = newSize; + + CHK_STATUS(updateFile(filePath, TRUE, (PBYTE) &allocationHeader, 0, FILE_ALLOCATION_HEADER_SIZE)); + +CleanUp: + + LEAVES(); + return retStatus; +} + +/** + * Map the allocation. + * IMPORTANT: We will determine whether this is direct allocation by checking the last 2 bits being 0. + * This works because all our allocators are at least 8 byte aligned so the handle will have it's + * least significant two bits set as 0. The File heap handle will have it set to 1s. + * + * NOTE: In order to map a particular allocation, we will allocate from the common heap for now. + * A more advanced implementation that requires a tight control over the memory and allocation might + * choose to reserve a certain amount of memory from the direct RAM heap and allocate from there. + */ +DEFINE_HEAP_MAP(hybridFileHeapMap) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + CHAR filePath[MAX_PATH_LEN + 1]; + UINT32 fileHandle; + PALLOCATION_HEADER pAllocation = NULL; + UINT64 fileLength; + + // Call the base class to ensure the params are ok and set the default ret values + CHK_STATUS(commonHeapMap(pHeap, handle, ppAllocation, pSize)); + + // In case it's a direct allocation handle use the encapsulated direct memory heap + if (IS_DIRECT_ALLOCATION_HANDLE(handle)) { + DLOGS("Direct allocation 0x%016" PRIx64, handle); + CHK_STATUS(pHybridHeap->pMemHeap->heapMapFn((PHeap) pHybridHeap->pMemHeap, handle, ppAllocation, pSize)); + + // Exit on success + CHK(FALSE, STATUS_SUCCESS); + } + + // Convert the handle + fileHandle = TO_FILE_HANDLE(handle); + DLOGS("File heap allocation. Handle 0x%016" PRIx64 " File handle 0x%08x", handle, fileHandle); + + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, fileHandle); + + // Get the file size, allocate and read the entire file into memory + CHK_STATUS(getFileLength(filePath, &fileLength)); + + CHK(NULL != (pAllocation = (PALLOCATION_HEADER) MEMALLOC(fileLength)), STATUS_NOT_ENOUGH_MEMORY); + + CHK_STATUS(readFile(filePath, TRUE, (PBYTE) pAllocation, &fileLength)); + CHK(pAllocation->type == FILE_ALLOCATION_TYPE && pAllocation->size == fileLength - FILE_ALLOCATION_HEADER_SIZE, STATUS_HEAP_FILE_HEAP_FILE_CORRUPT); + + // Set the values and return + *ppAllocation = pAllocation + 1; + *pSize = pAllocation->size; + +CleanUp: + + if (STATUS_FAILED(retStatus)) { + SAFE_MEMFREE(pAllocation); + } + + LEAVES(); + return retStatus; +} + +/** + * Un-Maps the allocation handle. + */ +DEFINE_HEAP_UNMAP(hybridFileHeapUnmap) +{ + ENTERS(); + STATUS retStatus = STATUS_SUCCESS; + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + PALLOCATION_HEADER pHeader = (PALLOCATION_HEADER)pAllocation - 1; + CHAR filePath[MAX_PATH_LEN + 1]; + + // Call the base class to ensure the params are ok + CHK_STATUS(commonHeapUnmap(pHeap, pAllocation)); + + // Check if this is a direct allocation by examining the type + if (FILE_ALLOCATION_TYPE != pHeader->type) { + DLOGS("Direct allocation"); + + // This is a direct allocation - call the encapsulated heap + CHK_STATUS(pHybridHeap->pMemHeap->heapUnmapFn((PHeap) pHybridHeap->pMemHeap, pAllocation)); + + // Exit on success + CHK(FALSE, STATUS_SUCCESS); + } + + DLOGS("Indirect allocation"); + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, pHeader->fileHandle); + + // Un-maping in this case is simply writing the content into the file storage and releasing the mapped memory + CHK_STATUS(writeFile(filePath, TRUE, FALSE, (PBYTE) pHeader, pHeader->size + FILE_ALLOCATION_HEADER_SIZE)); + + SAFE_MEMFREE(pHeader); + +CleanUp: + LEAVES(); + return retStatus; +} + +DEFINE_HEADER_SIZE(hybridFileGetAllocationHeaderSize) +{ + return FILE_ALLOCATION_HEADER_SIZE; +} + +DEFINE_FOOTER_SIZE(hybridFileGetAllocationFooterSize) +{ + return FILE_ALLOCATION_FOOTER_SIZE; +} + +DEFINE_ALIGNED_SIZE(hybridFileGetAllocationAlignedSize) +{ + return size; +} + +DEFINE_ALLOC_SIZE(hybridFileGetAllocationSize) +{ + PHybridFileHeap pHybridHeap = (PHybridFileHeap) pHeap; + CHAR filePath[MAX_PATH_LEN + 1]; + UINT32 fileHandle; + ALLOCATION_HEADER allocationHeader; + UINT64 memSizes, fileSizes, memHeapAllocationSize; + + CHECK_EXT(pHeap != NULL, "Internal error with file heap being null"); + + // Check if this is a direct allocation + if (IS_DIRECT_ALLOCATION_HANDLE(handle)) { + // Get the allocation header and footer in order to compensate the accounting for file header and footer. + memSizes = pHybridHeap->pMemHeap->getAllocationHeaderSizeFn() + pHybridHeap->pMemHeap->getAllocationFooterSizeFn(); + fileSizes = hybridFileGetAllocationHeaderSize() + hybridFileGetAllocationFooterSize(); + memHeapAllocationSize = pHybridHeap->pMemHeap->getAllocationSizeFn((PHeap) pHybridHeap->pMemHeap, handle); + return memHeapAllocationSize - memSizes + fileSizes; + } + + // In case of File allocation we need to read the header and get the size + fileHandle = TO_FILE_HANDLE(handle); + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, pHybridHeap->rootDirectory, FPATHSEPARATOR, fileHandle); + + // Read the header to get the size info so we can allocate enough storage + if (STATUS_FAILED(readFileSegment(filePath, TRUE, (PBYTE) &allocationHeader, 0, FILE_ALLOCATION_HEADER_SIZE))) { + DLOGW("Failed to read the allocation header from file handle %lu", fileHandle); + allocationHeader.size = 0; + } + +#ifdef HEAP_DEBUG + // Check the allocation 'guard band' in debug mode + if (0 != MEMCMP(allocationHeader.magic, ALLOCATION_HEADER_MAGIC, SIZEOF(ALLOCATION_HEADER_MAGIC))) { + DLOGE("Invalid header for file allocation handle %lu", fileHandle); + return INVALID_ALLOCATION_VALUE; + } + + // We don't use the footer for file allocation for perf purpose + + // Check the type + if (FILE_ALLOCATION_TYPE != allocationHeader.type) { + DLOGE("Invalid allocation type 0x%08x for file handle %lu", allocationHeader.type, fileHandle); + return INVALID_ALLOCATION_VALUE; + } +#endif + + return FILE_ALLOCATION_HEADER_SIZE + allocationHeader.size + FILE_ALLOCATION_FOOTER_SIZE; +} + +DEFINE_HEAP_LIMITS(hybridFileGetHeapLimits) +{ + *pMinHeapSize = MIN_HEAP_SIZE; + *pMaxHeapSize = MAX_LARGE_HEAP_SIZE; +} + +STATUS removeHeapFile(UINT64 callerData, DIR_ENTRY_TYPES entryType, PCHAR path, PCHAR name) +{ + STATUS retStatus = STATUS_SUCCESS; + INT32 retCode; + SIZE_T strLen; + + UNUSED_PARAM(callerData); + + // Early return on non-file types + CHK(entryType == DIR_ENTRY_TYPE_FILE, retStatus); + + // Check if the file ends with the extension for the hybrid file heap + strLen = STRLEN(name); + CHK(strLen >= ARRAY_SIZE(FILE_HEAP_FILE_EXTENSION) && + (0 == STRNCMP(FILE_HEAP_FILE_EXTENSION, name + strLen - ARRAY_SIZE(FILE_HEAP_FILE_EXTENSION) + 1, ARRAY_SIZE(FILE_HEAP_FILE_EXTENSION))), retStatus); + + DLOGS("Removing heap file %s", path); + retCode = FREMOVE(path); + + if (retCode != 0) { + switch (errno) { + case EACCES: + retStatus = STATUS_DIRECTORY_ACCESS_DENIED; + break; + + case ENOENT: + retStatus = STATUS_DIRECTORY_MISSING_PATH; + break; + + default: + retStatus = STATUS_REMOVE_FILE_FAILED; + } + } + +CleanUp: + return retStatus; +} diff --git a/src/heap/src/HybridFileHeap.h b/src/heap/src/HybridFileHeap.h new file mode 100644 index 000000000..19106d8a9 --- /dev/null +++ b/src/heap/src/HybridFileHeap.h @@ -0,0 +1,131 @@ +/** + * Hybrid file heap class + */ + +#ifndef __HYBRID_FILE_HEAP_H__ +#define __HYBRID_FILE_HEAP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define FILE_ALLOCATION_TYPE 4 + +// Default location of the root directory for the files +#define FILE_HEAP_DEFAULT_ROOT_DIRECTORY "." + +// Extension for the heap files +#define FILE_HEAP_FILE_EXTENSION ".hfh" + +// Starting index for the file heap files +#define FILE_HEAP_STARTING_FILE_INDEX 1 + +// Define the max root directory length accounting for the max file size of 10, a separator and the file extension +#define FILE_HEAP_MAX_ROOT_DIR_LEN (MAX_PATH_LEN - 10 - SIZEOF(FILE_HEAP_FILE_EXTENSION) - 1) + +/** + * We will encode a sequential number as the handle in upper 32 bits + */ +#define TO_FILE_HANDLE(h) ((UINT32)((UINT64)(h) >> 32)) +#define FROM_FILE_HANDLE(h) (ALLOCATION_HANDLE)(((UINT64)(h) << 32) | ALIGNMENT_BITS) + +/** + * Hybrid heap struct + */ +typedef struct +{ + /** + * Base Heap struct encapsulation + */ + BaseHeap heap; + + /** + * Spill ratio - this will indicate the ratio of the memory to use from main memory and file + */ + DOUBLE spillRatio; + + /** + * Root directory to store the files + */ + CHAR rootDirectory[MAX_PATH_LEN + 1]; + + /** + * Will keep the ever increasing number which will be used as a handle. OK to wrap + */ + UINT32 handleNum; + + /** + * The direct memory allocation based heap + */ + PBaseHeap pMemHeap; +} HybridFileHeap, *PHybridFileHeap; + +/** + * Hybrid heap internal functions + */ +STATUS hybridFileCreateHeap(PHeap, UINT32, PCHAR, PHybridFileHeap*); + +/** + * Allocate a buffer from the heap + */ +DEFINE_HEAP_ALLOC(hybridFileHeapAlloc); + +/** + * Free the previously allocated buffer handle + */ +DEFINE_HEAP_FREE(hybridFileHeapFree); + +/** + * Gets the allocation size + */ +DEFINE_HEAP_GET_ALLOC_SIZE(hybridFileHeapGetAllocSize); + +/** + * Sets the allocation size + */ +DEFINE_HEAP_SET_ALLOC_SIZE(hybridFileHeapSetAllocSize); + +/** + * Maps the allocation handle to memory. This is needed for in-direct allocation in file system + */ +DEFINE_HEAP_MAP(hybridFileHeapMap); + +/** + * Un-maps the previously mapped buffer + */ +DEFINE_HEAP_UNMAP(hybridFileHeapUnmap); + +/** + * Release the entire heap + */ +DEFINE_RELEASE_HEAP(hybridFileHeapRelease); + +/** + * Initialize the heap with a given limit + */ +DEFINE_INIT_HEAP(hybridFileHeapInit); + +/** + * Debug/check heap + */ +DEFINE_HEAP_CHK(hybridFileHeapDebugCheckAllocator); + +/** + * Dealing with the allocation sizes + */ +DEFINE_HEADER_SIZE(hybridFileGetAllocationHeaderSize); +DEFINE_FOOTER_SIZE(hybridFileGetAllocationFooterSize); +DEFINE_ALIGNED_SIZE(hybridFileGetAllocationAlignedSize); +DEFINE_ALLOC_SIZE(hybridFileGetAllocationSize); +DEFINE_HEAP_LIMITS(hybridFileGetHeapLimits); + +/** + * Auxiliary functionality + */ +STATUS removeHeapFile(UINT64, DIR_ENTRY_TYPES, PCHAR, PCHAR); + +#ifdef __cplusplus +} +#endif + +#endif // __HYBRID_FILE_HEAP_H__ diff --git a/src/heap/src/HybridHeap.c b/src/heap/src/HybridHeap.c index a4a111797..c2c5499f9 100644 --- a/src/heap/src/HybridHeap.c +++ b/src/heap/src/HybridHeap.c @@ -117,8 +117,20 @@ STATUS hybridCreateHeap(PHeap pHeap, UINT32 spillRatio, UINT32 behaviorFlags, PH pBaseHeap->getHeapLimitsFn = hybridGetHeapLimits; CleanUp: - if (STATUS_FAILED(retStatus) && handle != NULL) { - DLCLOSE(handle); + 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(); @@ -153,10 +165,7 @@ DEFINE_INIT_HEAP(hybridHeapInit) ENTERS(); STATUS retStatus = STATUS_SUCCESS; PHybridHeap pHybridHeap = (PHybridHeap) pHeap; - UINT32 ret; - UINT32 memHeapLimit; - UINT32 vramHeapLimit; - UINT32 maxVramSize; + UINT32 ret, memHeapLimit, vramHeapLimit, maxVramSize; // Delegate the call directly CHK_STATUS(commonHeapInit(pHeap, heapLimit)); @@ -212,7 +221,7 @@ DEFINE_RELEASE_HEAP(hybridHeapRelease) retStatus = commonHeapRelease(pHeap); // Release the direct memory heap - if (STATUS_SUCCESS != (memHeapStatus = pHybridHeap->pMemHeap->heapReleaseFn((PHeap) pHybridHeap->pMemHeap))) { + if (pHybridHeap->pMemHeap != NULL && STATUS_SUCCESS != (memHeapStatus = pHybridHeap->pMemHeap->heapReleaseFn((PHeap) pHybridHeap->pMemHeap))) { DLOGW("Failed to release in-memory heap with 0x%08x", memHeapStatus); } @@ -590,13 +599,16 @@ DEFINE_ALLOC_SIZE(hybridGetAllocationSize) PHybridHeap pHybridHeap = (PHybridHeap) pHeap; UINT32 vramHandle; PALLOCATION_HEADER pAllocation; + UINT64 memSizes, vramSizes, memHeapAllocationSize; + + CHECK_EXT(pHeap != NULL, "Internal error with VRAM heap being null"); // Check if this is a direct allocation if (IS_DIRECT_ALLOCATION_HANDLE(handle)) { // Get the allocation header and footer in order to compensate the accounting for vram header and footer. - UINT64 memSizes = pHybridHeap->pMemHeap->getAllocationHeaderSizeFn() + pHybridHeap->pMemHeap->getAllocationFooterSizeFn(); - UINT64 vramSizes = hybridGetAllocationHeaderSize() + hybridGetAllocationFooterSize(); - UINT64 memHeapAllocationSize = pHybridHeap->pMemHeap->getAllocationSizeFn((PHeap) pHybridHeap->pMemHeap, handle); + memSizes = pHybridHeap->pMemHeap->getAllocationHeaderSizeFn() + pHybridHeap->pMemHeap->getAllocationFooterSizeFn(); + vramSizes = hybridGetAllocationHeaderSize() + hybridGetAllocationFooterSize(); + memHeapAllocationSize = pHybridHeap->pMemHeap->getAllocationSizeFn((PHeap) pHybridHeap->pMemHeap, handle); return memHeapAllocationSize - memSizes + vramSizes; } diff --git a/src/heap/src/Include_i.h b/src/heap/src/Include_i.h index ec5450e52..af0a5c01e 100644 --- a/src/heap/src/Include_i.h +++ b/src/heap/src/Include_i.h @@ -154,6 +154,7 @@ typedef struct #include "SystemHeap.h" #include "AivHeap.h" #include "HybridHeap.h" +#include "HybridFileHeap.h" #ifdef __cplusplus } diff --git a/src/heap/tst/HeapApiFunctionalityTest.cpp b/src/heap/tst/HeapApiFunctionalityTest.cpp index 346b95eb0..c74950e0e 100644 --- a/src/heap/tst/HeapApiFunctionalityTest.cpp +++ b/src/heap/tst/HeapApiFunctionalityTest.cpp @@ -285,7 +285,7 @@ TEST_F(HeapApiFunctionalityTest, GetHeapSizeAndGetAllocSize) ALLOCATION_HANDLE handles[10]; // AIV heap - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); for (i = 0; i < 10; i++) { // Allocate a block block EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); @@ -299,7 +299,7 @@ TEST_F(HeapApiFunctionalityTest, GetHeapSizeAndGetAllocSize) EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); // System heap - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); for (i = 0; i < 10; i++) { // Allocate a block block EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); @@ -318,7 +318,7 @@ TEST_F(HeapApiFunctionalityTest, GetHeapSizeAndGetAllocSize) EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); // AIV hybrid heap - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE * 2 + 100000, 50, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE * 2 + 100000, 50, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, NULL, &pHeap)); for (i = 0; i < 10; i++) { // Allocate a block block EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); @@ -330,7 +330,7 @@ TEST_F(HeapApiFunctionalityTest, GetHeapSizeAndGetAllocSize) EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); // System hybrid heap - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE * 2 + 100000, 50, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE * 2 + 100000, 50, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, NULL, &pHeap)); for (i = 0; i < 10; i++) { // Allocate a block block EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); @@ -352,10 +352,10 @@ TEST_F(HeapApiFunctionalityTest, SingleLargeAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); singleLargeAlloc(pHeap); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); singleLargeAlloc(pHeap); } @@ -363,10 +363,10 @@ TEST_F(HeapApiFunctionalityTest, MultipleLargeAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); multipleLargeAlloc(pHeap); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); multipleLargeAlloc(pHeap); } @@ -374,7 +374,7 @@ TEST_F(HeapApiFunctionalityTest, DefragmentationAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); defragmentationAlloc(pHeap); } @@ -382,7 +382,7 @@ TEST_F(HeapApiFunctionalityTest, SingleByteAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); singleByteAlloc(pHeap); } @@ -390,7 +390,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapMinBlockFitAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); minBlockFitAlloc(pHeap); } @@ -398,7 +398,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapBlockCoallesceAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); blockCoalesceAlloc(pHeap); } @@ -406,7 +406,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapMinBlockFitResize) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); minBlockFitAllocResize(pHeap); } @@ -414,7 +414,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapUnalignedHeapLimit) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE + 1, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE + 1, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); #ifdef ALIGNED_MEMORY_MODEL EXPECT_EQ(MIN_HEAP_SIZE + 8, pHeap->heapLimit); #else @@ -434,7 +434,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapResizeEdgeCases) UINT64 setSize, iter; PVOID pAlloc; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); // Set to default zeroHandleArray(handles, NUM_ITERATIONS); @@ -548,7 +548,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapResizeUpDownBottomUp) UINT64 setSize; PVOID pAlloc; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); // Set to default zeroHandleArray(handles, NUM_ITERATIONS); @@ -618,7 +618,7 @@ TEST_F(HeapApiFunctionalityTest, AivHeapResizeUpDownTopDown) UINT64 setSize; PVOID pAlloc; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); // Set to default zeroHandleArray(handles, NUM_ITERATIONS); @@ -682,9 +682,9 @@ TEST_F(HeapApiFunctionalityTest, MultipleMapUnmapByteAlloc) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); multipleMapUnmapByteAlloc(pHeap); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); multipleMapUnmapByteAlloc(pHeap); } diff --git a/src/heap/tst/HeapApiTest.cpp b/src/heap/tst/HeapApiTest.cpp index 13fe65d77..fcc6f1e4f 100644 --- a/src/heap/tst/HeapApiTest.cpp +++ b/src/heap/tst/HeapApiTest.cpp @@ -4,107 +4,155 @@ class HeapApiTest : public HeapTestBase { }; TEST_F(HeapApiTest, InvalidInputHeapInitialize_HeapPointerNull) { - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, NULL))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, NULL))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, NULL))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, NULL))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, NULL))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, + NULL))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, + 20, + FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + NULL, + NULL))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, + 20, + FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + NULL, NULL))); } TEST_F(HeapApiTest, InvalidInputHeapInitialize_MinHeapSize) { PHeap pHeap; - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_AIV_HEAP, &pHeap))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, 20, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, + &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, + 20, + FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + NULL, + &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE - 1, + 20, + FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + NULL, &pHeap))); } TEST_F(HeapApiTest, InvalidInputHeapInitialize_MaxHeapSize) { PHeap pHeap; - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_AIV_HEAP, &pHeap))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MAX_HEAP_SIZE + 1, 20, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, &pHeap))); } TEST_F(HeapApiTest, InvalidInputHeapInitialize_SpillRatio) { PHeap pHeap; - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_AIV_HEAP, &pHeap))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 101, FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, + &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, + 101, + FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + NULL, + &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, + 101, + FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + NULL, &pHeap))); } TEST_F(HeapApiTest, InvalidInputHeapInitialize_HeapTypeFlags) { PHeap pHeap; - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, HEAP_FLAGS_NONE, &pHeap))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_HYBRID_VRAM_HEAP, &pHeap))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_REOPEN_VRAM_LIBRARY, &pHeap))); - EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, HEAP_FLAGS_NONE, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_HYBRID_VRAM_HEAP, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_REOPEN_VRAM_LIBRARY, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_HYBRID_FILE_HEAP, NULL, &pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_HYBRID_FILE_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, NULL, &pHeap))); } TEST_F(HeapApiTest, IdempotentHeapRelease_NullHeapRelease) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(NULL))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(NULL))); } @@ -126,11 +174,11 @@ TEST_F(HeapApiTest, InvalidHeapDebugCheckAllocator_NullHeapDebugCheckAllocator) TEST_F(HeapApiTest, InvalidHeapAlloc_NullHeap) { PHeap pHeap; ALLOCATION_HANDLE handle; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapAlloc(NULL, 1000, &handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapAlloc(NULL, 1000, &handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); } @@ -141,7 +189,7 @@ TEST_F(HeapApiTest, InvalidHeapGetAllocSize_NullHeapHandle) { ALLOCATION_HANDLE handle; // Create and allocate heap - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapGetAllocSize(NULL, handle, &size))); @@ -161,11 +209,11 @@ TEST_F(HeapApiTest, InvalidHeapGetAllocSize_NullHeapHandle) { TEST_F(HeapApiTest, InvalidHeapAlloc_NullHandle) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapAlloc(pHeap, 1000, NULL))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapAlloc(pHeap, 1000, NULL))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); } @@ -174,11 +222,11 @@ TEST_F(HeapApiTest, InvalidHeapAlloc_ZeroAlloc) { PHeap pHeap; ALLOCATION_HANDLE handle; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapAlloc(pHeap, 0, &handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapAlloc(pHeap, 0, &handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); } @@ -187,11 +235,11 @@ TEST_F(HeapApiTest, InvalidHeapAlloc_MaxAlloc) { PHeap pHeap; ALLOCATION_HANDLE handle; - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap)); EXPECT_EQ(STATUS_INVALID_ALLOCATION_SIZE, heapAlloc(pHeap, MAX_ALLOCATION_SIZE, &handle)); EXPECT_EQ(STATUS_SUCCESS, heapRelease(pHeap)); - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap)); EXPECT_EQ(STATUS_INVALID_ALLOCATION_SIZE, heapAlloc(pHeap, MAX_ALLOCATION_SIZE, &handle)); EXPECT_EQ(STATUS_SUCCESS, heapRelease(pHeap)); } @@ -199,12 +247,12 @@ TEST_F(HeapApiTest, InvalidHeapAlloc_MaxAlloc) { TEST_F(HeapApiTest, InvalidHeapFree_NullHeap) { PHeap pHeap; ALLOCATION_HANDLE handle; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapFree(NULL, handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); EXPECT_TRUE(STATUS_FAILED(heapFree(NULL, handle))); @@ -215,12 +263,12 @@ TEST_F(HeapApiTest, InvalidHeapFree_InvalidHandle) { PHeap pHeap; ALLOCATION_HANDLE handle; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapFree(pHeap, INVALID_ALLOCATION_HANDLE_VALUE))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); EXPECT_TRUE(STATUS_FAILED(heapFree(pHeap, INVALID_ALLOCATION_HANDLE_VALUE))); @@ -233,13 +281,13 @@ TEST_F(HeapApiTest, InvalidHeapMap_NullHeap) { PVOID pAlloc; UINT64 size; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(NULL, handle, &pAlloc, &size))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(NULL, handle, &pAlloc, &size))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); @@ -252,13 +300,13 @@ TEST_F(HeapApiTest, InvalidHeapMap_InvalidHandle) { PVOID pAlloc; UINT64 size; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(pHeap, INVALID_ALLOCATION_HANDLE_VALUE, &pAlloc, &size))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(pHeap, INVALID_ALLOCATION_HANDLE_VALUE, &pAlloc, &size))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); @@ -270,13 +318,13 @@ TEST_F(HeapApiTest, InvalidHeapMap_NullAllocation) { ALLOCATION_HANDLE handle; UINT64 size; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(pHeap, handle, NULL, &size))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(pHeap, handle, NULL, &size))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); @@ -288,13 +336,13 @@ TEST_F(HeapApiTest, InvalidHeapMap_NullSize) { ALLOCATION_HANDLE handle; PVOID pAlloc = NULL; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(pHeap, handle, &pAlloc, NULL))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, 1000, &handle))); EXPECT_TRUE(STATUS_FAILED(heapMap(pHeap, handle, &pAlloc, NULL))); EXPECT_TRUE(STATUS_SUCCEEDED(heapFree(pHeap, handle))); @@ -305,11 +353,11 @@ TEST_F(HeapApiTest, InvalidHeapUnmap_NullHeap) { PHeap pHeap; PVOID pAlloc = (PVOID) 12345; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapUnmap(NULL, pAlloc))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapUnmap(NULL, pAlloc))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); } @@ -317,26 +365,47 @@ TEST_F(HeapApiTest, InvalidHeapUnmap_NullHeap) { TEST_F(HeapApiTest, InvalidHeapUnmap_InvalidAllocation) { PHeap pHeap; - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapUnmap(pHeap, NULL))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap))); EXPECT_TRUE(STATUS_FAILED(heapUnmap(pHeap, NULL))); EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); } +TEST_F(HeapApiTest, InvalidFileHeapCreate_InvalidParams) { + PHeap pHeap = NULL; + CHAR filePath[MAX_PATH_LEN + 2]; + + // Non-existent path + EXPECT_NE(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, (PCHAR) "/doesNotExist", &pHeap)); + + // Max path + MEMSET(filePath, 'a', ARRAY_SIZE(filePath)); + filePath[ARRAY_SIZE(filePath) - 1] = '\0'; + EXPECT_NE(STATUS_SUCCESS, heapInitialize(MIN_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, filePath, &pHeap)); + + // Max heap + EXPECT_NE(STATUS_SUCCESS, heapInitialize(MAX_LARGE_HEAP_SIZE, 20, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, NULL, &pHeap)); + + // Should be a no-op call + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); +} + TEST_F(HeapApiTest, InvalidHeapResize_InvalidValues) { PHeap pHeap; ALLOCATION_HANDLE handle, storedHandle, invalidHandle = INVALID_ALLOCATION_HANDLE_VALUE; UINT64 heapSize = MIN_HEAP_SIZE * 2 + 100000; - UINT32 heapTypes[4] = {FLAGS_USE_AIV_HEAP, + UINT32 heapTypes[] = {FLAGS_USE_AIV_HEAP, FLAGS_USE_SYSTEM_HEAP, FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP}; + FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, + FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_FILE_HEAP, + FLAGS_USE_SYSTEM_HEAP | FLAGS_USE_HYBRID_FILE_HEAP}; - for (UINT32 heapType = 0; heapType < SIZEOF(heapTypes) / SIZEOF(HEAP_BEHAVIOR_FLAGS); heapType++) { - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(heapSize, 50, heapTypes[heapType], &pHeap)); + for (UINT32 heapType = 0; heapType < ARRAY_SIZE(heapTypes); heapType++) { + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(heapSize, 50, heapTypes[heapType], NULL, &pHeap)); EXPECT_EQ(STATUS_SUCCESS, heapAlloc(pHeap, 1000, &handle)); EXPECT_NE(INVALID_ALLOCATION_HANDLE_VALUE, handle); storedHandle = handle; @@ -354,4 +423,4 @@ TEST_F(HeapApiTest, InvalidHeapResize_InvalidValues) { EXPECT_EQ(STATUS_SUCCESS, heapFree(pHeap, handle)); EXPECT_EQ(STATUS_SUCCESS, heapRelease(pHeap)); } -} \ No newline at end of file +} diff --git a/src/heap/tst/HeapPerfTest.cpp b/src/heap/tst/HeapPerfTest.cpp index 3eac31e81..1374939f8 100644 --- a/src/heap/tst/HeapPerfTest.cpp +++ b/src/heap/tst/HeapPerfTest.cpp @@ -58,7 +58,7 @@ TEST_F(HeapPerfTest, randomAllocFreeWindowedPerf) UINT32 totalIteration = 10, sleepBetweenIteration = 2 * HUNDREDS_OF_NANOS_IN_A_SECOND, successCount = 0, i = 0; for (; i < totalIteration; i++) { - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap)); time = GETTIME(); randomAllocFree(pHeap, HEAP_PERF_TEST_VIEW_ITEM_COUNT, HEAP_PERF_TEST_ITERATION_COUNT, HEAP_PERF_TEST_MIN_ALLOCATION); endTime = GETTIME(); @@ -68,7 +68,7 @@ TEST_F(HeapPerfTest, randomAllocFreeWindowedPerf) iterationDurationSystem = (DOUBLE) durationSystem / HEAP_PERF_TEST_ITERATION_COUNT; DLOGI("System Allocator perf time: %lf seconds, time per iteration: %lf nanos", (DOUBLE) durationSystem / HUNDREDS_OF_NANOS_IN_A_SECOND, iterationDurationSystem * DEFAULT_TIME_UNIT_IN_NANOS); - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap)); time = GETTIME(); randomAllocFree(pHeap, HEAP_PERF_TEST_VIEW_ITEM_COUNT, HEAP_PERF_TEST_ITERATION_COUNT, HEAP_PERF_TEST_MIN_ALLOCATION); endTime = GETTIME(); @@ -101,7 +101,7 @@ TEST_F(HeapPerfTest, randomAllocFreeMultiStreamWindowedPerf) UINT32 totalIteration = 10, sleepBetweenIteration = 2 * HUNDREDS_OF_NANOS_IN_A_SECOND, successCount = 0, i = 0; for (; i < totalIteration; i++) { - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap)); time = GETTIME(); randomAllocFree(pHeap, HEAP_PERF_TEST_MULTI_VIEW_ITEM_COUNT, HEAP_PERF_TEST_MULTI_VIEW_ITERATION_COUNT, HEAP_PERF_TEST_MULTI_VIEW_MIN_ALLOCATION); endTime = GETTIME(); @@ -111,7 +111,7 @@ TEST_F(HeapPerfTest, randomAllocFreeMultiStreamWindowedPerf) iterationDurationSystem = (DOUBLE) durationSystem / HEAP_PERF_TEST_MULTI_VIEW_ITERATION_COUNT; DLOGI("System Allocator perf time: %lf seconds, time per iteration: %lf nanos", (DOUBLE) durationSystem / HUNDREDS_OF_NANOS_IN_A_SECOND, iterationDurationSystem * DEFAULT_TIME_UNIT_IN_NANOS); - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap)); time = GETTIME(); randomAllocFree(pHeap, HEAP_PERF_TEST_MULTI_VIEW_ITEM_COUNT, HEAP_PERF_TEST_MULTI_VIEW_ITERATION_COUNT, HEAP_PERF_TEST_MULTI_VIEW_MIN_ALLOCATION); endTime = GETTIME(); @@ -144,7 +144,7 @@ TEST_F(HeapPerfTest, singleAllocFreePerf) UINT32 totalIteration = 10, sleepBetweenIteration = 2 * HUNDREDS_OF_NANOS_IN_A_SECOND, successCount = 0, i = 0; for (; i < totalIteration; i++) { - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_SYSTEM_HEAP, NULL, &pHeap)); time = GETTIME(); singleAllocFree(pHeap); endTime = GETTIME(); @@ -154,7 +154,7 @@ TEST_F(HeapPerfTest, singleAllocFreePerf) iterationDurationSystem = (DOUBLE) durationSystem / HEAP_PERF_TEST_ITERATION_COUNT; DLOGI("System Allocator perf time: %lf seconds, time per iteration: %lf nanos", (DOUBLE) durationSystem / HUNDREDS_OF_NANOS_IN_A_SECOND, iterationDurationSystem * DEFAULT_TIME_UNIT_IN_NANOS); - EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_AIV_HEAP, &pHeap)); + EXPECT_EQ(STATUS_SUCCESS, heapInitialize(HEAP_PERF_TEST_SIZE, 20, FLAGS_USE_AIV_HEAP, NULL, &pHeap)); time = GETTIME(); singleAllocFree(pHeap); endTime = GETTIME(); diff --git a/src/heap/tst/HeapTestFixture.cpp b/src/heap/tst/HeapTestFixture.cpp index 22cbbf915..7f764b647 100644 --- a/src/heap/tst/HeapTestFixture.cpp +++ b/src/heap/tst/HeapTestFixture.cpp @@ -32,6 +32,11 @@ UINT8 HeapTestBase::mScratchBuf[]; VOID HeapTestBase::SetUpInternal() { + globalDlOpen = HeapTestBase::mockDlOpen; + globalDlClose = HeapTestBase::mockDlClose; + globalDlSym = HeapTestBase::mockDlSym; + globalDlError = HeapTestBase::mockDlError; + mVramGetMax = MIN_HEAP_SIZE * 2; mVramInit = 0; mVramFree = 0; @@ -57,14 +62,6 @@ VOID HeapTestBase::SetUpInternal() mDlCloseCount = 0; } -VOID HeapTestBase::SetUpTestCase() -{ - globalDlOpen = HeapTestBase::mockDlOpen; - globalDlClose = HeapTestBase::mockDlClose; - globalDlSym = HeapTestBase::mockDlSym; - globalDlError = HeapTestBase::mockDlError; -} - VOID HeapTestBase::SetUp() { UINT32 logLevel = 0; diff --git a/src/heap/tst/HeapTestFixture.h b/src/heap/tst/HeapTestFixture.h index f62883882..4c3b599f4 100644 --- a/src/heap/tst/HeapTestFixture.h +++ b/src/heap/tst/HeapTestFixture.h @@ -12,7 +12,6 @@ class HeapTestBase : public ::testing::Test { }; protected: - static VOID SetUpTestCase(); static VOID SetUpInternal(); virtual VOID SetUp(); diff --git a/src/heap/tst/HybridFileHeapTest.cpp b/src/heap/tst/HybridFileHeapTest.cpp new file mode 100644 index 000000000..ed5dd92a2 --- /dev/null +++ b/src/heap/tst/HybridFileHeapTest.cpp @@ -0,0 +1,172 @@ +#include "HeapTestFixture.h" + +using ::testing::WithParamInterface; +using ::testing::Bool; +using ::testing::Values; +using ::testing::Combine; + +class HybridFileHeapTest : public HeapTestBase, + public WithParamInterface<::std::tuple> +{ +protected: + VOID SetUp() { + HeapTestBase::SetUp(); + + HEAP_BEHAVIOR_FLAGS primaryHeapType; + std::tie(primaryHeapType) = GetParam(); + mHeapType = primaryHeapType | FLAGS_USE_HYBRID_FILE_HEAP; + } + + UINT32 mHeapType; +}; + +TEST_P(HybridFileHeapTest, hybridFileHeapOperationsAivPrimaryHeap) +{ + const UINT32 AllocationCount = 100; + PHeap pHeap; + ALLOCATION_HANDLE handle; + ALLOCATION_HANDLE handles[AllocationCount]; + UINT32 memHeapLimit; + UINT32 fileHeapLimit; + UINT32 fileAllocSize; + UINT32 ramAllocSize; + UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; + UINT32 spillRatio = 50; + UINT32 numAlloc = AllocationCount / 2; + UINT32 i, fileHandleIndex, skip; + CHAR filePath[MAX_PATH_LEN + 1]; + BOOL exist; + UINT64 fileSize, allocSize, retAllocSize; + PVOID pAlloc; + + // Split the 50% and allocate half from ram and half from file heap + memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); + fileHeapLimit = heapSize - memHeapLimit; + fileAllocSize = fileHeapLimit / numAlloc; + ramAllocSize = memHeapLimit / numAlloc; + + // Set the invalid allocation handles + for (i = 0; i < AllocationCount; i++) { + handles[i] = INVALID_ALLOCATION_HANDLE_VALUE; + } + + // Initialize + EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, + spillRatio, + mHeapType, + NULL, + &pHeap))); + + DLOGV("Allocating from RAM"); + + // Allocate from ram - should be 1 less due to service structs + for (i = 0; i < numAlloc - 1; i++) { + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, ramAllocSize, &handle))) << "Failed allocating from direct heap with index: " << i; + EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)) << "Invalid direct allocation handle at index: " << i; + + // Store the handle for later processing + handles[i] = handle; + } + + DLOGV("Allocating from File heap"); + + // Allocate from file heap + for (i = 0, fileHandleIndex = numAlloc - 1; i < numAlloc; i++, fileHandleIndex++) { + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, fileAllocSize, &handle))) << "Failed allocating from file heap with index: " << i; + EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)) << "Invalid file allocation handle at index: " << i; + handles[fileHandleIndex] = handle; + } + + // Validate the allocations + for (i = 0; i < numAlloc; i++) { + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, FILE_HEAP_DEFAULT_ROOT_DIRECTORY, FPATHSEPARATOR, i + 1); + exist = FALSE; + EXPECT_EQ(STATUS_SUCCESS, fileExists(filePath, &exist)); + EXPECT_EQ(TRUE, exist); + EXPECT_EQ(STATUS_SUCCESS, getFileLength(filePath, &fileSize)); + EXPECT_EQ(fileAllocSize + SIZEOF(ALLOCATION_HEADER), fileSize); + } + + // Try to map, read, write, unmap, map again and verify + for (i = 0; i < AllocationCount - 1; i++) { + EXPECT_EQ(STATUS_SUCCESS, heapGetAllocSize(pHeap, handles[i], &retAllocSize)); + EXPECT_EQ(STATUS_SUCCESS, heapMap(pHeap, handles[i], &pAlloc, &allocSize)); + EXPECT_EQ(retAllocSize, allocSize); + MEMSET(pAlloc, 'a', allocSize); + EXPECT_EQ(STATUS_SUCCESS, heapUnmap(pHeap, pAlloc)); + + // Validate + EXPECT_EQ(STATUS_SUCCESS, heapMap(pHeap, handles[i], &pAlloc, &retAllocSize)); + EXPECT_EQ(allocSize, retAllocSize); + EXPECT_TRUE(MEMCHK(pAlloc, 'a', (SIZE_T) retAllocSize)); + EXPECT_EQ(STATUS_SUCCESS, heapUnmap(pHeap, pAlloc)); + } + + // Resize larger + for (i = 0; i < AllocationCount - 1; i++) { + // Increase the allocation size by 1 and validate the returned sizes + EXPECT_EQ(STATUS_SUCCESS, heapGetAllocSize(pHeap, handles[i], &retAllocSize)); + EXPECT_EQ(STATUS_SUCCESS, heapSetAllocSize(pHeap, &handles[i], retAllocSize + 1)); + EXPECT_EQ(STATUS_SUCCESS, heapGetAllocSize(pHeap, handles[i], &allocSize)); + EXPECT_EQ(retAllocSize + 1, allocSize); + + // Map the allocation and ensure the content is OK + EXPECT_EQ(STATUS_SUCCESS, heapMap(pHeap, handles[i], &pAlloc, &allocSize)); + EXPECT_EQ(retAllocSize + 1, allocSize); + EXPECT_TRUE(MEMCHK(pAlloc, 'a', (SIZE_T) retAllocSize)); + EXPECT_EQ(STATUS_SUCCESS, heapUnmap(pHeap, pAlloc)); + } + + // Resize smaller + for (i = 0; i < AllocationCount - 1; i++) { + // Reduce the allocation size by 2 and validate the returned sizes + EXPECT_EQ(STATUS_SUCCESS, heapGetAllocSize(pHeap, handles[i], &retAllocSize)); + EXPECT_EQ(STATUS_SUCCESS, heapSetAllocSize(pHeap, &handles[i], retAllocSize - 2)); + EXPECT_EQ(STATUS_SUCCESS, heapGetAllocSize(pHeap, handles[i], &allocSize)); + EXPECT_EQ(retAllocSize - 2, allocSize); + + // Map the allocation and ensure the content is OK + EXPECT_EQ(STATUS_SUCCESS, heapMap(pHeap, handles[i], &pAlloc, &allocSize)); + EXPECT_EQ(retAllocSize - 2, allocSize); + EXPECT_TRUE(MEMCHK(pAlloc, 'a', (SIZE_T) allocSize)); + EXPECT_EQ(STATUS_SUCCESS, heapUnmap(pHeap, pAlloc)); + } + + // Validate the allocations + for (i = 0; i < numAlloc; i++) { + SPRINTF(filePath, "%s%c%u" FILE_HEAP_FILE_EXTENSION, FILE_HEAP_DEFAULT_ROOT_DIRECTORY, FPATHSEPARATOR, i + 1); + exist = FALSE; + EXPECT_EQ(STATUS_SUCCESS, fileExists(filePath, &exist)); + EXPECT_EQ(TRUE, exist); + EXPECT_EQ(STATUS_SUCCESS, getFileLength(filePath, &fileSize)); + + // After the modifications, we increased the size by 1 and decreased by 2 so the diff is minus 1 + EXPECT_EQ(fileAllocSize + SIZEOF(ALLOCATION_HEADER) - 1, fileSize); + } + + // Free odd allocations in case of AIV heap and all of the allocations in case of system heap + skip = (mHeapType & FLAGS_USE_SYSTEM_HEAP) != HEAP_FLAGS_NONE ? 1 : 2; + for (i = 0; i < AllocationCount; i += skip) { + if (IS_VALID_ALLOCATION_HANDLE(handles[i])) { + EXPECT_EQ(STATUS_SUCCESS, heapFree(pHeap, handles[i])); + } + } + + // Release the heap which should free the rest of the allocations + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); +} + +TEST_P(HybridFileHeapTest, hybridFileCreateHeapMemHeapSmall) +{ + PHeap pHeap; + + // Initialize should fail as MIN_HEAP_SIZE will be smaller for the mem heap with 20% reduction + EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, + 20, + mHeapType, + NULL, + &pHeap))); +} + +INSTANTIATE_TEST_CASE_P(PermutatedHeapType, HybridFileHeapTest, + Values(FLAGS_USE_AIV_HEAP, FLAGS_USE_SYSTEM_HEAP)); diff --git a/src/heap/tst/HybridHeapTest.cpp b/src/heap/tst/HybridHeapTest.cpp index 91ea24a04..c4d78b5aa 100644 --- a/src/heap/tst/HybridHeapTest.cpp +++ b/src/heap/tst/HybridHeapTest.cpp @@ -1,11 +1,49 @@ #include "HeapTestFixture.h" -class HybridHeapTest : public HeapTestBase { +using ::testing::WithParamInterface; +using ::testing::Bool; +using ::testing::Values; +using ::testing::Combine; + +class HybridHeapTest : public HeapTestBase, + public WithParamInterface<::std::tuple> +{ +protected: + static const UINT32 AllocationCount = 100; + + VOID SetUp() { + HeapTestBase::SetUp(); + + HEAP_BEHAVIOR_FLAGS primaryHeapType; + std::tie(primaryHeapType) = GetParam(); + mHeapType = primaryHeapType | FLAGS_USE_HYBRID_VRAM_HEAP; + + // Set the invalid allocation handles + for (UINT32 i = 0; i < AllocationCount; i++) { + mHandles[i] = INVALID_ALLOCATION_HANDLE_VALUE; + } + + mHeap = NULL; + } + + VOID freeAllocations() { + // Release the allocations in case of the system heap usage as heap release doesn't free allocations + if (mHeap != NULL && (mHeapType & FLAGS_USE_SYSTEM_HEAP) != HEAP_FLAGS_NONE) { + for (UINT32 i = 0; i < AllocationCount; i++) { + if (IS_VALID_ALLOCATION_HANDLE(mHandles[i])) { + EXPECT_EQ(STATUS_SUCCESS, heapFree(mHeap, mHandles[i])); + } + } + } + } + + UINT32 mHeapType; + PHeap mHeap; + ALLOCATION_HANDLE mHandles[AllocationCount]; }; -TEST_F(HybridHeapTest, hybridCreateHeap) +TEST_P(HybridHeapTest, hybridCreateHeap) { - PHeap pHeap; ALLOCATION_HANDLE handle; UINT32 memHeapLimit; UINT32 vramHeapLimit; @@ -13,7 +51,7 @@ TEST_F(HybridHeapTest, hybridCreateHeap) UINT32 ramAllocSize; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; UINT32 spillRatio = 50; - UINT32 numAlloc = 50; + UINT32 numAlloc = AllocationCount / 2; // Split the 50% and allocate half from ram and half from vram memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); @@ -23,9 +61,10 @@ TEST_F(HybridHeapTest, hybridCreateHeap) // Initialize EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, - spillRatio, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + spillRatio, + mHeapType, + NULL, + &mHeap))); // Validate internal calls EXPECT_EQ(mVramGetMaxCount, 1); @@ -40,12 +79,14 @@ TEST_F(HybridHeapTest, hybridCreateHeap) EXPECT_EQ(mDlErrorCount, 0); EXPECT_EQ(mDlSymCount, 7); - DLOGV("Allocating from RAM"); + DLOGV("Allocating from RAM type %s", + (mHeapType & FLAGS_USE_AIV_HEAP) != HEAP_FLAGS_NONE ? "AIV heap" : "System heap"); // Allocate from ram - should be 1 less due to service structs for (UINT32 i = 0; i < numAlloc - 1; i++) { - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, ramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, ramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[i] = handle; } // Validate internal calls @@ -65,7 +106,7 @@ TEST_F(HybridHeapTest, hybridCreateHeap) // Allocate from vram for (UINT32 i = 0; i < numAlloc; i++) { - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, vramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, vramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); } @@ -82,8 +123,11 @@ TEST_F(HybridHeapTest, hybridCreateHeap) EXPECT_EQ(mDlErrorCount, 0); EXPECT_EQ(mDlSymCount, 7); + // Free allocations before release + freeAllocations(); + // Release the heap and validate internal calls - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); EXPECT_EQ(mVramGetMaxCount, 1); EXPECT_EQ(mVramInitCount, 1); EXPECT_EQ(mVramAllocCount, numAlloc); @@ -97,44 +141,43 @@ TEST_F(HybridHeapTest, hybridCreateHeap) EXPECT_EQ(mDlSymCount, 7); } -TEST_F(HybridHeapTest, hybridCreateHeapMemHeapSmall) +TEST_P(HybridHeapTest, hybridCreateHeapMemHeapSmall) { - PHeap pHeap; - // Initialize should fail as MIN_HEAP_SIZE will be smaller for the mem heap with 20% reduction EXPECT_TRUE(STATUS_FAILED(heapInitialize(MIN_HEAP_SIZE, 20, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapDlOpenCount) +TEST_P(HybridHeapTest, hybridCreateHeapDlOpenCount) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Initialize with one time opening EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + mHeapType, + NULL, + &mHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); EXPECT_EQ(mDlCloseCount, 1); EXPECT_EQ(mDlOpenCount, 1); // Initialize with reopen EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP | FLAGS_REOPEN_VRAM_LIBRARY, - &pHeap))); - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + mHeapType | FLAGS_REOPEN_VRAM_LIBRARY, + NULL, + &mHeap))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); EXPECT_EQ(mDlCloseCount, 2); EXPECT_EQ(mDlOpenCount, 3); } -TEST_F(HybridHeapTest, hybridCreateHeapDlOpenError) +TEST_P(HybridHeapTest, hybridCreateHeapDlOpenError) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Set to produce an error @@ -142,16 +185,16 @@ TEST_F(HybridHeapTest, hybridCreateHeapDlOpenError) EXPECT_TRUE(STATUS_FAILED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); // Validate the on error we don't attempt to close the library as the handle is NULL EXPECT_EQ(mDlCloseCount, 0); } -TEST_F(HybridHeapTest, hybridCreateHeapDlSymError) +TEST_P(HybridHeapTest, hybridCreateHeapDlSymError) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Set to produce an error @@ -159,35 +202,35 @@ TEST_F(HybridHeapTest, hybridCreateHeapDlSymError) EXPECT_TRUE(STATUS_FAILED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); // Validate the on error we close the library EXPECT_EQ(mDlCloseCount, 1); } -TEST_F(HybridHeapTest, hybridCreateHeapDlCloseError) +TEST_P(HybridHeapTest, hybridCreateHeapDlCloseError) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Set to produce an error mDlClose = 1; EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, - 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + 50, + mHeapType, + NULL, + &mHeap))); - EXPECT_TRUE(STATUS_FAILED(heapRelease(pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapRelease(mHeap))); // Validate the on error we close the library EXPECT_EQ(mDlCloseCount, 1); } -TEST_F(HybridHeapTest, hybridCreateHeapVRamInitError) +TEST_P(HybridHeapTest, hybridCreateHeapVRamInitError) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Set to produce an error @@ -196,13 +239,13 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamInitError) // Initialize should fail as we will fail to vram init EXPECT_TRUE(STATUS_FAILED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapGetMaxVramSmall) +TEST_P(HybridHeapTest, hybridCreateHeapGetMaxVramSmall) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Set to produce an error @@ -211,13 +254,13 @@ TEST_F(HybridHeapTest, hybridCreateHeapGetMaxVramSmall) // Initialize should fail as requested vram size will be smaller than the max vram EXPECT_TRUE(STATUS_FAILED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapVRamReleaseError) +TEST_P(HybridHeapTest, hybridCreateHeapVRamReleaseError) { - PHeap pHeap; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; // Set to produce an error @@ -225,15 +268,15 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamReleaseError) EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, 50, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); - EXPECT_TRUE(STATUS_FAILED(heapRelease(pHeap))); + EXPECT_TRUE(STATUS_FAILED(heapRelease(mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapVRamAllocError) +TEST_P(HybridHeapTest, hybridCreateHeapVRamAllocError) { - PHeap pHeap; ALLOCATION_HANDLE handle; UINT32 memHeapLimit; UINT32 vramHeapLimit; @@ -241,7 +284,7 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamAllocError) UINT32 ramAllocSize; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; UINT32 spillRatio = 50; - UINT32 numAlloc = 50; + UINT32 numAlloc = AllocationCount / 2; // Split the 50% and allocate half from ram and half from vram memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); @@ -254,30 +297,33 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamAllocError) EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, spillRatio, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); DLOGV("Allocating from RAM"); // Allocate from ram - should be 1 less due to service structs for (UINT32 i = 0; i < numAlloc - 1; i++) { - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, ramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, ramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[i] = handle; } DLOGV("Allocating from VRAM"); // Allocate from vram for (UINT32 i = 0; i < numAlloc; i++) { - EXPECT_FALSE(STATUS_SUCCEEDED(heapAlloc(pHeap, vramAllocSize, &handle))); + EXPECT_FALSE(STATUS_SUCCEEDED(heapAlloc(mHeap, vramAllocSize, &handle))); + mHandles[numAlloc - 1 + i] = handle; } - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + freeAllocations(); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapVRamMapError) +TEST_P(HybridHeapTest, hybridCreateHeapVRamMapError) { - PHeap pHeap; ALLOCATION_HANDLE handle; UINT32 memHeapLimit; UINT32 vramHeapLimit; @@ -285,7 +331,7 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamMapError) UINT32 ramAllocSize; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; UINT32 spillRatio = 50; - UINT32 numAlloc = 50; + UINT32 numAlloc = AllocationCount / 2; // Split the 50% and allocate half from ram and half from vram memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); vramHeapLimit = heapSize - memHeapLimit; @@ -297,31 +343,34 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamMapError) EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, spillRatio, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); DLOGV("Allocating from RAM"); // Allocate from ram - should be 1 less due to service structs for (UINT32 i = 0; i < numAlloc - 1; i++) { - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, ramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, ramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[i] = handle; } DLOGV("Allocating from VRAM"); // Allocate from vram for (UINT32 i = 0; i < numAlloc; i++) { - EXPECT_TRUE(STATUS_FAILED(heapAlloc(pHeap, vramAllocSize, &handle))); + EXPECT_TRUE(STATUS_FAILED(heapAlloc(mHeap, vramAllocSize, &handle))); EXPECT_FALSE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[numAlloc - 1 + i] = handle; } - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + freeAllocations(); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapVRamUnmapError) +TEST_P(HybridHeapTest, hybridCreateHeapVRamUnmapError) { - PHeap pHeap; ALLOCATION_HANDLE handle; UINT64 retSize; PVOID pAlloc; @@ -331,7 +380,7 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamUnmapError) UINT32 ramAllocSize; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; UINT32 spillRatio = 50; - UINT32 numAlloc = 50; + UINT32 numAlloc = AllocationCount / 2; // Split the 50% and allocate half from ram and half from vram memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); vramHeapLimit = heapSize - memHeapLimit; @@ -343,15 +392,17 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamUnmapError) EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, spillRatio, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); DLOGV("Allocating from RAM"); // Allocate from ram - should be 1 less due to service structs for (UINT32 i = 0; i < numAlloc - 1; i++) { - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, ramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, ramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[i] = handle; } DLOGV("Allocating from VRAM"); @@ -359,22 +410,24 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamUnmapError) // Allocate from vram for (UINT32 i = 0; i < numAlloc; i++) { // Should produce a warning but shouldn't fail - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, vramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, vramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); // Try mapping it - should succeed - EXPECT_TRUE(STATUS_SUCCEEDED(heapMap(pHeap, handle, &pAlloc, &retSize))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapMap(mHeap, handle, &pAlloc, &retSize))); // Try un-mapping it - should fail - EXPECT_TRUE(STATUS_FAILED(heapUnmap(pHeap, pAlloc))); + EXPECT_TRUE(STATUS_FAILED(heapUnmap(mHeap, pAlloc))); + + mHandles[numAlloc - 1 + i] = handle; } - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + freeAllocations(); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); } -TEST_F(HybridHeapTest, hybridCreateHeapVRamFreeError) +TEST_P(HybridHeapTest, hybridCreateHeapVRamFreeError) { - PHeap pHeap; ALLOCATION_HANDLE handle; UINT64 retSize; PVOID pAlloc; @@ -384,7 +437,7 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamFreeError) UINT32 ramAllocSize; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; UINT32 spillRatio = 50; - UINT32 numAlloc = 50; + UINT32 numAlloc = AllocationCount / 2; // Split the 50% and allocate half from ram and half from vram memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); vramHeapLimit = heapSize - memHeapLimit; @@ -396,15 +449,17 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamFreeError) EXPECT_TRUE(STATUS_SUCCEEDED(heapInitialize(heapSize, spillRatio, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap))); + mHeapType, + NULL, + &mHeap))); DLOGV("Allocating from RAM"); // Allocate from ram - should be 1 less due to service structs for (UINT32 i = 0; i < numAlloc - 1; i++) { - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, ramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, ramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[i] = handle; } DLOGV("Allocating from VRAM"); @@ -412,33 +467,33 @@ TEST_F(HybridHeapTest, hybridCreateHeapVRamFreeError) // Allocate from vram for (UINT32 i = 0; i < numAlloc; i++) { // Should produce a warning but shouldn't fail - EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(pHeap, vramAllocSize, &handle))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapAlloc(mHeap, vramAllocSize, &handle))); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); // Try mapping it - should succeed - EXPECT_TRUE(STATUS_SUCCEEDED(heapMap(pHeap, handle, &pAlloc, &retSize))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapMap(mHeap, handle, &pAlloc, &retSize))); // Try un-mapping it - should succeed - EXPECT_TRUE(STATUS_SUCCEEDED(heapUnmap(pHeap, pAlloc))); + EXPECT_TRUE(STATUS_SUCCEEDED(heapUnmap(mHeap, pAlloc))); // Try freeing it - should fail - EXPECT_TRUE(STATUS_FAILED(heapFree(pHeap, handle))); + EXPECT_TRUE(STATUS_FAILED(heapFree(mHeap, handle))); } - EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(pHeap))); + freeAllocations(); + EXPECT_TRUE(STATUS_SUCCEEDED(heapRelease(mHeap))); } -TEST_F(HybridHeapTest, hybridFillResizeAlloc) +TEST_P(HybridHeapTest, hybridFillResizeAlloc) { - PHeap pHeap; - ALLOCATION_HANDLE handle, storedHandle; + ALLOCATION_HANDLE handle; UINT32 memHeapLimit; UINT32 vramHeapLimit; UINT32 vramAllocSize; UINT32 ramAllocSize; UINT32 heapSize = MIN_HEAP_SIZE * 2 + 100000; UINT32 spillRatio = 50; - UINT32 numAlloc = 50; + UINT32 numAlloc = AllocationCount / 2; // Split the 50% and allocate half from ram and half from vram memHeapLimit = (UINT32)(heapSize * ((DOUBLE)spillRatio / 100)); @@ -448,41 +503,45 @@ TEST_F(HybridHeapTest, hybridFillResizeAlloc) EXPECT_EQ(STATUS_SUCCESS, heapInitialize(heapSize, spillRatio, - FLAGS_USE_AIV_HEAP | FLAGS_USE_HYBRID_VRAM_HEAP, - &pHeap)); + mHeapType, + NULL, + &mHeap)); // Allocate from ram - account for the service structs // Store an allocation handle somewhere in the middle for (UINT32 i = 0; i < numAlloc; i++) { - EXPECT_EQ(STATUS_SUCCESS, heapAlloc(pHeap, ramAllocSize, &handle)); + EXPECT_EQ(STATUS_SUCCESS, heapAlloc(mHeap, ramAllocSize, &handle)); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); - - // Store a handle somewhere in the middle - if (i == numAlloc / 2) { - storedHandle = handle; - } + mHandles[i] = handle; } // Allocate from vram and account for the service structs. for (UINT32 i = 0; i < numAlloc - 1; i++) { - EXPECT_EQ(STATUS_SUCCESS, heapAlloc(pHeap, vramAllocSize, &handle)); + EXPECT_EQ(STATUS_SUCCESS, heapAlloc(mHeap, vramAllocSize, &handle)); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); + mHandles[numAlloc + i] = handle; } // Set to produce an error if vram allocation is called mVramAlloc = 0; // Try to allocate and ensure we fail - EXPECT_EQ(STATUS_SUCCESS, heapAlloc(pHeap, ramAllocSize - 200, &handle)); + EXPECT_EQ(STATUS_SUCCESS, heapAlloc(mHeap, ramAllocSize - 200, &handle)); EXPECT_FALSE(IS_VALID_ALLOCATION_HANDLE(handle)); - // Resize the stored handle - EXPECT_EQ(STATUS_SUCCESS, heapSetAllocSize(pHeap, &storedHandle, 100)); - EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(storedHandle)); + // Resize a ram handle from somewhere in the middle + EXPECT_EQ(STATUS_SUCCESS, heapSetAllocSize(mHeap, &mHandles[numAlloc / 2], 100)); + EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(mHandles[numAlloc / 2])); // Ensure we are able to allocate from direct RAM - EXPECT_EQ(STATUS_SUCCESS, heapAlloc(pHeap, ramAllocSize - 200, &handle)); + EXPECT_EQ(STATUS_SUCCESS, heapAlloc(mHeap, ramAllocSize - 200, &handle)); EXPECT_TRUE(IS_VALID_ALLOCATION_HANDLE(handle)); - EXPECT_EQ(STATUS_SUCCESS, heapRelease(pHeap)); -} \ No newline at end of file + EXPECT_EQ(STATUS_SUCCESS, heapFree(mHeap, handle)); + + freeAllocations(); + EXPECT_EQ(STATUS_SUCCESS, heapRelease(mHeap)); +} + +INSTANTIATE_TEST_CASE_P(PermutatedHeapType, HybridHeapTest, + Values(FLAGS_USE_AIV_HEAP, FLAGS_USE_SYSTEM_HEAP)); diff --git a/src/mkvgen/src/SpsParser.c b/src/mkvgen/src/SpsParser.c index 41a57acee..6f77c7b42 100644 --- a/src/mkvgen/src/SpsParser.c +++ b/src/mkvgen/src/SpsParser.c @@ -81,8 +81,7 @@ STATUS getVideoWidthAndHeightFromH265Sps(PBYTE codecPrivateData, UINT32 codecPri BYTE naluType; UINT16 numNalus, naluIterator, naluLen; BOOL spsNaluFound = FALSE; - PBYTE pRun; - UINT32 adaptedSize, naluSize; + UINT32 adaptedSize; CHK(codecPrivateData != NULL && pWidth != NULL && pHeight != NULL, STATUS_NULL_ARG); CHK(codecPrivateDataSize >= MIN_H264_H265_CPD_SIZE, STATUS_MKV_INVALID_H264_H265_CPD); diff --git a/src/utils/include/com/amazonaws/kinesis/video/utils/Include.h b/src/utils/include/com/amazonaws/kinesis/video/utils/Include.h index 0394e0769..e8b40b99b 100644 --- a/src/utils/include/com/amazonaws/kinesis/video/utils/Include.h +++ b/src/utils/include/com/amazonaws/kinesis/video/utils/Include.h @@ -163,7 +163,9 @@ STATUS tolowerupperstr(PCHAR, UINT32, BOOL, PCHAR); PUBLIC_API STATUS readFile(PCHAR filePath, BOOL binMode, PBYTE pBuffer, PUINT64 pSize); PUBLIC_API STATUS readFileSegment(PCHAR filePath, BOOL binMode, PBYTE pBuffer, UINT64 offset, UINT64 readSize); PUBLIC_API STATUS writeFile(PCHAR filePath, BOOL binMode, BOOL append, PBYTE pBuffer, UINT64 size); +PUBLIC_API STATUS updateFile(PCHAR filePath, BOOL binMode, PBYTE pBuffer, UINT64 offset, UINT64 size); PUBLIC_API STATUS getFileLength(PCHAR filePath, PUINT64 pSize); +PUBLIC_API STATUS setFileLength(PCHAR filePath, UINT64 size); PUBLIC_API STATUS fileExists(PCHAR filePath, PBOOL pExists); PUBLIC_API STATUS createFile(PCHAR filePath, UINT64 size); diff --git a/src/utils/src/FileIo.c b/src/utils/src/FileIo.c index 22aa0e26e..6bae6c020 100644 --- a/src/utils/src/FileIo.c +++ b/src/utils/src/FileIo.c @@ -83,7 +83,7 @@ STATUS readFileSegment(PCHAR filePath, BOOL binMode, PBYTE pBuffer, UINT64 offse // Set the offset and read the file content result = FSEEK(fp, (UINT32) offset, SEEK_SET); - CHK(result && (FREAD(pBuffer, (SIZE_T) readSize, 1, fp) == 1), STATUS_READ_FILE_FAILED); + CHK(result == 0 && (FREAD(pBuffer, (SIZE_T) readSize, 1, fp) == 1), STATUS_READ_FILE_FAILED); CleanUp: @@ -129,6 +129,45 @@ STATUS writeFile(PCHAR filePath, BOOL binMode, BOOL append, PBYTE pBuffer, UINT6 return retStatus; } +/** + * Write contents pointed to by pBuffer to the given filePath. + * + * Parameters: + * filePath - file path to write to + * binMode - TRUE to read file stream as binary; FALSE to read as a normal text file + * pBuffer - memory location whose contents should be written to the file + * offset - Offset to start writing from + * size - number of bytes that should be written to the file + */ +STATUS updateFile(PCHAR filePath, BOOL binMode, PBYTE pBuffer, UINT64 offset, UINT64 size) +{ + STATUS retStatus = STATUS_SUCCESS; + FILE *fp = NULL; + UINT32 i; + PBYTE pCurPtr; + + CHK(filePath != NULL && pBuffer != NULL, STATUS_NULL_ARG); + + fp = FOPEN(filePath, binMode ? "rb+" : "r+"); + + CHK(fp != NULL, STATUS_OPEN_FILE_FAILED); + + CHK(0 == FSEEK(fp, (UINT32) offset, SEEK_SET), STATUS_INVALID_OPERATION); + + for (i = 0, pCurPtr = pBuffer + offset; i < size; i++, pCurPtr++) { + CHK(EOF != FPUTC(*pCurPtr, fp), STATUS_WRITE_TO_FILE_FAILED); + } + +CleanUp: + + if (fp != NULL) { + FCLOSE(fp); + fp = NULL; + } + + return retStatus; +} + /** * Gets the file length of the given filePath. * @@ -150,6 +189,79 @@ STATUS getFileLength(PCHAR filePath, PUINT64 pLength) return retStatus; } +/** + * Sets the file length of the given filePath. + * + * Parameters: + * filePath - file path whose file length should be computed + * length - Sets the size of the file in bytes + * + * Returns: + * STATUS of the operation + */ +STATUS setFileLength(PCHAR filePath, UINT64 length) +{ + STATUS retStatus = STATUS_SUCCESS; + INT32 retVal, errCode, fileDesc; + + CHK(filePath != NULL, STATUS_NULL_ARG); + +#if defined __WINDOWS_BUILD__ + fileDesc = _open(filePath, _O_BINARY | _O_RANDOM | _O_RDWR, 0); + + if (fileDesc != -1) { + retVal = _chsize_s(fileDesc, length); + + if (retVal != 0) { + retVal = -1; + errCode = errno; + } + + _close(fileDesc); + } else { + retVal = -1; + errCode = errno; + } + +#else + UNUSED_PARAM(fileDesc); + retVal = truncate(filePath, length); + errCode = errno; +#endif + + if (retVal == -1) { + switch (errCode) { + case EACCES: + retStatus = STATUS_DIRECTORY_ACCESS_DENIED; + break; + + case ENOENT: + retStatus = STATUS_DIRECTORY_MISSING_PATH; + break; + + case EINVAL: + retStatus = STATUS_INVALID_ARG_LEN; + break; + + case EISDIR: + case EBADF: + retStatus = STATUS_INVALID_ARG; + break; + + case ENOSPC: + retStatus = STATUS_NOT_ENOUGH_MEMORY; + break; + + default: + retStatus = STATUS_INVALID_OPERATION; + } + } + +CleanUp: + + return retStatus; +} + /** * Checks if the file or directory exists with a given full or relative path *