@@ -1925,20 +1925,27 @@ static pi_result SetKernelParamsAndLaunch(
19251925// The function is used as argument to piEnqueueNativeKernel which requires
19261926// that the passed function takes one void* argument.
19271927void DispatchNativeKernel (void *Blob) {
1928- // First value is a pointer to Corresponding CGExecKernel object.
1929- CGExecKernel *HostTask = *(CGExecKernel **)Blob;
1930- bool ShouldDeleteCG = static_cast <void **>(Blob)[1 ] != nullptr ;
1928+ void **CastedBlob = (void **)Blob;
1929+
1930+ std::vector<Requirement *> *Reqs =
1931+ static_cast <std::vector<Requirement *> *>(CastedBlob[0 ]);
1932+
1933+ std::unique_ptr<HostKernelBase> *HostKernel =
1934+ static_cast <std::unique_ptr<HostKernelBase> *>(CastedBlob[1 ]);
1935+
1936+ NDRDescT *NDRDesc = static_cast <NDRDescT *>(CastedBlob[2 ]);
19311937
19321938 // Other value are pointer to the buffers.
1933- void **NextArg = static_cast < void **>(Blob) + 2 ;
1934- for (detail::Requirement *Req : HostTask-> MRequirements )
1939+ void **NextArg = CastedBlob + 3 ;
1940+ for (detail::Requirement *Req : *Reqs )
19351941 Req->MData = *(NextArg++);
1936- HostTask->MHostKernel ->call (HostTask->MNDRDesc , nullptr );
19371942
1938- // The command group will (if not already was) be released in scheduler.
1939- // Hence we're free to deallocate it here.
1940- if (ShouldDeleteCG)
1941- delete HostTask;
1943+ (*HostKernel)->call (*NDRDesc, nullptr );
1944+
1945+ // The ownership of these objects have been passed to us, need to cleanup
1946+ delete Reqs;
1947+ delete HostKernel;
1948+ delete NDRDesc;
19421949}
19431950
19441951cl_int enqueueImpKernel (
@@ -2118,15 +2125,26 @@ cl_int ExecCGCommand::enqueueImp() {
21182125
21192126 // piEnqueueNativeKernel takes arguments blob which is passes to user
21202127 // function.
2121- // Reserve extra space for the pointer to CGExecKernel to restore context.
2122- std::vector<void *> ArgsBlob (HostTask->MArgs .size () + 2 );
2123- ArgsBlob[0 ] = (void *)HostTask;
2124- {
2125- std::intptr_t ShouldDeleteCG =
2126- static_cast <std::intptr_t >(MDeps.size () == 0 && MUsers.size () == 0 );
2127- ArgsBlob[1 ] = reinterpret_cast <void *>(ShouldDeleteCG);
2128- }
2129- void **NextArg = ArgsBlob.data () + 2 ;
2128+ // Need the following items to restore context in the host task.
2129+ // Make a copy on heap to "dettach" from the command group as it can be
2130+ // released before the host task completes.
2131+ std::vector<void *> ArgsBlob (HostTask->MArgs .size () + 3 );
2132+
2133+ std::vector<Requirement *> *CopyReqs =
2134+ new std::vector<Requirement *>(HostTask->MRequirements );
2135+
2136+ // Not actually a copy, but move. Should be OK as it's not expected that
2137+ // MHostKernel will be used elsewhere.
2138+ std::unique_ptr<HostKernelBase> *CopyHostKernel =
2139+ new std::unique_ptr<HostKernelBase>(std::move (HostTask->MHostKernel ));
2140+
2141+ NDRDescT *CopyNDRDesc = new NDRDescT (HostTask->MNDRDesc );
2142+
2143+ ArgsBlob[0 ] = (void *)CopyReqs;
2144+ ArgsBlob[1 ] = (void *)CopyHostKernel;
2145+ ArgsBlob[2 ] = (void *)CopyNDRDesc;
2146+
2147+ void **NextArg = ArgsBlob.data () + 3 ;
21302148
21312149 if (MQueue->is_host ()) {
21322150 for (ArgDesc &Arg : HostTask->MArgs ) {
0 commit comments