Skip to content

[SYCL][NFC] Detach library loading helpers from UR #15491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all 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
12 changes: 0 additions & 12 deletions sycl/include/sycl/detail/ur.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,6 @@ template <sycl::backend BE>
__SYCL_EXPORT void *getPluginOpaqueData(void *opaquedata_arg);

namespace ur {
// Function to load a shared library
// Implementation is OS dependent
void *loadOsLibrary(const std::string &Library);

// Function to unload a shared library
// Implementation is OS dependent (see posix-ur.cpp and windows-ur.cpp)
int unloadOsLibrary(void *Library);

// Function to get Address of a symbol defined in the shared
// library, implementation is OS dependent.
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName);

// The SYCL_UR_TRACE sets what we will trace.
// This is a bit-mask of various things we'd want to trace.
enum TraceLevel { TRACE_BASIC = 0x1, TRACE_CALLS = 0x2, TRACE_ALL = -1 };
Expand Down
2 changes: 2 additions & 0 deletions sycl/source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ set(SYCL_COMMON_SOURCES
"virtual_mem.cpp"
"$<$<PLATFORM_ID:Windows>:detail/windows_ur.cpp>"
"$<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:Darwin>>:detail/posix_ur.cpp>"
"$<$<PLATFORM_ID:Windows>:detail/load_library_win.cpp>"
"$<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:Darwin>>:detail/load_library_posix.cpp>"
)

