diff --git a/sycl/source/detail/scheduler/commands.cpp b/sycl/source/detail/scheduler/commands.cpp index 61ffe777f4c45..7639c14c7424c 100644 --- a/sycl/source/detail/scheduler/commands.cpp +++ b/sycl/source/detail/scheduler/commands.cpp @@ -1925,20 +1925,27 @@ static pi_result SetKernelParamsAndLaunch( // The function is used as argument to piEnqueueNativeKernel which requires // that the passed function takes one void* argument. void DispatchNativeKernel(void *Blob) { - // First value is a pointer to Corresponding CGExecKernel object. - CGExecKernel *HostTask = *(CGExecKernel **)Blob; - bool ShouldDeleteCG = static_cast(Blob)[1] != nullptr; + void **CastedBlob = (void **)Blob; + + std::vector *Reqs = + static_cast *>(CastedBlob[0]); + + std::unique_ptr *HostKernel = + static_cast *>(CastedBlob[1]); + + NDRDescT *NDRDesc = static_cast(CastedBlob[2]); // Other value are pointer to the buffers. - void **NextArg = static_cast(Blob) + 2; - for (detail::Requirement *Req : HostTask->MRequirements) + void **NextArg = CastedBlob + 3; + for (detail::Requirement *Req : *Reqs) Req->MData = *(NextArg++); - HostTask->MHostKernel->call(HostTask->MNDRDesc, nullptr); - // The command group will (if not already was) be released in scheduler. - // Hence we're free to deallocate it here. - if (ShouldDeleteCG) - delete HostTask; + (*HostKernel)->call(*NDRDesc, nullptr); + + // The ownership of these objects have been passed to us, need to cleanup + delete Reqs; + delete HostKernel; + delete NDRDesc; } cl_int enqueueImpKernel( @@ -2118,15 +2125,26 @@ cl_int ExecCGCommand::enqueueImp() { // piEnqueueNativeKernel takes arguments blob which is passes to user // function. - // Reserve extra space for the pointer to CGExecKernel to restore context. - std::vector ArgsBlob(HostTask->MArgs.size() + 2); - ArgsBlob[0] = (void *)HostTask; - { - std::intptr_t ShouldDeleteCG = - static_cast(MDeps.size() == 0 && MUsers.size() == 0); - ArgsBlob[1] = reinterpret_cast(ShouldDeleteCG); - } - void **NextArg = ArgsBlob.data() + 2; + // Need the following items to restore context in the host task. + // Make a copy on heap to "dettach" from the command group as it can be + // released before the host task completes. + std::vector ArgsBlob(HostTask->MArgs.size() + 3); + + std::vector *CopyReqs = + new std::vector(HostTask->MRequirements); + + // Not actually a copy, but move. Should be OK as it's not expected that + // MHostKernel will be used elsewhere. + std::unique_ptr *CopyHostKernel = + new std::unique_ptr(std::move(HostTask->MHostKernel)); + + NDRDescT *CopyNDRDesc = new NDRDescT(HostTask->MNDRDesc); + + ArgsBlob[0] = (void *)CopyReqs; + ArgsBlob[1] = (void *)CopyHostKernel; + ArgsBlob[2] = (void *)CopyNDRDesc; + + void **NextArg = ArgsBlob.data() + 3; if (MQueue->is_host()) { for (ArgDesc &Arg : HostTask->MArgs) {