Skip to content

Commit f899fb3

Browse files
[SYCL] sycl::handler_impl keeps pointers to queue_impl, not shared_ptrs (#17941)
handle_impl is created internally, in automatic scope. So it's not need to control queue_impl lifetime from it, and it's correct to use raw pointers.
1 parent da6b33a commit f899fb3

File tree

6 files changed

+73
-53
lines changed

6 files changed

+73
-53
lines changed

sycl/include/sycl/handler.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,14 +439,22 @@ class __SYCL_EXPORT handler {
439439
/// is null if no secondary queue is associated with the submission.
440440
/// \param CallerNeedsEvent indicates if the event resulting from this handler
441441
/// is needed by the caller.
442+
#ifndef __INTEL_PREVIEW_BREAKING_CHANGES
443+
// TODO: This function is not used anymore, remove it in the next
444+
// ABI-breaking window.
442445
handler(std::shared_ptr<detail::queue_impl> Queue,
443446
std::shared_ptr<detail::queue_impl> PrimaryQueue,
444447
std::shared_ptr<detail::queue_impl> SecondaryQueue,
445448
bool CallerNeedsEvent);
449+
#endif
450+
__SYCL_DLL_LOCAL handler(std::shared_ptr<detail::queue_impl> Queue,
451+
detail::queue_impl *PrimaryQueue,
452+
detail::queue_impl *SecondaryQueue,
453+
bool CallerNeedsEvent);
446454

447455
/// Constructs SYCL handler from Graph.
448456
///
449-
/// The hander will add the command-group as a node to the graph rather than
457+
/// The handler will add the command-group as a node to the graph rather than
450458
/// enqueueing it straight away.
451459
///
452460
/// \param Graph is a SYCL command_graph

sycl/source/detail/handler_impl.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ enum class HandlerSubmissionState : std::uint8_t {
3131

3232
class handler_impl {
3333
public:
34-
handler_impl(std::shared_ptr<queue_impl> SubmissionPrimaryQueue,
35-
std::shared_ptr<queue_impl> SubmissionSecondaryQueue,
36-
bool EventNeeded)
37-
: MSubmissionPrimaryQueue(std::move(SubmissionPrimaryQueue)),
38-
MSubmissionSecondaryQueue(std::move(SubmissionSecondaryQueue)),
34+
handler_impl(queue_impl *SubmissionPrimaryQueue,
35+
queue_impl *SubmissionSecondaryQueue, bool EventNeeded)
36+
: MSubmissionPrimaryQueue(SubmissionPrimaryQueue),
37+
MSubmissionSecondaryQueue(SubmissionSecondaryQueue),
3938
MEventNeeded(EventNeeded) {};
4039

4140
handler_impl(
@@ -73,13 +72,13 @@ class handler_impl {
7372
/// Shared pointer to the primary queue implementation. This is different from
7473
/// the queue associated with the handler if the corresponding submission is
7574
/// a fallback from a previous submission.
76-
std::shared_ptr<queue_impl> MSubmissionPrimaryQueue;
75+
queue_impl *MSubmissionPrimaryQueue = nullptr;
7776

7877
/// Shared pointer to the secondary queue implementation. Nullptr if no
7978
/// secondary queue fallback was given in the associated submission. This is
8079
/// equal to the queue associated with the handler if the corresponding
8180
/// submission is a fallback from a previous submission.
82-
std::shared_ptr<queue_impl> MSubmissionSecondaryQueue;
81+
queue_impl *MSubmissionSecondaryQueue = nullptr;
8382

8483
/// Bool stores information about whether the event resulting from the
8584
/// corresponding work is required.

sycl/source/detail/queue_impl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ event queue_impl::submit_impl(const detail::type_erased_cgfo_ty &CGF,
360360
const detail::code_location &Loc,
361361
bool IsTopCodeLoc,
362362
const SubmissionInfo &SubmitInfo) {
363-
handler Handler(Self, PrimaryQueue, SecondaryQueue, CallerNeedsEvent);
363+
handler Handler(Self, PrimaryQueue.get(), SecondaryQueue.get(),
364+
CallerNeedsEvent);
364365
auto &HandlerImpl = detail::getSyclObjImpl(Handler);
365366
if (xptiTraceEnabled()) {
366367
Handler.saveCodeLoc(Loc, IsTopCodeLoc);

sycl/source/handler.cpp

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ fill_image_desc(const ext::oneapi::experimental::image_descriptor &ImgDesc) {
199199
}
200200

201201
static void
202-
fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
202+
fill_copy_args(detail::handler_impl *impl,
203203
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
204204
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
205205
ur_exp_image_copy_flags_t ImageCopyFlags, size_t SrcPitch,
@@ -266,7 +266,7 @@ fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
266266
}
267267

268268
static void
269-
fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
269+
fill_copy_args(detail::handler_impl *impl,
270270
const ext::oneapi::experimental::image_descriptor &Desc,
271271
ur_exp_image_copy_flags_t ImageCopyFlags,
272272
sycl::range<3> SrcOffset = {0, 0, 0},
@@ -281,7 +281,7 @@ fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
281281
}
282282

283283
static void
284-
fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
284+
fill_copy_args(detail::handler_impl *impl,
285285
const ext::oneapi::experimental::image_descriptor &Desc,
286286
ur_exp_image_copy_flags_t ImageCopyFlags, size_t SrcPitch,
287287
size_t DestPitch, sycl::range<3> SrcOffset = {0, 0, 0},
@@ -295,7 +295,7 @@ fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
295295
}
296296

297297
static void
298-
fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
298+
fill_copy_args(detail::handler_impl *impl,
299299
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
300300
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
301301
ur_exp_image_copy_flags_t ImageCopyFlags,
@@ -314,20 +314,32 @@ fill_copy_args(std::shared_ptr<detail::handler_impl> &impl,
314314

315315
handler::handler(std::shared_ptr<detail::queue_impl> Queue,
316316
bool CallerNeedsEvent)
317-
: handler(Queue, Queue, nullptr, CallerNeedsEvent) {}
317+
: impl(std::make_shared<detail::handler_impl>(Queue.get(), nullptr,
318+
CallerNeedsEvent)),
319+
MQueue(Queue) {}
318320

321+
#ifndef __INTEL_PREVIEW_BREAKING_CHANGES
322+
// TODO: This function is not used anymore, remove it in the next
323+
// ABI-breaking window.
319324
handler::handler(std::shared_ptr<detail::queue_impl> Queue,
320325
std::shared_ptr<detail::queue_impl> PrimaryQueue,
321326
std::shared_ptr<detail::queue_impl> SecondaryQueue,
322327
bool CallerNeedsEvent)
323-
: impl(std::make_shared<detail::handler_impl>(std::move(PrimaryQueue),
324-
std::move(SecondaryQueue),
328+
: impl(std::make_shared<detail::handler_impl>(
329+
PrimaryQueue.get(), SecondaryQueue.get(), CallerNeedsEvent)),
330+
MQueue(Queue) {}
331+
#endif
332+
333+
handler::handler(std::shared_ptr<detail::queue_impl> Queue,
334+
detail::queue_impl *PrimaryQueue,
335+
detail::queue_impl *SecondaryQueue, bool CallerNeedsEvent)
336+
: impl(std::make_shared<detail::handler_impl>(PrimaryQueue, SecondaryQueue,
325337
CallerNeedsEvent)),
326338
MQueue(std::move(Queue)) {}
327339

328340
handler::handler(
329341
std::shared_ptr<ext::oneapi::experimental::detail::graph_impl> Graph)
330-
: impl(std::make_shared<detail::handler_impl>(std::move(Graph))) {}
342+
: impl(std::make_shared<detail::handler_impl>(Graph)) {}
331343

332344
// Sets the submission state to indicate that an explicit kernel bundle has been
333345
// set. Throws a sycl::exception with errc::invalid if the current state
@@ -1339,7 +1351,7 @@ void handler::ext_oneapi_copy(
13391351
MSrcPtr = const_cast<void *>(Src);
13401352
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
13411353

1342-
detail::fill_copy_args(impl, DestImgDesc,
1354+
detail::fill_copy_args(impl.get(), DestImgDesc,
13431355
UR_EXP_IMAGE_COPY_FLAG_HOST_TO_DEVICE);
13441356

13451357
setType(detail::CGType::CopyImage);
@@ -1357,7 +1369,7 @@ void handler::ext_oneapi_copy(
13571369
MSrcPtr = const_cast<void *>(Src);
13581370
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
13591371

1360-
detail::fill_copy_args(impl, DestImgDesc,
1372+
detail::fill_copy_args(impl.get(), DestImgDesc,
13611373
UR_EXP_IMAGE_COPY_FLAG_HOST_TO_DEVICE, SrcOffset,
13621374
SrcExtent, DestOffset, {0, 0, 0}, CopyExtent);
13631375

@@ -1374,7 +1386,7 @@ void handler::ext_oneapi_copy(
13741386
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
13751387
MDstPtr = Dest;
13761388

1377-
detail::fill_copy_args(impl, SrcImgDesc,
1389+
detail::fill_copy_args(impl.get(), SrcImgDesc,
13781390
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_HOST);
13791391

13801392
setType(detail::CGType::CopyImage);
@@ -1393,7 +1405,7 @@ void handler::ext_oneapi_copy(
13931405
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
13941406
MDstPtr = Dest;
13951407

1396-
detail::fill_copy_args(impl, SrcImgDesc,
1408+
detail::fill_copy_args(impl.get(), SrcImgDesc,
13971409
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_HOST, SrcOffset,
13981410
{0, 0, 0}, DestOffset, DestExtent, CopyExtent);
13991411

@@ -1417,7 +1429,7 @@ void handler::ext_oneapi_copy(
14171429

14181430
if (ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_HOST_TO_DEVICE ||
14191431
ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_HOST) {
1420-
detail::fill_copy_args(impl, Desc, ImageCopyFlags, DeviceRowPitch,
1432+
detail::fill_copy_args(impl.get(), Desc, ImageCopyFlags, DeviceRowPitch,
14211433
DeviceRowPitch);
14221434
} else {
14231435
throw sycl::exception(make_error_code(errc::invalid),
@@ -1447,13 +1459,13 @@ void handler::ext_oneapi_copy(
14471459

14481460
// Fill the host extent based on the type of copy.
14491461
if (ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_HOST_TO_DEVICE) {
1450-
detail::fill_copy_args(impl, DeviceImgDesc, ImageCopyFlags, DeviceRowPitch,
1451-
DeviceRowPitch, SrcOffset, HostExtent, DestOffset,
1452-
{0, 0, 0}, CopyExtent);
1462+
detail::fill_copy_args(impl.get(), DeviceImgDesc, ImageCopyFlags,
1463+
DeviceRowPitch, DeviceRowPitch, SrcOffset,
1464+
HostExtent, DestOffset, {0, 0, 0}, CopyExtent);
14531465
} else if (ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_HOST) {
1454-
detail::fill_copy_args(impl, DeviceImgDesc, ImageCopyFlags, DeviceRowPitch,
1455-
DeviceRowPitch, SrcOffset, {0, 0, 0}, DestOffset,
1456-
HostExtent, CopyExtent);
1466+
detail::fill_copy_args(impl.get(), DeviceImgDesc, ImageCopyFlags,
1467+
DeviceRowPitch, DeviceRowPitch, SrcOffset, {0, 0, 0},
1468+
DestOffset, HostExtent, CopyExtent);
14571469
} else {
14581470
throw sycl::exception(make_error_code(errc::invalid),
14591471
"Copy Error: This copy function only performs host "
@@ -1475,7 +1487,7 @@ void handler::ext_oneapi_copy(
14751487
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
14761488
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
14771489

1478-
detail::fill_copy_args(impl, SrcImgDesc, DestImgDesc,
1490+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc,
14791491
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE);
14801492

14811493
setType(detail::CGType::CopyImage);
@@ -1495,7 +1507,7 @@ void handler::ext_oneapi_copy(
14951507
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
14961508
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
14971509

1498-
detail::fill_copy_args(impl, SrcImgDesc, DestImgDesc,
1510+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc,
14991511
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE, SrcOffset,
15001512
{0, 0, 0}, DestOffset, {0, 0, 0}, CopyExtent);
15011513

@@ -1514,7 +1526,7 @@ void handler::ext_oneapi_copy(
15141526
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
15151527
MDstPtr = Dest;
15161528

1517-
detail::fill_copy_args(impl, SrcImgDesc, DestImgDesc,
1529+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc,
15181530
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE, 0,
15191531
DestRowPitch);
15201532

@@ -1535,9 +1547,10 @@ void handler::ext_oneapi_copy(
15351547
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
15361548
MDstPtr = Dest;
15371549

1538-
detail::fill_copy_args(
1539-
impl, SrcImgDesc, DestImgDesc, UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE, 0,
1540-
DestRowPitch, SrcOffset, {0, 0, 0}, DestOffset, {0, 0, 0}, CopyExtent);
1550+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc,
1551+
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE, 0,
1552+
DestRowPitch, SrcOffset, {0, 0, 0}, DestOffset,
1553+
{0, 0, 0}, CopyExtent);
15411554

15421555
setType(detail::CGType::CopyImage);
15431556
}
@@ -1554,7 +1567,7 @@ void handler::ext_oneapi_copy(
15541567
MSrcPtr = const_cast<void *>(Src);
15551568
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
15561569

1557-
detail::fill_copy_args(impl, SrcImgDesc, DestImgDesc,
1570+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc,
15581571
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE, SrcRowPitch,
15591572
0);
15601573

@@ -1575,9 +1588,10 @@ void handler::ext_oneapi_copy(
15751588
MSrcPtr = const_cast<void *>(Src);
15761589
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
15771590

1578-
detail::fill_copy_args(
1579-
impl, SrcImgDesc, DestImgDesc, UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE,
1580-
SrcRowPitch, 0, SrcOffset, {0, 0, 0}, DestOffset, {0, 0, 0}, CopyExtent);
1591+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc,
1592+
UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE, SrcRowPitch,
1593+
0, SrcOffset, {0, 0, 0}, DestOffset, {0, 0, 0},
1594+
CopyExtent);
15811595

15821596
setType(detail::CGType::CopyImage);
15831597
}
@@ -1601,7 +1615,7 @@ void handler::ext_oneapi_copy(
16011615

16021616
if (ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE ||
16031617
ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_HOST_TO_HOST) {
1604-
detail::fill_copy_args(impl, SrcImgDesc, DestImgDesc, ImageCopyFlags,
1618+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc, ImageCopyFlags,
16051619
SrcRowPitch, DestRowPitch);
16061620
} else {
16071621
throw sycl::exception(make_error_code(errc::invalid),
@@ -1628,7 +1642,7 @@ void handler::ext_oneapi_copy(
16281642

16291643
if (ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE ||
16301644
ImageCopyFlags == UR_EXP_IMAGE_COPY_FLAG_HOST_TO_HOST) {
1631-
detail::fill_copy_args(impl, SrcImgDesc, DestImgDesc, ImageCopyFlags,
1645+
detail::fill_copy_args(impl.get(), SrcImgDesc, DestImgDesc, ImageCopyFlags,
16321646
SrcRowPitch, DestRowPitch, SrcOffset, {0, 0, 0},
16331647
DestOffset, {0, 0, 0}, CopyExtent);
16341648
} else {
@@ -1752,21 +1766,18 @@ void handler::ext_oneapi_signal_external_semaphore(
17521766

17531767
void handler::use_kernel_bundle(
17541768
const kernel_bundle<bundle_state::executable> &ExecBundle) {
1755-
std::shared_ptr<detail::queue_impl> PrimaryQueue =
1756-
impl->MSubmissionPrimaryQueue;
1757-
if ((!impl->MGraph &&
1758-
(PrimaryQueue->get_context() != ExecBundle.get_context())) ||
1769+
if ((!impl->MGraph && (impl->MSubmissionPrimaryQueue->get_context() !=
1770+
ExecBundle.get_context())) ||
17591771
(impl->MGraph &&
17601772
(impl->MGraph->getContext() != ExecBundle.get_context())))
17611773
throw sycl::exception(
17621774
make_error_code(errc::invalid),
17631775
"Context associated with the primary queue is different from the "
17641776
"context associated with the kernel bundle");
17651777

1766-
std::shared_ptr<detail::queue_impl> SecondaryQueue =
1767-
impl->MSubmissionSecondaryQueue;
1768-
if (SecondaryQueue &&
1769-
SecondaryQueue->get_context() != ExecBundle.get_context())
1778+
if (impl->MSubmissionSecondaryQueue &&
1779+
impl->MSubmissionSecondaryQueue->get_context() !=
1780+
ExecBundle.get_context())
17701781
throw sycl::exception(
17711782
make_error_code(errc::invalid),
17721783
"Context associated with the secondary queue is different from the "
@@ -1917,7 +1928,7 @@ void handler::verifyDeviceHasProgressGuarantee(
19171928
}
19181929

19191930
bool handler::supportsUSMMemcpy2D() {
1920-
for (const std::shared_ptr<detail::queue_impl> &QueueImpl :
1931+
for (detail::queue_impl *QueueImpl :
19211932
{impl->MSubmissionPrimaryQueue, impl->MSubmissionSecondaryQueue}) {
19221933
if (QueueImpl &&
19231934
!checkContextSupports(QueueImpl->getContextImplPtr(),
@@ -1928,7 +1939,7 @@ bool handler::supportsUSMMemcpy2D() {
19281939
}
19291940

19301941
bool handler::supportsUSMFill2D() {
1931-
for (const std::shared_ptr<detail::queue_impl> &QueueImpl :
1942+
for (detail::queue_impl *QueueImpl :
19321943
{impl->MSubmissionPrimaryQueue, impl->MSubmissionSecondaryQueue}) {
19331944
if (QueueImpl && !checkContextSupports(QueueImpl->getContextImplPtr(),
19341945
UR_CONTEXT_INFO_USM_FILL2D_SUPPORT))
@@ -1938,7 +1949,7 @@ bool handler::supportsUSMFill2D() {
19381949
}
19391950

19401951
bool handler::supportsUSMMemset2D() {
1941-
for (const std::shared_ptr<detail::queue_impl> &QueueImpl :
1952+
for (detail::queue_impl *QueueImpl :
19421953
{impl->MSubmissionPrimaryQueue, impl->MSubmissionSecondaryQueue}) {
19431954
if (QueueImpl && !checkContextSupports(QueueImpl->getContextImplPtr(),
19441955
UR_CONTEXT_INFO_USM_FILL2D_SUPPORT))

sycl/test/abi/sycl_symbols_windows.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@
401401
??0handler@_V1@sycl@@AEAA@V?$shared_ptr@Vgraph_impl@detail@experimental@oneapi@ext@_V1@sycl@@@std@@@Z
402402
??0handler@_V1@sycl@@AEAA@V?$shared_ptr@Vqueue_impl@detail@_V1@sycl@@@std@@00_N@Z
403403
??0handler@_V1@sycl@@AEAA@V?$shared_ptr@Vqueue_impl@detail@_V1@sycl@@@std@@_N@Z
404+
??0handler@_V1@sycl@@AEAA@V?$shared_ptr@Vqueue_impl@detail@_V1@sycl@@@std@@PEAVqueue_impl@detail@12@1_N@Z
404405
??0image_mem@experimental@oneapi@ext@_V1@sycl@@QEAA@$$QEAV012345@@Z
405406
??0image_mem@experimental@oneapi@ext@_V1@sycl@@QEAA@AEBUimage_descriptor@12345@AEBVdevice@45@AEBVcontext@45@@Z
406407
??0image_mem@experimental@oneapi@ext@_V1@sycl@@QEAA@AEBUimage_descriptor@12345@AEBVqueue@45@@Z

sycl/unittests/scheduler/SchedulerTestUtils.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ sycl::detail::Requirement getMockRequirement(const MemObjT &MemObj) {
239239

240240
class MockHandler : public sycl::handler {
241241
public:
242-
MockHandler(std::shared_ptr<sycl::detail::queue_impl> Queue,
242+
MockHandler(std::shared_ptr<sycl::detail::queue_impl> &Queue,
243243
bool CallerNeedsEvent)
244244
: sycl::handler(Queue, CallerNeedsEvent) {}
245245
// Methods
@@ -306,7 +306,7 @@ class MockHandler : public sycl::handler {
306306

307307
class MockHandlerCustomFinalize : public MockHandler {
308308
public:
309-
MockHandlerCustomFinalize(std::shared_ptr<sycl::detail::queue_impl> Queue,
309+
MockHandlerCustomFinalize(std::shared_ptr<sycl::detail::queue_impl> &Queue,
310310
bool CallerNeedsEvent)
311311
: MockHandler(Queue, CallerNeedsEvent) {}
312312

0 commit comments

Comments
 (0)