@@ -207,32 +207,40 @@ RPCServerTy::isDeviceUsingRPC(plugin::GenericDeviceTy &Device,
207207Error RPCServerTy::initDevice (plugin::GenericDeviceTy &Device,
208208 plugin::GenericGlobalHandlerTy &Handler,
209209 plugin::DeviceImageTy &Image) {
210+ std::lock_guard<decltype (BufferMutex)> Lock (BufferMutex);
210211 uint64_t NumPorts =
211212 std::min (Device.requestedRPCPortCount (), rpc::MAX_PORT_COUNT );
212- auto RPCBufferOrErr = Device.allocate (
213- rpc::Server::allocation_size (Device.getRPCNumLanes (), NumPorts), nullptr ,
214- TARGET_ALLOC_HOST );
215- if (!RPCBufferOrErr)
216- return RPCBufferOrErr.takeError ();
217-
218- void *RPCBuffer = *RPCBufferOrErr;
219- if (!RPCBuffer)
220- return plugin::Plugin::error (
221- error::ErrorCode::UNKNOWN ,
222- " failed to initialize RPC server for device %d" , Device.getDeviceId ());
223-
224- // The doorbell is used by AMDGPU targets to let the server thread be
225- // descheduled. It is optional and will be ignored if the fields are null.
226- rpc::Doorbell Doorbell{};
227- if (auto Err = Device.Plugin .initRPCDoorbell (Doorbell.value , Doorbell.mailbox ,
228- Doorbell.event_id ))
229- return Err;
230-
231- auto *DoorbellPtr = reinterpret_cast <rpc::Doorbell *>(
232- static_cast <uint8_t *>(RPCBuffer) + rpc::Server::doorbell_offset ());
233- std::memcpy (DoorbellPtr, &Doorbell, sizeof (rpc::Doorbell));
213+ void *RPCBuffer = Buffers[Device.getDeviceId ()];
214+ if (!RPCBuffer) {
215+ auto RPCBufferOrErr = Device.allocate (
216+ rpc::Server::allocation_size (Device.getRPCNumLanes (), NumPorts),
217+ nullptr , TARGET_ALLOC_HOST );
218+ if (!RPCBufferOrErr)
219+ return RPCBufferOrErr.takeError ();
220+
221+ RPCBuffer = *RPCBufferOrErr;
222+ if (!RPCBuffer)
223+ return plugin::Plugin::error (
224+ error::ErrorCode::UNKNOWN ,
225+ " failed to initialize RPC server for device %d" ,
226+ Device.getDeviceId ());
227+
228+ // The doorbell is used by AMDGPU targets to let the server thread be
229+ // descheduled. It is optional and will be ignored if the fields are null.
230+ rpc::Doorbell Doorbell{};
231+ if (auto Err = Device.Plugin .initRPCDoorbell (
232+ Doorbell.value , Doorbell.mailbox , Doorbell.event_id ))
233+ return Err;
234+
235+ auto *DoorbellPtr = reinterpret_cast <rpc::Doorbell *>(
236+ static_cast <uint8_t *>(RPCBuffer) + rpc::Server::doorbell_offset ());
237+ std::memcpy (DoorbellPtr, &Doorbell, sizeof (rpc::Doorbell));
238+
239+ Buffers[Device.getDeviceId ()] = RPCBuffer;
240+ Devices[Device.getDeviceId ()] = &Device;
241+ }
234242
235- // Get the address of the RPC client from the device .
243+ // Each image has its own client that must point at the shared buffer .
236244 plugin::GlobalTy ClientGlobal (" __llvm_rpc_client" , sizeof (rpc::Client));
237245 if (auto Err =
238246 Handler.getGlobalMetadataFromDevice (Device, Image, ClientGlobal))
@@ -242,9 +250,6 @@ Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device,
242250 if (auto Err = Device.dataSubmit (ClientGlobal.getPtr (), &client,
243251 sizeof (rpc::Client), nullptr ))
244252 return Err;
245- std::lock_guard<decltype (BufferMutex)> Lock (BufferMutex);
246- Buffers[Device.getDeviceId ()] = RPCBuffer;
247- Devices[Device.getDeviceId ()] = &Device;
248253
249254 return Error::success ();
250255}
0 commit comments