set(SYCL_NON_PREVIEW_SOURCES "${SYCL_COMMON_SOURCES}"
Expand Down
17 changes: 9 additions & 8 deletions sycl/source/detail/jit_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <detail/jit_compiler.hpp>
#include <detail/kernel_bundle_impl.hpp>
#include <detail/kernel_impl.hpp>
#include <detail/load_library.hpp>
#include <detail/queue_impl.hpp>
#include <detail/sycl_mem_obj_t.hpp>
#include <sycl/detail/ur.hpp>
Expand All @@ -32,32 +33,32 @@ jit_compiler::jit_compiler() {
auto checkJITLibrary = [this]() -> bool {
static const std::string JITLibraryName = "libsycl-jit.so";

void *LibraryPtr = sycl::detail::ur::loadOsLibrary(JITLibraryName);
void *LibraryPtr = sycl::detail::loadOsLibrary(JITLibraryName);
if (LibraryPtr == nullptr) {
printPerformanceWarning("Could not find JIT library " + JITLibraryName);
return false;
}

this->AddToConfigHandle = reinterpret_cast<AddToConfigFuncT>(
sycl::detail::ur::getOsLibraryFuncAddress(LibraryPtr,
"addToJITConfiguration"));
sycl::detail::getOsLibraryFuncAddress(LibraryPtr,
"addToJITConfiguration"));
if (!this->AddToConfigHandle) {
printPerformanceWarning(
"Cannot resolve JIT library function entry point");
return false;
}

this->ResetConfigHandle = reinterpret_cast<ResetConfigFuncT>(
sycl::detail::ur::getOsLibraryFuncAddress(LibraryPtr,
"resetJITConfiguration"));
sycl::detail::getOsLibraryFuncAddress(LibraryPtr,
"resetJITConfiguration"));
if (!this->ResetConfigHandle) {
printPerformanceWarning(
"Cannot resolve JIT library function entry point");
return false;
}

this->FuseKernelsHandle = reinterpret_cast<FuseKernelsFuncT>(
sycl::detail::ur::getOsLibraryFuncAddress(LibraryPtr, "fuseKernels"));
sycl::detail::getOsLibraryFuncAddress(LibraryPtr, "fuseKernels"));
if (!this->FuseKernelsHandle) {
printPerformanceWarning(
"Cannot resolve JIT library function entry point");
Expand All @@ -66,8 +67,8 @@ jit_compiler::jit_compiler() {

this->MaterializeSpecConstHandle =
reinterpret_cast<MaterializeSpecConstFuncT>(
sycl::detail::ur::getOsLibraryFuncAddress(
LibraryPtr, "materializeSpecConstants"));
sycl::detail::getOsLibraryFuncAddress(LibraryPtr,
"materializeSpecConstants"));
if (!this->MaterializeSpecConstHandle) {
printPerformanceWarning(
"Cannot resolve JIT library function entry point");
Expand Down
12 changes: 6 additions & 6 deletions sycl/source/detail/kernel_compiler/kernel_compiler_opencl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//

#include <sycl/detail/ur.hpp> // getOsLibraryFuncAddress
#include <detail/load_library.hpp> // getOsLibraryFuncAddress
#include <sycl/exception.hpp> // make_error_code

#include "kernel_compiler_opencl.hpp"
Expand All @@ -27,7 +27,7 @@ namespace detail {
// ensures the OclocLibrary has the right version, etc.
void checkOclocLibrary(void *OclocLibrary) {
void *OclocVersionHandle =
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocVersion");
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocVersion");
// The initial versions of ocloc library did not have the oclocVersion()
// function. Those versions had the same API as the first version of ocloc
// library having that oclocVersion() function.
Expand Down Expand Up @@ -67,7 +67,7 @@ void *loadOclocLibrary() {
#endif
void *tempPtr = OclocLibrary;
if (tempPtr == nullptr) {
tempPtr = sycl::detail::ur::loadOsLibrary(OclocLibraryName);
tempPtr = sycl::detail::loadOsLibrary(OclocLibraryName);

if (tempPtr == nullptr)
throw sycl::exception(make_error_code(errc::build),
Expand Down Expand Up @@ -104,12 +104,12 @@ void SetupLibrary(voidPtr &oclocInvokeHandle, voidPtr &oclocFreeOutputHandle,
loadOclocLibrary();

oclocInvokeHandle =
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
if (!oclocInvokeHandle)
throw sycl::exception(the_errc, "Cannot load oclocInvoke() function");

oclocFreeOutputHandle = sycl::detail::ur::getOsLibraryFuncAddress(
OclocLibrary, "oclocFreeOutput");
oclocFreeOutputHandle =
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocFreeOutput");
if (!oclocFreeOutputHandle)
throw sycl::exception(the_errc, "Cannot load oclocFreeOutput() function");
}
Expand Down
36 changes: 36 additions & 0 deletions sycl/source/detail/load_library.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//==-------------------------- load_library.hpp ----------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Collection of helper OS-agnostic functions to dynamically load libraries and
// query their symbols.
//
//===----------------------------------------------------------------------===//

#pragma once

#include <string>

namespace sycl {
inline namespace _V1 {
namespace detail {

// Function to load a shared library
// Implementation is OS dependent
void *loadOsLibrary(const std::string &Library);

// Function to unload a shared library
// Implementation is OS dependent (see posix-ur.cpp and windows-ur.cpp)
int unloadOsLibrary(void *Library);

// Function to get Address of a symbol defined in the shared
// library, implementation is OS dependent.
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName);

} // namespace detail
} // namespace _V1
} // namespace sycl
41 changes: 41 additions & 0 deletions sycl/source/detail/load_library_posix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//==-------------------- load_library_posix.cpp ----------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <detail/load_library.hpp>
#include <sycl/detail/defines_elementary.hpp>
#include <sycl/detail/iostream_proxy.hpp>
#include <sycl/detail/ur.hpp>

#include <dlfcn.h>
#include <string>

namespace sycl {
inline namespace _V1 {
namespace detail {

void *loadOsLibrary(const std::string &LibraryPath) {
// TODO: Check if the option RTLD_NOW is correct. Explore using
// RTLD_DEEPBIND option when there are multiple adapters.
void *so = dlopen(LibraryPath.c_str(), RTLD_NOW);
if (!so && ur::trace(ur::TraceLevel::TRACE_ALL)) {
char *Error = dlerror();
std::cerr << "SYCL_UR_TRACE: dlopen(" << LibraryPath << ") failed with <"
<< (Error ? Error : "unknown error") << ">" << std::endl;
}
return so;
}

int unloadOsLibrary(void *Library) { return dlclose(Library); }

void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName) {
return dlsym(Library, FunctionName.c_str());
}

} // namespace detail
} // namespace _V1
} // namespace sycl
72 changes: 72 additions & 0 deletions sycl/source/detail/load_library_win.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//==-------------------- load_library_lin.cpp ------------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <detail/load_library.hpp>
#include <detail/windows_os_utils.hpp>

#include <filesystem>
#include <cassert>
#include <string>
#include <windows.h>
#include <winreg.h>

namespace sycl {
inline namespace _V1 {
namespace detail {

void *loadOsLibrary(const std::string &LibraryPath) {
// Tells the system to not display the critical-error-handler message box.
// Instead, the system sends the error to the calling process.
// This is crucial for graceful handling of shared libs that can't be
// loaded, e.g. due to missing native run-times.

UINT SavedMode = SetErrorMode(SEM_FAILCRITICALERRORS);
// Exclude current directory from DLL search path
if (!SetDllDirectoryA("")) {
assert(false && "Failed to update DLL search path");
}

auto Result = (void *)LoadLibraryExA(LibraryPath.c_str(), NULL, NULL);
(void)SetErrorMode(SavedMode);
if (!SetDllDirectoryA(nullptr)) {
assert(false && "Failed to restore DLL search path");
}

return Result;
}

int unloadOsLibrary(void *Library) {
return (int)FreeLibrary((HMODULE)Library);
}

void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName) {
return reinterpret_cast<void *>(
GetProcAddress((HMODULE)Library, FunctionName.c_str()));
}

static std::filesystem::path getCurrentDSODirPath() {
wchar_t Path[MAX_PATH];
auto Handle =
getOSModuleHandle(reinterpret_cast<void *>(&getCurrentDSODirPath));
DWORD Ret = GetModuleFileName(
reinterpret_cast<HMODULE>(ExeModuleHandle == Handle ? 0 : Handle), Path,
MAX_PATH);
assert(Ret < MAX_PATH && "Path is longer than MAX_PATH?");
assert(Ret > 0 && "GetModuleFileName failed");
(void)Ret;

BOOL RetCode = PathRemoveFileSpec(Path);
assert(RetCode && "PathRemoveFileSpec failed");
(void)RetCode;

return std::filesystem::path(Path);
}

} // namespace detail
} // namespace _V1
} // namespace sycl
12 changes: 6 additions & 6 deletions sycl/source/detail/online_compiler/online_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#include <detail/load_library.hpp>
#include <sycl/detail/os_util.hpp>
#include <sycl/detail/ur.hpp>
#include <sycl/ext/intel/experimental/online_compiler.hpp>

#include <cstring>
Expand Down Expand Up @@ -94,12 +94,12 @@ compileToSPIRV(const std::string &Source, sycl::info::device_type DeviceType,
#else
static const std::string OclocLibraryName = "libocloc.so";
#endif
void *OclocLibrary = sycl::detail::ur::loadOsLibrary(OclocLibraryName);
void *OclocLibrary = sycl::detail::loadOsLibrary(OclocLibraryName);
if (!OclocLibrary)
throw online_compile_error("Cannot load ocloc library: " +
OclocLibraryName);
void *OclocVersionHandle =
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocVersion");
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocVersion");
// The initial versions of ocloc library did not have the oclocVersion()
// function. Those versions had the same API as the first version of ocloc
// library having that oclocVersion() function.
Expand All @@ -126,11 +126,11 @@ compileToSPIRV(const std::string &Source, sycl::info::device_type DeviceType,
".N), where (N >= " + std::to_string(CurrentVersionMinor) + ").");

CompileToSPIRVHandle =
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
if (!CompileToSPIRVHandle)
throw online_compile_error("Cannot load oclocInvoke() function");
FreeSPIRVOutputsHandle = sycl::detail::ur::getOsLibraryFuncAddress(
OclocLibrary, "oclocFreeOutput");
FreeSPIRVOutputsHandle =
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocFreeOutput");
if (!FreeSPIRVOutputsHandle)
throw online_compile_error("Cannot load oclocFreeOutput() function");
}
Expand Down
18 changes: 0 additions & 18 deletions sycl/source/detail/posix_ur.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,6 @@ namespace sycl {
inline namespace _V1 {
namespace detail::ur {

void *loadOsLibrary(const std::string &LibraryPath) {
// TODO: Check if the option RTLD_NOW is correct. Explore using
// RTLD_DEEPBIND option when there are multiple adapters.
void *so = dlopen(LibraryPath.c_str(), RTLD_NOW);
if (!so && trace(TraceLevel::TRACE_ALL)) {
char *Error = dlerror();
std::cerr << "SYCL_UR_TRACE: dlopen(" << LibraryPath << ") failed with <"
<< (Error ? Error : "unknown error") << ">" << std::endl;
}
return so;
}

int unloadOsLibrary(void *Library) { return dlclose(Library); }

void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName) {
return dlsym(Library, FunctionName.c_str());
}

void *getURLoaderLibrary() { return nullptr; }

} // namespace detail::ur
Expand Down
Loading
Loading