Skip to content

Commit 9a59ef5

Browse files
[SYCL] Introduce a fully-mocked PI plugin for unit tests (#6684)
The idea behind this PR is to introduce an infrastructure which allows to write unit-tests, which are not dependent on a presence of actual backends (like OpenCL, L0, etc.) or devices (like CPU, GPU, etc.). Motivation for the patch: host device is going to be removed and we have a number of in-tree LIT tests, which can't pass if there are no devices available, so they are likely to be removed/disabled in short-term (#6683), unless we move them into llvm-test-suite or unit-tests with new infrastructure suggested here. Signed-off-by: Larsen, Steffen <[email protected]> Co-authored-by: Sachkov, Alexey <[email protected]>
1 parent ec179b7 commit 9a59ef5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1365
-1858
lines changed

sycl/source/detail/global_handler.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,24 @@ void GlobalHandler::registerDefaultContextReleaseHandler() {
116116
static DefaultContextReleaseHandler handler{};
117117
}
118118

119+
// Note: Split from shutdown so it is available to the unittests for ensuring
120+
// that the mock plugin is the lone plugin.
121+
void GlobalHandler::unloadPlugins() {
122+
// Call to GlobalHandler::instance().getPlugins() initializes plugins. If
123+
// user application has loaded SYCL runtime, and never called any APIs,
124+
// there's no need to load and unload plugins.
125+
if (GlobalHandler::instance().MPlugins.Inst) {
126+
for (plugin &Plugin : GlobalHandler::instance().getPlugins()) {
127+
// PluginParameter is reserved for future use that can control
128+
// some parameters in the plugin tear-down process.
129+
// Currently, it is not used.
130+
void *PluginParameter = nullptr;
131+
Plugin.call<PiApiKind::piTearDown>(PluginParameter);
132+
Plugin.unload();
133+
}
134+
}
135+
}
136+
119137
void shutdown() {
120138
// Ensure neither host task is working so that no default context is accessed
121139
// upon its release
@@ -134,20 +152,10 @@ void shutdown() {
134152
GlobalHandler::instance().MScheduler.Inst.reset(nullptr);
135153
GlobalHandler::instance().MProgramManager.Inst.reset(nullptr);
136154

137-
// Call to GlobalHandler::instance().getPlugins() initializes plugins. If
138-
// user application has loaded SYCL runtime, and never called any APIs,
139-
// there's no need to load and unload plugins.
140-
if (GlobalHandler::instance().MPlugins.Inst) {
141-
for (plugin &Plugin : GlobalHandler::instance().getPlugins()) {
142-
// PluginParameter is reserved for future use that can control
143-
// some parameters in the plugin tear-down process.
144-
// Currently, it is not used.
145-
void *PluginParameter = nullptr;
146-
Plugin.call<PiApiKind::piTearDown>(PluginParameter);
147-
Plugin.unload();
148-
}
155+
// Clear the plugins and reset the instance if it was there.
156+
GlobalHandler::instance().unloadPlugins();
157+
if (GlobalHandler::instance().MPlugins.Inst)
149158
GlobalHandler::instance().MPlugins.Inst.reset(nullptr);
150-
}
151159

152160
// Release the rest of global resources.
153161
delete &GlobalHandler::instance();

sycl/source/detail/global_handler.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class GlobalHandler {
7171

7272
static void registerDefaultContextReleaseHandler();
7373

74+
void unloadPlugins();
75+
7476
private:
7577
friend void releaseDefaultContexts();
7678
friend void shutdown();

sycl/source/detail/posix_pi.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ void *loadOsLibrary(const std::string &PluginPath) {
2929
return so;
3030
}
3131

32-
int unloadOsLibrary(void *Library) { return dlclose(Library); }
32+
int unloadOsLibrary(void *Library) {
33+
// The mock plugin does not have an associated library, so we allow nullptr
34+
// here to avoid it trying to free a non-existent library.
35+
if (!Library)
36+
return 0;
37+
return dlclose(Library);
38+
}
3339

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

sycl/source/detail/windows_pi.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ void *loadOsLibrary(const std::string &PluginPath) {
4141
}
4242

4343
int unloadOsLibrary(void *Library) {
44+
// The mock plugin does not have an associated library, so we allow nullptr
45+
// here to avoid it trying to free a non-existent library.
46+
if (!Library)
47+
return 1;
4448
return (int)FreeLibrary((HMODULE)Library);
4549
}
4650

sycl/test/Unit/lit.cfg.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ def find_shlibpath_var():
7373
lit_config.warning("unable to inject shared library path on '{}'"
7474
.format(platform.system()))
7575

76+
# The mock plugin currently appears as an opencl plugin, but could be changed in
77+
# the future. To avoid it being filtered out we set the filter to use the *
78+
# wildcard.
79+
config.environment['SYCL_DEVICE_FILTER'] = "*"
80+
lit_config.note("Using Mock Plugin.")
81+
7682
config.environment['SYCL_CACHE_DIR'] = config.llvm_obj_root + "/sycl_cache"
77-
config.environment['SYCL_DEVICE_FILTER'] = lit_config.params.get('SYCL_PLUGIN', "opencl") + ",host"
78-
lit_config.note("Backend: {}".format(config.environment['SYCL_DEVICE_FILTER']))
7983
lit_config.note("SYCL cache directory: {}".format(config.environment['SYCL_CACHE_DIR']))

sycl/unittests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ add_subdirectory(Extensions)
4646
add_subdirectory(windows)
4747
add_subdirectory(event)
4848
add_subdirectory(buffer)
49+
add_subdirectory(context)

sycl/unittests/Extensions/DefaultContext.cpp

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <sycl/sycl.hpp>
1010

1111
#include <detail/config.hpp>
12-
#include <helpers/CommonRedefinitions.hpp>
1312
#include <helpers/PiMock.hpp>
1413
#include <helpers/ScopedEnvVar.hpp>
1514

@@ -25,17 +24,11 @@ TEST(DefaultContextTest, DefaultContextTest) {
2524
ScopedEnvVar var(EnableDefaultContextsName, "1",
2625
SYCLConfig<SYCL_ENABLE_DEFAULT_CONTEXTS>::reset);
2726

28-
sycl::platform Plt1{sycl::default_selector()};
29-
if (Plt1.is_host()) {
30-
std::cout << "Host platform does not support PI mock.\n";
31-
return;
32-
}
33-
sycl::unittest::PiMock Mock1{Plt1};
34-
setupDefaultMockAPIs(Mock1);
27+
sycl::unittest::PiMock Mock1;
28+
sycl::platform Plt1 = Mock1.getPlatform();
3529

36-
sycl::platform Plt2{sycl::default_selector()};
37-
sycl::unittest::PiMock Mock2{Plt2};
38-
setupDefaultMockAPIs(Mock2);
30+
sycl::unittest::PiMock Mock2;
31+
sycl::platform Plt2 = Mock2.getPlatform();
3932

4033
const sycl::device Dev1 = Plt1.get_devices()[0];
4134
const sycl::device Dev2 = Plt2.get_devices()[0];
@@ -55,13 +48,8 @@ TEST(DefaultContextTest, DefaultContextCanBeDisabled) {
5548
ScopedEnvVar var(EnableDefaultContextsName, "0",
5649
SYCLConfig<SYCL_ENABLE_DEFAULT_CONTEXTS>::reset);
5750

58-
sycl::platform Plt{sycl::default_selector()};
59-
if (Plt.is_host()) {
60-
std::cout << "Host platform does not support PI mock.\n";
61-
return;
62-
}
63-
sycl::unittest::PiMock Mock{Plt};
64-
setupDefaultMockAPIs(Mock);
51+
sycl::unittest::PiMock Mock;
52+
sycl::platform Plt = Mock.getPlatform();
6553

6654
bool catchException = false;
6755
try {

sycl/unittests/SYCL2020/GetNativeOpenCL.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include <sycl/backend/opencl.hpp>
1414
#include <sycl/sycl.hpp>
1515

16-
#include <helpers/CommonRedefinitions.hpp>
1716
#include <helpers/PiMock.hpp>
1817
#include <helpers/TestKernel.hpp>
1918

@@ -84,20 +83,8 @@ static pi_result redefinedUSMEnqueueMemset(pi_queue, void *, pi_int32, size_t,
8483
}
8584

8685
TEST(GetNative, GetNativeHandle) {
87-
platform Plt{default_selector()};
88-
if (Plt.get_backend() != backend::opencl) {
89-
std::cout << "Test is created for opencl only" << std::endl;
90-
return;
91-
}
92-
if (Plt.is_host()) {
93-
std::cout << "Not run on host - no PI events created in that case"
94-
<< std::endl;
95-
return;
96-
}
97-
TestCounter = 0;
98-
99-
unittest::PiMock Mock{Plt};
100-
setupDefaultMockAPIs(Mock);
86+
sycl::unittest::PiMock Mock;
87+
sycl::platform Plt = Mock.getPlatform();
10188

10289
Mock.redefine<detail::PiApiKind::piEventGetInfo>(redefinedEventGetInfo);
10390
Mock.redefine<detail::PiApiKind::piContextRetain>(redefinedContextRetain);
@@ -111,9 +98,8 @@ TEST(GetNative, GetNativeHandle) {
11198
Mock.redefine<detail::PiApiKind::piextUSMEnqueueMemset>(
11299
redefinedUSMEnqueueMemset);
113100

114-
default_selector Selector;
115101
context Context(Plt);
116-
queue Queue(Context, Selector);
102+
queue Queue(Context, default_selector_v);
117103

118104
auto Device = Queue.get_device();
119105

0 commit comments

Comments
 (0)