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 *