Skip to content

Commit 6f620a4

Browse files
[SYCL] Handle exceptions on mutually exclusive handler operations (intel#4639)
Calling handler::set_specialization_constant after or before calling handler::use_kernel_bundle should cause the latter operation to throw a SYCL exception with error code errc::invalid. These changes enforces this behavior. This is achieved by introducing a handler_impl class that holds the current submission state. These states help detect the invalid operation order. Since adding the implementation to the handler class would be an ABI break, the handler_impl is inserted at the start of the extended members upon construction of the handler. This should be promoted in the next release that breaks ABI. Additionally these changes moves the unit tests in sycl/unittests/SYCL2020/SpecConstDefaultValues.cpp into the more general specialization constant unit test file sycl/unittests/SYCL2020/SpecializationConstant.cpp. Three additional test cases are added to ensure the exception behavior added with this PR. Signed-off-by: Steffen Larsen <steffen.larsen@intel.com>
1 parent c74a624 commit 6f620a4

File tree

9 files changed

+495
-181
lines changed

9 files changed

+495
-181
lines changed

sycl/include/CL/sycl/detail/cg.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ namespace detail {
9494
enum class ExtendedMembersType : unsigned int {
9595
HANDLER_KERNEL_BUNDLE = 0,
9696
HANDLER_MEM_ADVICE,
97+
// handler_impl is stored in the exended members to avoid breaking ABI.
98+
// TODO: This should be made a member of the handler class once ABI can be
99+
// broken.
100+
HANDLER_IMPL,
97101
};
98102

99103
// Holds a pointer to an object of an arbitrary type and an ID value which

sycl/include/CL/sycl/handler.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ template <typename T, int Dimensions, typename AllocatorT, typename Enable>
8080
class buffer;
8181
namespace detail {
8282

83+
class handler_impl;
8384
class kernel_impl;
8485
class queue_impl;
8586
class stream_impl;
@@ -1112,6 +1113,12 @@ class __SYCL_EXPORT handler {
11121113
kernel_parallel_for_work_group<KernelName, ElementType>(KernelFunc);
11131114
}
11141115

1116+
std::shared_ptr<detail::handler_impl> getHandlerImpl() const;
1117+
1118+
void setStateExplicitKernelBundle();
1119+
void setStateSpecConstSet();
1120+
bool isStateExplicitKernelBundle() const;
1121+
11151122
std::shared_ptr<detail::kernel_bundle_impl>
11161123
getOrInsertHandlerKernelBundle(bool Insert) const;
11171124

@@ -1146,6 +1153,8 @@ class __SYCL_EXPORT handler {
11461153
void set_specialization_constant(
11471154
typename std::remove_reference_t<decltype(SpecName)>::value_type Value) {
11481155

1156+
setStateSpecConstSet();
1157+
11491158
std::shared_ptr<detail::kernel_bundle_impl> KernelBundleImplPtr =
11501159
getOrInsertHandlerKernelBundle(/*Insert=*/true);
11511160

@@ -1158,6 +1167,11 @@ class __SYCL_EXPORT handler {
11581167
typename std::remove_reference_t<decltype(SpecName)>::value_type
11591168
get_specialization_constant() const {
11601169

1170+
if (isStateExplicitKernelBundle())
1171+
throw sycl::exception(make_error_code(errc::invalid),
1172+
"Specialization constants cannot be read after "
1173+
"explicitly setting the used kernel bundle");
1174+
11611175
std::shared_ptr<detail::kernel_bundle_impl> KernelBundleImplPtr =
11621176
getOrInsertHandlerKernelBundle(/*Insert=*/true);
11631177

@@ -1170,6 +1184,7 @@ class __SYCL_EXPORT handler {
11701184

11711185
void
11721186
use_kernel_bundle(const kernel_bundle<bundle_state::executable> &ExecBundle) {
1187+
setStateExplicitKernelBundle();
11731188
setHandlerKernelBundle(detail::getSyclObjImpl(ExecBundle));
11741189
}
11751190

sycl/source/detail/handler_impl.hpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//==---------------- handler_impl.hpp - SYCL handler -----------------------==//
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+
#pragma once
10+
11+
#include <detail/kernel_bundle_impl.hpp>
12+
13+
__SYCL_INLINE_NAMESPACE(cl) {
14+
namespace sycl {
15+
namespace detail {
16+
17+
using KernelBundleImplPtr = std::shared_ptr<detail::kernel_bundle_impl>;
18+
19+
enum class HandlerSubmissionState : std::uint8_t {
20+
NO_STATE = 0,
21+
EXPLICIT_KERNEL_BUNDLE_STATE,
22+
SPEC_CONST_SET_STATE,
23+
};
24+
25+
class handler_impl {
26+
public:
27+
handler_impl() = default;
28+
29+
void setStateExplicitKernelBundle() {
30+
if (MSubmissionState == HandlerSubmissionState::SPEC_CONST_SET_STATE)
31+
throw sycl::exception(
32+
make_error_code(errc::invalid),
33+
"Kernel bundle cannot be explicitly set after a specialization "
34+
"constant has been set");
35+
MSubmissionState = HandlerSubmissionState::EXPLICIT_KERNEL_BUNDLE_STATE;
36+
}
37+
38+
void setStateSpecConstSet() {
39+
if (MSubmissionState ==
40+
HandlerSubmissionState::EXPLICIT_KERNEL_BUNDLE_STATE)
41+
throw sycl::exception(make_error_code(errc::invalid),
42+
"Specialization constants cannot be set after "
43+
"explicitly setting the used kernel bundle");
44+
MSubmissionState = HandlerSubmissionState::SPEC_CONST_SET_STATE;
45+
}
46+
47+
bool isStateExplicitKernelBundle() const {
48+
return MSubmissionState ==
49+
HandlerSubmissionState::EXPLICIT_KERNEL_BUNDLE_STATE;
50+
}
51+
52+
/// Registers mutually exclusive submission states.
53+
HandlerSubmissionState MSubmissionState = HandlerSubmissionState::NO_STATE;
54+
};
55+
56+
} // namespace detail
57+
} // namespace sycl
58+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/handler.cpp

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <CL/sycl/stream.hpp>
1818
#include <detail/config.hpp>
1919
#include <detail/global_handler.hpp>
20+
#include <detail/handler_impl.hpp>
2021
#include <detail/kernel_bundle_impl.hpp>
2122
#include <detail/kernel_impl.hpp>
2223
#include <detail/queue_impl.hpp>
@@ -27,8 +28,56 @@ namespace sycl {
2728

2829
handler::handler(std::shared_ptr<detail::queue_impl> Queue, bool IsHost)
2930
: MQueue(std::move(Queue)), MIsHost(IsHost) {
30-
MSharedPtrStorage.emplace_back(
31-
std::make_shared<std::vector<detail::ExtendedMemberT>>());
31+
// Create extended members and insert handler_impl
32+
// TODO: When allowed to break ABI the handler_impl should be made a member
33+
// of the handler class.
34+
auto ExtendedMembers =
35+
std::make_shared<std::vector<detail::ExtendedMemberT>>();
36+
detail::ExtendedMemberT HandlerImplMember = {
37+
detail::ExtendedMembersType::HANDLER_IMPL,
38+
std::make_shared<detail::handler_impl>()};
39+
ExtendedMembers->push_back(std::move(HandlerImplMember));
40+
MSharedPtrStorage.push_back(std::move(ExtendedMembers));
41+
}
42+
43+
/// Gets the handler_impl at the start of the extended members.
44+
std::shared_ptr<detail::handler_impl> handler::getHandlerImpl() const {
45+
std::lock_guard<std::mutex> Lock(
46+
detail::GlobalHandler::instance().getHandlerExtendedMembersMutex());
47+
48+
assert(!MSharedPtrStorage.empty());
49+
50+
std::shared_ptr<std::vector<detail::ExtendedMemberT>> ExtendedMembersVec =
51+
detail::convertToExtendedMembers(MSharedPtrStorage[0]);
52+
53+
assert(ExtendedMembersVec->size() > 0);
54+
55+
auto HandlerImplMember = (*ExtendedMembersVec)[0];
56+
57+
assert(detail::ExtendedMembersType::HANDLER_IMPL == HandlerImplMember.MType);
58+
59+
return std::static_pointer_cast<detail::handler_impl>(
60+
HandlerImplMember.MData);
61+
}
62+
63+
// Sets the submission state to indicate that an explicit kernel bundle has been
64+
// set. Throws a sycl::exception with errc::invalid if the current state
65+
// indicates that a specialization constant has been set.
66+
void handler::setStateExplicitKernelBundle() {
67+
getHandlerImpl()->setStateExplicitKernelBundle();
68+
}
69+
70+
// Sets the submission state to indicate that a specialization constant has been
71+
// set. Throws a sycl::exception with errc::invalid if the current state
72+
// indicates that an explicit kernel bundle has been set.
73+
void handler::setStateSpecConstSet() {
74+
getHandlerImpl()->setStateSpecConstSet();
75+
}
76+
77+
// Returns true if the submission state is EXPLICIT_KERNEL_BUNDLE_STATE and
78+
// false otherwise.
79+
bool handler::isStateExplicitKernelBundle() const {
80+
return getHandlerImpl()->isStateExplicitKernelBundle();
3281
}
3382

3483
// Returns a shared_ptr to kernel_bundle stored in the extended members vector.
@@ -43,12 +92,11 @@ handler::getOrInsertHandlerKernelBundle(bool Insert) const {
4392

4493
assert(!MSharedPtrStorage.empty());
4594

46-
std::shared_ptr<std::vector<detail::ExtendedMemberT>> ExendedMembersVec =
95+
std::shared_ptr<std::vector<detail::ExtendedMemberT>> ExtendedMembersVec =
4796
detail::convertToExtendedMembers(MSharedPtrStorage[0]);
48-
4997
// Look for the kernel bundle in extended members
5098
std::shared_ptr<detail::kernel_bundle_impl> KernelBundleImpPtr;
51-
for (const detail::ExtendedMemberT &EMember : *ExendedMembersVec)
99+
for (const detail::ExtendedMemberT &EMember : *ExtendedMembersVec)
52100
if (detail::ExtendedMembersType::HANDLER_KERNEL_BUNDLE == EMember.MType) {
53101
KernelBundleImpPtr =
54102
std::static_pointer_cast<detail::kernel_bundle_impl>(EMember.MData);
@@ -66,8 +114,7 @@ handler::getOrInsertHandlerKernelBundle(bool Insert) const {
66114

67115
detail::ExtendedMemberT EMember = {
68116
detail::ExtendedMembersType::HANDLER_KERNEL_BUNDLE, KernelBundleImpPtr};
69-
70-
ExendedMembersVec->push_back(EMember);
117+
ExtendedMembersVec->push_back(EMember);
71118
}
72119

73120
return KernelBundleImpPtr;
@@ -85,16 +132,18 @@ void handler::setHandlerKernelBundle(
85132
std::shared_ptr<std::vector<detail::ExtendedMemberT>> ExendedMembersVec =
86133
detail::convertToExtendedMembers(MSharedPtrStorage[0]);
87134

88-
for (detail::ExtendedMemberT &EMember : *ExendedMembersVec)
135+
// Look for kernel bundle in extended members and overwrite it.
136+
for (detail::ExtendedMemberT &EMember : *ExendedMembersVec) {
89137
if (detail::ExtendedMembersType::HANDLER_KERNEL_BUNDLE == EMember.MType) {
90138
EMember.MData = NewKernelBundleImpPtr;
91139
return;
92140
}
141+
}
93142

143+
// Kernel bundle was set found so we add it.
94144
detail::ExtendedMemberT EMember = {
95145
detail::ExtendedMembersType::HANDLER_KERNEL_BUNDLE,
96146
NewKernelBundleImpPtr};
97-
98147
ExendedMembersVec->push_back(EMember);
99148
}
100149

sycl/test/abi/sycl_symbols_linux.dump

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3920,7 +3920,9 @@ _ZN2cl4sycl7handler18ext_oneapi_barrierERKSt6vectorINS0_5eventESaIS3_EE
39203920
_ZN2cl4sycl7handler18extractArgsAndReqsEv
39213921
_ZN2cl4sycl7handler20DisableRangeRoundingEv
39223922
_ZN2cl4sycl7handler20associateWithHandlerEPNS0_6detail16AccessorBaseHostENS0_6access6targetE
3923+
_ZN2cl4sycl7handler20setStateSpecConstSetEv
39233924
_ZN2cl4sycl7handler22setHandlerKernelBundleERKSt10shared_ptrINS0_6detail18kernel_bundle_implEE
3925+
_ZN2cl4sycl7handler28setStateExplicitKernelBundleEv
39243926
_ZN2cl4sycl7handler24GetRangeRoundingSettingsERmS2_S2_
39253927
_ZN2cl4sycl7handler28extractArgsAndReqsFromLambdaEPcmPKNS0_6detail19kernel_param_desc_tE
39263928
_ZN2cl4sycl7handler28extractArgsAndReqsFromLambdaEPcmPKNS0_6detail19kernel_param_desc_tEb
@@ -4263,6 +4265,8 @@ _ZNK2cl4sycl7context8get_infoILNS0_4info7contextE4225EEENS3_12param_traitsIS4_XT
42634265
_ZNK2cl4sycl7context8get_infoILNS0_4info7contextE4228EEENS3_12param_traitsIS4_XT_EE11return_typeEv
42644266
_ZNK2cl4sycl7context8get_infoILNS0_4info7contextE65552EEENS3_12param_traitsIS4_XT_EE11return_typeEv
42654267
_ZNK2cl4sycl7context9getNativeEv
4268+
_ZNK2cl4sycl7handler14getHandlerImplEv
4269+
_ZNK2cl4sycl7handler27isStateExplicitKernelBundleEv
42664270
_ZNK2cl4sycl7handler30getOrInsertHandlerKernelBundleEb
42674271
_ZNK2cl4sycl7program10get_kernelENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
42684272
_ZNK2cl4sycl7program10get_kernelENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb

sycl/test/abi/sycl_symbols_windows.dump

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,7 @@
20562056
?getElementSize@?$image_impl@$01@detail@sycl@cl@@QEBA_KXZ
20572057
?getElementSize@?$image_impl@$02@detail@sycl@cl@@QEBA_KXZ
20582058
?getEndTime@HostProfilingInfo@detail@sycl@cl@@QEBA_KXZ
2059+
?getHandlerImpl@handler@sycl@cl@@AEBA?AV?$shared_ptr@Vhandler_impl@detail@sycl@cl@@@std@@XZ
20592060
?getImageDesc@?$image_impl@$00@detail@sycl@cl@@AEAA?AU_pi_image_desc@@_N@Z
20602061
?getImageDesc@?$image_impl@$01@detail@sycl@cl@@AEAA?AU_pi_image_desc@@_N@Z
20612062
?getImageDesc@?$image_impl@$02@detail@sycl@cl@@AEAA?AU_pi_image_desc@@_N@Z
@@ -2331,6 +2332,7 @@
23312332
?isInterop@SYCLMemObjT@detail@sycl@cl@@QEBA_NXZ
23322333
?isOutOfRange@detail@sycl@cl@@YA_NV?$vec@H$03@23@W4addressing_mode@23@V?$range@$02@23@@Z
23332334
?isPathPresent@OSUtil@detail@sycl@cl@@SA_NAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
2335+
?isStateExplicitKernelBundle@handler@sycl@cl@@AEBA_NXZ
23342336
?isValidModeForDestinationAccessor@handler@sycl@cl@@CA_NW4mode@access@23@@Z
23352337
?isValidModeForSourceAccessor@handler@sycl@cl@@CA_NW4mode@access@23@@Z
23362338
?isValidTargetForExplicitOp@handler@sycl@cl@@CA_NW4target@access@23@@Z
@@ -3812,6 +3814,8 @@
38123814
?setPitches@?$image_impl@$00@detail@sycl@cl@@AEAAXXZ
38133815
?setPitches@?$image_impl@$01@detail@sycl@cl@@AEAAXXZ
38143816
?setPitches@?$image_impl@$02@detail@sycl@cl@@AEAAXXZ
3817+
?setStateExplicitKernelBundle@handler@sycl@cl@@AEAAXXZ
3818+
?setStateSpecConstSet@handler@sycl@cl@@AEAAXXZ
38153819
?setType@handler@sycl@cl@@AEAAXW4CGTYPE@CG@detail@23@@Z
38163820
?set_final_data@SYCLMemObjT@detail@sycl@cl@@QEAAX$$T@Z
38173821
?set_final_data_from_storage@SYCLMemObjT@detail@sycl@cl@@QEAAXXZ

sycl/unittests/SYCL2020/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
44
set(LLVM_REQUIRES_EH 1)
55
add_sycl_unittest(SYCL2020Tests OBJECT
66
GetNativeOpenCL.cpp
7-
SpecConstDefaultValues.cpp
7+
SpecializationConstant.cpp
88
KernelBundle.cpp
99
KernelID.cpp
1010
)

0 commit comments

Comments
 (0)