Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 56 additions & 15 deletions projects/miopen/src/db_path.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@
#include <miopen/filesystem.hpp>

#include <cstdlib>
#include <string>
#ifdef __linux__
#include <dlfcn.h>
#endif
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif

MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_SYSTEM_DB_PATH)
MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_USER_DB_PATH)
Expand All @@ -61,27 +68,61 @@ fs::path GetLibPath()
}
#endif

#ifdef _WIN32
fs::path GetLibPath()
{
// Mirrors GetOwningModuleDirectory() in src/solver/ck_impl_lib_loader.cpp: locate the module
// that owns a known MIOpen symbol, so the result follows MIOpen.dll rather than the process
// that loaded it.
HMODULE hmod = nullptr;
if(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(miopenCreate),
&hmod) != 0)
{
std::wstring module_path(MAX_PATH, L'\0');
while(true)
{
const auto len = GetModuleFileNameW(
hmod, module_path.data(), static_cast<DWORD>(module_path.size()));
if(len == 0)
break;
if(len < module_path.size())
{
module_path.resize(len);
auto path = miopen::weakly_canonical(fs::path{module_path}).parent_path();
MIOPEN_LOG_I2("Lib Path: " << path);
return path;
}
module_path.resize(module_path.size() * 2);
Comment thread
jdcampbe marked this conversation as resolved.
Resolved
}
}
return {};
}
#endif

fs::path GetSystemDbPath()
{
auto p = env::value(MIOPEN_SYSTEM_DB_PATH);
if(p.empty())
#if MIOPEN_BUILD_DEV || defined(_WIN32)
{
// Here, by default, MIOPEN_SYSTEM_DB_PATH is an empty path on Windows.
// MIOpen.dll will be searching for System DB files in local directory.
if(!p.empty())
return p;
#if MIOPEN_BUILD_DEV
// Development builds read the databases straight out of the build tree.
return "${MIOPEN_SYSTEM_DB_PATH}";
#elif defined(_WIN32)
// On Windows the databases are installed alongside MIOpen.dll (DATABASE_INSTALL_DIR is "bin"),
// so resolve them relative to the loaded module. Falling back to the configured value would
// make the lookup relative to the current working directory, which only finds the databases
// when the process happens to be started from the install directory.
static const auto lib_path = GetLibPath();
if(lib_path.empty())
return "${MIOPEN_SYSTEM_DB_PATH}";
}
return lib_path;
#else
{
// Get the module path and construct the db path
static const auto lib_path = GetLibPath().parent_path() / "share/miopen/db";
return lib_path;
}
// Get the module path and construct the db path
static const auto lib_path = GetLibPath().parent_path() / "share/miopen/db";
return lib_path;
#endif
else
{
return p;
}
}

namespace {
Expand Down
2 changes: 2 additions & 0 deletions projects/miopen/src/env_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_FIND_ENFORCE)
MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_FIND_MODE)
MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_FIND_MODE_FUSION)
MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_USER_DB_PATH)
MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_SYSTEM_DB_PATH)
MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_CUSTOM_CACHE_DIR)
MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_LEVEL)
MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_BUFFER_SIZE, 0);
Expand Down Expand Up @@ -214,6 +215,7 @@ const LibEnvVar& FindEnvVariable(std::string_view name)
{MIOPEN_LOG_LEVEL.GetName(), MIOPEN_LOG_LEVEL},
{MIOPEN_LOG_BUFFER_SIZE.GetName(), MIOPEN_LOG_BUFFER_SIZE},
{MIOPEN_USER_DB_PATH.GetName(), MIOPEN_USER_DB_PATH},
{MIOPEN_SYSTEM_DB_PATH.GetName(), MIOPEN_SYSTEM_DB_PATH},
{MIOPEN_CUSTOM_CACHE_DIR.GetName(), MIOPEN_CUSTOM_CACHE_DIR},
{MIOPEN_DEBUG_CONV_DIRECT_ASM_WRW1X1_PERF_VALS.GetName(), MIOPEN_DEBUG_CONV_DIRECT_ASM_WRW1X1_PERF_VALS},
{MIOPEN_SKIP_ASAN_DISABLED_TESTS.GetName(), MIOPEN_SKIP_ASAN_DISABLED_TESTS},
Expand Down
74 changes: 74 additions & 0 deletions projects/miopen/test/gtest/db_paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,22 @@
#include <string>
#include <sstream>

