Skip to content

Commit ef9ae8e

Browse files
committed
[SYCL][NFC] Detach library loading helpers from UR
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
1 parent 3e98b3a commit ef9ae8e

File tree

10 files changed

+172
-98
lines changed

10 files changed

+172
-98
lines changed

sycl/include/sycl/detail/ur.hpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,6 @@ template <sycl::backend BE>
111111
__SYCL_EXPORT void *getPluginOpaqueData(void *opaquedata_arg);
112112

113113
namespace ur {
114-
// Function to load a shared library
115-
// Implementation is OS dependent
116-
void *loadOsLibrary(const std::string &Library);
117-
118-
// Function to unload a shared library
119-
// Implementation is OS dependent (see posix-ur.cpp and windows-ur.cpp)
120-
int unloadOsLibrary(void *Library);
121-
122-
// Function to get Address of a symbol defined in the shared
123-
// library, implementation is OS dependent.
124-
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName);
125-
126114
void *getURLoaderLibrary();
127115

128116
// Performs UR one-time initialization.

sycl/source/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ set(SYCL_COMMON_SOURCES
305305
"virtual_mem.cpp"
306306
"$<$<PLATFORM_ID:Windows>:detail/windows_ur.cpp>"
307307
"$<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:Darwin>>:detail/posix_ur.cpp>"
308+
"$<$<PLATFORM_ID:Windows>:detail/load_library_win.cpp>"
309+
"$<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:Darwin>>:detail/load_library_posix.cpp>"
308310
)
309311

