Skip to content

Commit

Permalink
[SYCL][NFC] Detach library loading helpers from UR
Browse files Browse the repository at this point in the history
This is a by-product of intel#14145. Functions to dynamically load a library and
query a symbol out of it should not be attached to UR, because they are used for
other libraries as well.

Moved them from `detail::ur` into `detail` namespace, outlined into a separate
header and removed declarations from public SYCL headers.

Fixes intel#14923
  • Loading branch information
AlexeySachkov committed Sep 24, 2024
1 parent 3e98b3a commit ef9ae8e
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 98 deletions.
12 changes: 0 additions & 12 deletions sycl/include/sycl/detail/ur.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,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);

void *getURLoaderLibrary();

// Performs UR one-time initialization.
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 @@ -12,6 +12,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 @@ -31,32 +32,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 @@ -65,8 +66,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

0 comments on commit ef9ae8e

Please sign in to comment.