#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <miopen/miopen.h>
#include <windows.h>
#endif

using ::testing::_;
using ::testing::Return;

namespace fs = miopen::fs;

MIOPEN_LIB_ENV_VAR(MIOPEN_USER_DB_PATH)
MIOPEN_LIB_ENV_VAR(MIOPEN_CUSTOM_CACHE_DIR)
MIOPEN_LIB_ENV_VAR(MIOPEN_SYSTEM_DB_PATH)

// Helper function to build expected version string
std::string GetExpectedVersionString()
Expand Down Expand Up @@ -339,3 +348,68 @@ TEST_F(CPU_DbPaths_NONE, CacheDisabled_ReturnsCorrectly)
// Just verify it returns a valid boolean without crashing
EXPECT_TRUE(is_disabled == true || is_disabled == false);
}

// ============================================================================
// Tests for GetSystemDbPath()
// ============================================================================

TEST_F(CPU_DbPaths_NONE, SystemDbPath_EnvVarSet)
{
const std::string custom_path = (fs::temp_directory_path() / "custom/system/db").string();
ScopedEnvironment<std::string> scoped_env(MIOPEN_SYSTEM_DB_PATH, custom_path);

EXPECT_EQ(miopen::GetSystemDbPath(), fs::path{custom_path})
<< "MIOPEN_SYSTEM_DB_PATH must take precedence over the built-in default";
}

TEST_F(CPU_DbPaths_NONE, SystemDbPath_NoEnvVar_IsAbsolute)
{
ScopedEnvironment<std::string> unset_system_db(MIOPEN_SYSTEM_DB_PATH, "");

const auto system_db_path = miopen::GetSystemDbPath();

// An empty or relative default is resolved against the current working directory, so the
// system databases would only be found when the process happens to be started from the
// directory holding them.
EXPECT_TRUE(system_db_path.is_absolute())
<< "System DB path '" << system_db_path.string()
<< "' must be absolute so database lookup does not depend on the working directory";
}

#ifdef _WIN32
TEST_F(CPU_DbPaths_NONE, SystemDbPath_NoEnvVar_FollowsMIOpenModule)
{
#if MIOPEN_BUILD_DEV
GTEST_SKIP() << "Development builds read databases from the build tree, not the install layout";
#else
ScopedEnvironment<std::string> unset_system_db(MIOPEN_SYSTEM_DB_PATH, "");

// DATABASE_INSTALL_DIR is "bin" on Windows, so the databases are installed next to
// MIOpen.dll. Resolve that directory independently and compare.
HMODULE hmod = nullptr;
ASSERT_NE(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(miopenCreate),
&hmod),
0)
<< "Unable to locate the module exporting miopenCreate";

std::wstring module_path(MAX_PATH, L'\0');
DWORD len = 0;
while(true)
{
len = GetModuleFileNameW(hmod, module_path.data(), static_cast<DWORD>(module_path.size()));
ASSERT_NE(len, 0u) << "GetModuleFileNameW failed";
if(len < module_path.size())
break;
module_path.resize(module_path.size() * 2);
}
module_path.resize(len);
const auto expected = miopen::weakly_canonical(fs::path{module_path}).parent_path();

EXPECT_EQ(miopen::GetSystemDbPath(), expected)
<< "System DB path should follow MIOpen.dll so an installed MIOpen finds its databases "
"no matter which directory the application runs from";
#endif
}
#endif
Loading