diff --git a/shared/source/compiler_interface/windows/compiler_cache_windows.cpp b/shared/source/compiler_interface/windows/compiler_cache_windows.cpp index 4cb1d3a8bb..0274757457 100644 --- a/shared/source/compiler_interface/windows/compiler_cache_windows.cpp +++ b/shared/source/compiler_interface/windows/compiler_cache_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -28,17 +28,11 @@ struct ElementsStruct { std::vector getFiles(const std::string &path) { std::vector files; - std::string newPath; WIN32_FIND_DATAA ffd{0}; HANDLE hFind = INVALID_HANDLE_VALUE; - if (path.c_str()[path.size() - 1] == '\\') { - return files; - } else { - newPath = path + "/*"; - } - + std::string newPath = joinPath(path, "*"); hFind = NEO::SysCalls::findFirstFileA(newPath.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { @@ -47,6 +41,10 @@ std::vector getFiles(const std::string &path) { } do { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + continue; + } + auto fileName = joinPath(path, ffd.cFileName); if (fileName.find(".cl_cache") != fileName.npos || fileName.find(".l0_cache") != fileName.npos) { @@ -118,6 +116,7 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath, NULL); if (std::get(handle) == INVALID_HANDLE_VALUE) { + NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "PID %d [Cache failure]: Create config file failed! error code: %lu\n", GetCurrentProcessId(), GetLastError()); std::get(handle) = NEO::SysCalls::createFileA(configFilePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, diff --git a/shared/source/os_interface/windows/sys_calls.cpp b/shared/source/os_interface/windows/sys_calls.cpp index 38ac65cee2..6bb1ec4f65 100644 --- a/shared/source/os_interface/windows/sys_calls.cpp +++ b/shared/source/os_interface/windows/sys_calls.cpp @@ -47,7 +47,11 @@ DWORD getLastError() { bool pathExists(const std::string &path) { DWORD ret = GetFileAttributesA(path.c_str()); - return ret == FILE_ATTRIBUTE_DIRECTORY; + if (ret == INVALID_FILE_ATTRIBUTES) { + return false; + } + + return (ret & FILE_ATTRIBUTE_DIRECTORY) != 0; } HANDLE createEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName) { diff --git a/shared/test/unit_test/compiler_interface/windows/compiler_cache_tests_windows.cpp b/shared/test/unit_test/compiler_interface/windows/compiler_cache_tests_windows.cpp index a4a9a19930..66e0ef8666 100644 --- a/shared/test/unit_test/compiler_interface/windows/compiler_cache_tests_windows.cpp +++ b/shared/test/unit_test/compiler_interface/windows/compiler_cache_tests_windows.cpp @@ -11,6 +11,7 @@ #include "shared/source/helpers/string.h" #include "shared/source/os_interface/debug_env_reader.h" #include "shared/source/os_interface/windows/sys_calls.h" +#include "shared/source/utilities/stackvec.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/gtest_helpers.h" #include "shared/test/common/helpers/variable_backup.h" @@ -232,6 +233,7 @@ TEST_F(CompilerCacheWindowsTest, GivenCompilerCacheWithOneMegabyteWhenEvictCache filesData[i].nFileSizeHigh = 0; filesData[i].nFileSizeLow = cacheFileSize; filesData[i].ftLastAccessTime.dwHighDateTime = 0; + filesData[i].dwFileAttributes = 0; SysCalls::findNextFileAFileData[i] = filesData[i]; } @@ -250,6 +252,41 @@ TEST_F(CompilerCacheWindowsTest, GivenCompilerCacheWithOneMegabyteWhenEvictCache EXPECT_EQ(0, strcmp(deletedFiles[1].c_str(), "somePath\\cl_cache\\file_1.cl_cache")); } +TEST_F(CompilerCacheWindowsTest, GivenCompilerCacheWithOneMegabyteAnd3CacheFilesAnd1DirectoryWhenEvictCacheIsCalledThenDeleteTwoOldestFilesSkippingDirectory) { + WIN32_FIND_DATAA filesData[4]; + DWORD cacheFileSize = (MemoryConstants::megaByte / 6) + 10; + + filesData[0].ftLastAccessTime.dwLowDateTime = 6u; + filesData[1].ftLastAccessTime.dwLowDateTime = 4u; // Directory + filesData[2].ftLastAccessTime.dwLowDateTime = 8u; + filesData[3].ftLastAccessTime.dwLowDateTime = 2u; + + StackVec fileAttributes = {0, FILE_ATTRIBUTE_DIRECTORY, 0, 0}; + + for (size_t i = 0; i < 4; i++) { + snprintf(filesData[i].cFileName, MAX_PATH, "file_%zu.cl_cache", i); + filesData[i].nFileSizeHigh = 0; + filesData[i].nFileSizeLow = cacheFileSize; + filesData[i].ftLastAccessTime.dwHighDateTime = 0; + filesData[i].dwFileAttributes = fileAttributes[i]; + + SysCalls::findNextFileAFileData[i] = filesData[i]; + } + + SysCalls::findFirstFileAResult = reinterpret_cast(0x1234); + const size_t cacheSize = MemoryConstants::megaByte - 2u; + CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize}); + auto &deletedFiles = SysCalls::deleteFiles; + + uint64_t bytesEvicted{0u}; + auto result = cache.evictCache(bytesEvicted); + + EXPECT_TRUE(result); + EXPECT_EQ(2u, SysCalls::deleteFileACalled); + EXPECT_EQ(0, strcmp(deletedFiles[0].c_str(), "somePath\\cl_cache\\file_3.cl_cache")); + EXPECT_EQ(0, strcmp(deletedFiles[1].c_str(), "somePath\\cl_cache\\file_0.cl_cache")); +} + TEST_F(CompilerCacheWindowsTest, givenEvictCacheWhenFileSearchFailedThenDebugMessageWithErrorIsPrinted) { DebugManagerStateRestore restore; NEO::debugManager.flags.PrintDebugMessages.set(1); @@ -419,6 +456,7 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC filesData[i].nFileSizeHigh = 0; filesData[i].nFileSizeLow = cacheFileSize; filesData[i].ftLastAccessTime.dwHighDateTime = 0; + filesData[i].dwFileAttributes = 0; SysCalls::findNextFileAFileData[i] = filesData[i]; } @@ -441,6 +479,63 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC EXPECT_EQ(0u, SysCalls::closeHandleCalled); } +TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigFailsAndCreateNewConfigFailsAndSecondTimeOpenExistingConfigSucceedsThenPrintErrorMessageFromCreateConfigFail) { + DebugManagerStateRestore restore; + NEO::debugManager.flags.PrintDebugMessages.set(1); + + const size_t readCacheDirSize = 840 * MemoryConstants::kiloByte; + SysCalls::createFileAResults[0] = INVALID_HANDLE_VALUE; + SysCalls::createFileAResults[1] = INVALID_HANDLE_VALUE; + SysCalls::createFileAResults[2] = reinterpret_cast(0x1234); + SysCalls::lockFileExResult = TRUE; + + SysCalls::callBaseReadFile = false; + SysCalls::readFileResult = TRUE; + SysCalls::readFileBufferData = readCacheDirSize; + + SysCalls::getLastErrorResult = ERROR_FILE_NOT_FOUND; + + WIN32_FIND_DATAA filesData[4]; + DWORD cacheFileSize = (MemoryConstants::megaByte / 6) + 10; + + filesData[0].ftLastAccessTime.dwLowDateTime = 6u; + filesData[1].ftLastAccessTime.dwLowDateTime = 4u; + filesData[2].ftLastAccessTime.dwLowDateTime = 8u; + filesData[3].ftLastAccessTime.dwLowDateTime = 2u; + + for (size_t i = 0; i < 4; i++) { + snprintf(filesData[i].cFileName, MAX_PATH, "file_%zu.cl_cache", i); + filesData[i].nFileSizeHigh = 0; + filesData[i].nFileSizeLow = cacheFileSize; + filesData[i].ftLastAccessTime.dwHighDateTime = 0; + filesData[i].dwFileAttributes = 0; + + SysCalls::findNextFileAFileData[i] = filesData[i]; + } + + const size_t cacheSize = MemoryConstants::megaByte - 2u; + CompilerCacheMockWindows cache({true, ".cl_cache", "somePath\\cl_cache", cacheSize}); + + UnifiedHandle configFileHandle{nullptr}; + size_t directorySize = 0u; + ::testing::internal::CaptureStderr(); + cache.lockConfigFileAndReadSize("somePath\\cl_cache\\config.file", configFileHandle, directorySize); + auto capturedStderr = ::testing::internal::GetCapturedStderr(); + + std::string expectedStderrSubstr("[Cache failure]: Create config file failed! error code:"); + + EXPECT_TRUE(hasSubstr(capturedStderr, expectedStderrSubstr)); + + EXPECT_EQ(3u, SysCalls::createFileACalled); + EXPECT_EQ(1u, SysCalls::lockFileExCalled); + + EXPECT_EQ(readCacheDirSize, directorySize); + + EXPECT_EQ(1u, SysCalls::readFileCalled); + EXPECT_EQ(0u, SysCalls::unlockFileExCalled); + EXPECT_EQ(0u, SysCalls::closeHandleCalled); +} + TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingConfigFailsThenPrintErrorMessageAndEarlyReturn) { DebugManagerStateRestore restore; NEO::debugManager.flags.PrintDebugMessages.set(1); @@ -469,6 +564,7 @@ TEST_F(CompilerCacheWindowsTest, givenLockConfigFileAndReadSizeWhenOpenExistingC filesData[i].nFileSizeHigh = 0; filesData[i].nFileSizeLow = cacheFileSize; filesData[i].ftLastAccessTime.dwHighDateTime = 0; + filesData[i].dwFileAttributes = 0; SysCalls::findNextFileAFileData[i] = filesData[i]; }