310312
set(SYCL_NON_PREVIEW_SOURCES "${SYCL_COMMON_SOURCES}"

sycl/source/detail/jit_compiler.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <detail/jit_compiler.hpp>
1313
#include <detail/kernel_bundle_impl.hpp>
1414
#include <detail/kernel_impl.hpp>
15+
#include <detail/load_library.hpp>
1516
#include <detail/queue_impl.hpp>
1617
#include <detail/sycl_mem_obj_t.hpp>
1718
#include <sycl/detail/ur.hpp>
@@ -31,32 +32,32 @@ jit_compiler::jit_compiler() {
3132
auto checkJITLibrary = [this]() -> bool {
3233
static const std::string JITLibraryName = "libsycl-jit.so";
3334

34-
void *LibraryPtr = sycl::detail::ur::loadOsLibrary(JITLibraryName);
35+
void *LibraryPtr = sycl::detail::loadOsLibrary(JITLibraryName);
3536
if (LibraryPtr == nullptr) {
3637
printPerformanceWarning("Could not find JIT library " + JITLibraryName);
3738
return false;
3839
}
3940

4041
this->AddToConfigHandle = reinterpret_cast<AddToConfigFuncT>(
41-
sycl::detail::ur::getOsLibraryFuncAddress(LibraryPtr,
42-
"addToJITConfiguration"));
42+
sycl::detail::getOsLibraryFuncAddress(LibraryPtr,
43+
"addToJITConfiguration"));
4344
if (!this->AddToConfigHandle) {
4445
printPerformanceWarning(
4546
"Cannot resolve JIT library function entry point");
4647
return false;
4748
}
4849

4950
this->ResetConfigHandle = reinterpret_cast<ResetConfigFuncT>(
50-
sycl::detail::ur::getOsLibraryFuncAddress(LibraryPtr,
51-
"resetJITConfiguration"));
51+
sycl::detail::getOsLibraryFuncAddress(LibraryPtr,
52+
"resetJITConfiguration"));
5253
if (!this->ResetConfigHandle) {
5354
printPerformanceWarning(
5455
"Cannot resolve JIT library function entry point");
5556
return false;
5657
}
5758

5859
this->FuseKernelsHandle = reinterpret_cast<FuseKernelsFuncT>(
59-
sycl::detail::ur::getOsLibraryFuncAddress(LibraryPtr, "fuseKernels"));
60+
sycl::detail::getOsLibraryFuncAddress(LibraryPtr, "fuseKernels"));
6061
if (!this->FuseKernelsHandle) {
6162
printPerformanceWarning(
6263
"Cannot resolve JIT library function entry point");
@@ -65,8 +66,8 @@ jit_compiler::jit_compiler() {
6566

6667
this->MaterializeSpecConstHandle =
6768
reinterpret_cast<MaterializeSpecConstFuncT>(
68-
sycl::detail::ur::getOsLibraryFuncAddress(
69-
LibraryPtr, "materializeSpecConstants"));
69+
sycl::detail::getOsLibraryFuncAddress(LibraryPtr,
70+
"materializeSpecConstants"));
7071
if (!this->MaterializeSpecConstHandle) {
7172
printPerformanceWarning(
7273
"Cannot resolve JIT library function entry point");

sycl/source/detail/kernel_compiler/kernel_compiler_opencl.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include <sycl/detail/ur.hpp> // getOsLibraryFuncAddress
9+
#include <detail/load_library.hpp> // getOsLibraryFuncAddress
1010
#include <sycl/exception.hpp> // make_error_code
1111

1212
#include "kernel_compiler_opencl.hpp"
@@ -27,7 +27,7 @@ namespace detail {
2727
// ensures the OclocLibrary has the right version, etc.
2828
void checkOclocLibrary(void *OclocLibrary) {
2929
void *OclocVersionHandle =
30-
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocVersion");
30+
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocVersion");
3131
// The initial versions of ocloc library did not have the oclocVersion()
3232
// function. Those versions had the same API as the first version of ocloc
3333
// library having that oclocVersion() function.
@@ -67,7 +67,7 @@ void *loadOclocLibrary() {
6767
#endif
6868
void *tempPtr = OclocLibrary;
6969
if (tempPtr == nullptr) {
70-
tempPtr = sycl::detail::ur::loadOsLibrary(OclocLibraryName);
70+
tempPtr = sycl::detail::loadOsLibrary(OclocLibraryName);
7171

7272
if (tempPtr == nullptr)
7373
throw sycl::exception(make_error_code(errc::build),
@@ -104,12 +104,12 @@ void SetupLibrary(voidPtr &oclocInvokeHandle, voidPtr &oclocFreeOutputHandle,
104104
loadOclocLibrary();
105105

106106
oclocInvokeHandle =
107-
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
107+
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
108108
if (!oclocInvokeHandle)
109109
throw sycl::exception(the_errc, "Cannot load oclocInvoke() function");
110110

111-
oclocFreeOutputHandle = sycl::detail::ur::getOsLibraryFuncAddress(
112-
OclocLibrary, "oclocFreeOutput");
111+
oclocFreeOutputHandle =
112+
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocFreeOutput");
113113
if (!oclocFreeOutputHandle)
114114
throw sycl::exception(the_errc, "Cannot load oclocFreeOutput() function");
115115
}

sycl/source/detail/load_library.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//==-------------------------- load_library.hpp ----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Collection of helper OS-agnostic functions to dynamically load libraries and
10+
// query their symbols.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#pragma once
15+
16+
#include <string>
17+
18+
namespace sycl {
19+
inline namespace _V1 {
20+
namespace detail {
21+
22+
// Function to load a shared library
23+
// Implementation is OS dependent
24+
void *loadOsLibrary(const std::string &Library);
25+
26+
// Function to unload a shared library
27+
// Implementation is OS dependent (see posix-ur.cpp and windows-ur.cpp)
28+
int unloadOsLibrary(void *Library);
29+
30+
// Function to get Address of a symbol defined in the shared
31+
// library, implementation is OS dependent.
32+
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName);
33+
34+
} // namespace detail
35+
} // namespace _V1
36+
} // namespace sycl
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//==-------------------- load_library_posix.cpp ----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <detail/load_library.hpp>
10+
#include <sycl/detail/defines_elementary.hpp>
11+
#include <sycl/detail/iostream_proxy.hpp>
12+
#include <sycl/detail/ur.hpp>
13+
14+
#include <dlfcn.h>
15+
#include <string>
16+
17+
namespace sycl {
18+
inline namespace _V1 {
19+
namespace detail {
20+
21+
void *loadOsLibrary(const std::string &LibraryPath) {
22+
// TODO: Check if the option RTLD_NOW is correct. Explore using
23+
// RTLD_DEEPBIND option when there are multiple adapters.
24+
void *so = dlopen(LibraryPath.c_str(), RTLD_NOW);
25+
if (!so && ur::trace(ur::TraceLevel::TRACE_ALL)) {
26+
char *Error = dlerror();
27+
std::cerr << "SYCL_UR_TRACE: dlopen(" << LibraryPath << ") failed with <"
28+
<< (Error ? Error : "unknown error") << ">" << std::endl;
29+
}
30+
return so;
31+
}
32+
33+
int unloadOsLibrary(void *Library) { return dlclose(Library); }
34+
35+
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName) {
36+
return dlsym(Library, FunctionName.c_str());
37+
}
38+
39+
} // namespace detail
40+
} // namespace _V1
41+
} // namespace sycl
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//==-------------------- load_library_lin.cpp ------------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <detail/load_library.hpp>
10+
#include <detail/windows_os_utils.hpp>
11+
12+
#include <filesystem>
13+
#include <cassert>
14+
#include <string>
15+
#include <windows.h>
16+
#include <winreg.h>
17+
18+
namespace sycl {
19+
inline namespace _V1 {
20+
namespace detail {
21+
22+
void *loadOsLibrary(const std::string &LibraryPath) {
23+
// Tells the system to not display the critical-error-handler message box.
24+
// Instead, the system sends the error to the calling process.
25+
// This is crucial for graceful handling of shared libs that can't be
26+
// loaded, e.g. due to missing native run-times.
27+
28+
UINT SavedMode = SetErrorMode(SEM_FAILCRITICALERRORS);
29+
// Exclude current directory from DLL search path
30+
if (!SetDllDirectoryA("")) {
31+
assert(false && "Failed to update DLL search path");
32+
}
33+
34+
auto Result = (void *)LoadLibraryExA(LibraryPath.c_str(), NULL, NULL);
35+
(void)SetErrorMode(SavedMode);
36+
if (!SetDllDirectoryA(nullptr)) {
37+
assert(false && "Failed to restore DLL search path");
38+
}
39+
40+
return Result;
41+
}
42+
43+
int unloadOsLibrary(void *Library) {
44+
return (int)FreeLibrary((HMODULE)Library);
45+
}
46+
47+
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName) {
48+
return reinterpret_cast<void *>(
49+
GetProcAddress((HMODULE)Library, FunctionName.c_str()));
50+
}
51+
52+
static std::filesystem::path getCurrentDSODirPath() {
53+
wchar_t Path[MAX_PATH];
54+
auto Handle =
55+
getOSModuleHandle(reinterpret_cast<void *>(&getCurrentDSODirPath));
56+
DWORD Ret = GetModuleFileName(
57+
reinterpret_cast<HMODULE>(ExeModuleHandle == Handle ? 0 : Handle), Path,
58+
MAX_PATH);
59+
assert(Ret < MAX_PATH && "Path is longer than MAX_PATH?");
60+
assert(Ret > 0 && "GetModuleFileName failed");
61+
(void)Ret;
62+
63+
BOOL RetCode = PathRemoveFileSpec(Path);
64+
assert(RetCode && "PathRemoveFileSpec failed");
65+
(void)RetCode;
66+
67+
return std::filesystem::path(Path);
68+
}
69+
70+
} // namespace detail
71+
} // namespace _V1
72+
} // namespace sycl

sycl/source/detail/online_compiler/online_compiler.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include <detail/load_library.hpp>
910
#include <sycl/detail/os_util.hpp>
10-
#include <sycl/detail/ur.hpp>
1111
#include <sycl/ext/intel/experimental/online_compiler.hpp>
1212

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

128128
CompileToSPIRVHandle =
129-
sycl::detail::ur::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
129+
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocInvoke");
130130
if (!CompileToSPIRVHandle)
131131
throw online_compile_error("Cannot load oclocInvoke() function");
132-
FreeSPIRVOutputsHandle = sycl::detail::ur::getOsLibraryFuncAddress(
133-
OclocLibrary, "oclocFreeOutput");
132+
FreeSPIRVOutputsHandle =
133+
sycl::detail::getOsLibraryFuncAddress(OclocLibrary, "oclocFreeOutput");
134134
if (!FreeSPIRVOutputsHandle)
135135
throw online_compile_error("Cannot load oclocFreeOutput() function");
136136
}

sycl/source/detail/posix_ur.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,6 @@ namespace sycl {
1717
inline namespace _V1 {
1818
namespace detail::ur {
1919

20-
void *loadOsLibrary(const std::string &LibraryPath) {
21-
// TODO: Check if the option RTLD_NOW is correct. Explore using
22-
// RTLD_DEEPBIND option when there are multiple adapters.
23-
void *so = dlopen(LibraryPath.c_str(), RTLD_NOW);
24-
if (!so && trace(TraceLevel::TRACE_ALL)) {
25-
char *Error = dlerror();
26-
std::cerr << "SYCL_UR_TRACE: dlopen(" << LibraryPath << ") failed with <"
27-
<< (Error ? Error : "unknown error") << ">" << std::endl;
28-
}
29-
return so;
30-
}
31-
32-
int unloadOsLibrary(void *Library) { return dlclose(Library); }
33-
34-
void *getOsLibraryFuncAddress(void *Library, const std::string &FunctionName) {
35-
return dlsym(Library, FunctionName.c_str());
36-
}
37-
3820
void *getURLoaderLibrary() { return nullptr; }
3921

4022
} // namespace detail::ur

0 commit comments

Comments
 (0)