[Openmp-commits] [llvm] [openmp] [OFFLOAD][OPENMP] 6.0 compatible interop interface (PR #143491)
Kevin Sala Penades via Openmp-commits
openmp-commits at lists.llvm.org
Wed Jul 16 11:16:36 PDT 2025
================
@@ -193,119 +194,276 @@ __OMP_GET_INTEROP_TY3(const char *, type_desc)
__OMP_GET_INTEROP_TY3(const char *, rc_desc)
#undef __OMP_GET_INTEROP_TY3
-static const char *copyErrorString(llvm::Error &&Err) {
- // TODO: Use the error string while avoiding leaks.
- std::string ErrMsg = llvm::toString(std::move(Err));
- char *UsrMsg = reinterpret_cast<char *>(malloc(ErrMsg.size() + 1));
- strcpy(UsrMsg, ErrMsg.c_str());
- return UsrMsg;
-}
-
extern "C" {
-void __tgt_interop_init(ident_t *LocRef, int32_t Gtid,
- omp_interop_val_t *&InteropPtr,
- kmp_interop_type_t InteropType, int32_t DeviceId,
- int32_t Ndeps, kmp_depend_info_t *DepList,
- int32_t HaveNowait) {
- int32_t NdepsNoalias = 0;
- kmp_depend_info_t *NoaliasDepList = NULL;
- assert(InteropType != kmp_interop_type_unknown &&
- "Cannot initialize with unknown interop_type!");
- if (DeviceId == -1) {
- DeviceId = omp_get_default_device();
+omp_interop_val_t *__tgt_interop_get(ident_t *LocRef, int32_t InteropType,
+ int64_t DeviceNum, int32_t NumPrefers,
+ interop_spec_t *Prefers,
+ interop_ctx_t *Ctx, dep_pack_t *Deps) {
+
+ DP("Call to %s with device_num %" PRId64 ", interop type %" PRId32
+ ", number of preferred specs %" PRId32 "%s%s\n",
+ __func__, DeviceNum, InteropType, NumPrefers,
+ Ctx->flags.implicit ? " (implicit)" : "",
+ Ctx->flags.nowait ? " (nowait)" : "");
+
+ if (OffloadPolicy::get(*PM).Kind == OffloadPolicy::DISABLED)
+ return omp_interop_none;
+
+ // Now, try to create an interop with device_num.
+ if (DeviceNum == OFFLOAD_DEVICE_DEFAULT)
+ DeviceNum = omp_get_default_device();
+
+ auto gtid = Ctx->gtid;
+
+ if (InteropType == kmp_interop_type_targetsync) {
+ if (Ctx->flags.nowait)
+ DP("Warning: nowait flag on interop creation not supported yet. "
+ "Ignored\n");
+ if (Deps)
+ __kmpc_omp_wait_deps(LocRef, gtid, Deps->ndeps, Deps->deplist,
+ Deps->ndeps_noalias, Deps->noalias_deplist);
}
- if (InteropType == kmp_interop_type_tasksync) {
- __kmpc_omp_wait_deps(LocRef, Gtid, Ndeps, DepList, NdepsNoalias,
- NoaliasDepList);
+ auto DeviceOrErr = PM->getDevice(DeviceNum);
+ if (!DeviceOrErr) {
+ [[maybe_unused]] std::string ErrStr = toString(DeviceOrErr.takeError());
+ DP("Couldn't find device %" PRId64
+ " while constructing interop object: %s\n",
+ DeviceNum, ErrStr.c_str());
+ return omp_interop_none;
+ }
+ auto &Device = *DeviceOrErr;
+ omp_interop_val_t *Interop = omp_interop_none;
+ auto InteropSpec = Device.RTL->select_interop_preference(
+ DeviceNum, InteropType, NumPrefers, Prefers);
+ if (InteropSpec.fr_id == omp_fr_none) {
+ DP("Interop request not supported by device %" PRId64 "\n", DeviceNum);
+ return omp_interop_none;
+ }
+ DP("Selected interop preference is fr_id=%s%s impl_attrs=%" PRId64 "\n",
+ getForeignRuntimeIdToStr((omp_foreign_runtime_id_t)InteropSpec.fr_id),
+ InteropSpec.attrs.inorder ? " inorder" : "", InteropSpec.impl_attrs);
+
+ if (Ctx->flags.implicit) {
+ // This is a request for an RTL managed interop object.
+ // Get it from the InteropTbl if possible
+ if (PM->InteropTbl.size() > 0) {
+ for (auto iop : PM->InteropTbl) {
+ if (iop->isCompatibleWith(InteropType, InteropSpec, DeviceNum, gtid)) {
+ Interop = iop;
+ Interop->markDirty();
+ DP("Reused interop " DPxMOD " from device number %" PRId64
+ " for gtid %" PRId32 "\n",
+ DPxPTR(Interop), DeviceNum, gtid);
+ return Interop;
+ }
+ }
+ }
}
- InteropPtr = new omp_interop_val_t(DeviceId, InteropType);
-
- auto DeviceOrErr = PM->getDevice(DeviceId);
- if (!DeviceOrErr) {
- InteropPtr->err_str = copyErrorString(DeviceOrErr.takeError());
- return;
+ Interop = Device.RTL->create_interop(DeviceNum, InteropType, &InteropSpec);
+ DP("Created an interop " DPxMOD " from device number %" PRId64 "\n",
+ DPxPTR(Interop), DeviceNum);
+
+ if (Ctx->flags.implicit) {
+ // register the new implicit interop in the RTL
+ Interop->setOwner(gtid);
+ Interop->markDirty();
+ PM->InteropTbl.add(Interop);
+ } else {
+ Interop->setOwner(-1);
}
- DeviceTy &Device = *DeviceOrErr;
- if (!Device.RTL ||
- Device.RTL->init_device_info(DeviceId, &(InteropPtr)->device_info,
- &(InteropPtr)->err_str)) {
- delete InteropPtr;
- InteropPtr = omp_interop_none;
+ return Interop;
+}
+
+int __tgt_interop_use(ident_t *LocRef, omp_interop_val_t *Interop,
+ interop_ctx_t *Ctx, dep_pack_t *Deps) {
+ bool nowait = Ctx->flags.nowait;
+ DP("Call to %s with interop " DPxMOD ", nowait %" PRId32 "\n", __func__,
+ DPxPTR(Interop), nowait);
+ if (OffloadPolicy::get(*PM).Kind == OffloadPolicy::DISABLED || !Interop)
+ return OFFLOAD_FAIL;
+
+ if (Interop->interop_type == kmp_interop_type_targetsync) {
+ if (Deps) {
+ if (nowait) {
+ DP("Warning: nowait flag on interop use with dependences not supported"
+ "yet. Ignored\n");
+ nowait = false;
+ }
+
+ __kmpc_omp_wait_deps(LocRef, Ctx->gtid, Deps->ndeps, Deps->deplist,
+ Deps->ndeps_noalias, Deps->noalias_deplist);
+ }
}
- if (InteropType == kmp_interop_type_tasksync) {
- if (!Device.RTL ||
- Device.RTL->init_async_info(DeviceId, &(InteropPtr)->async_info)) {
- delete InteropPtr;
- InteropPtr = omp_interop_none;
+
+ if (Interop->async_info && Interop->async_info->Queue) {
+ if (nowait)
+ Interop->asyncBarrier();
+ else {
+ Interop->flush();
+ Interop->syncBarrier();
+ Interop->markClean();
}
}
+
+ return OFFLOAD_SUCCESS;
}
-void __tgt_interop_use(ident_t *LocRef, int32_t Gtid,
- omp_interop_val_t *&InteropPtr, int32_t DeviceId,
- int32_t Ndeps, kmp_depend_info_t *DepList,
- int32_t HaveNowait) {
- int32_t NdepsNoalias = 0;
- kmp_depend_info_t *NoaliasDepList = NULL;
- assert(InteropPtr && "Cannot use nullptr!");
- omp_interop_val_t *InteropVal = InteropPtr;
- if (DeviceId == -1) {
- DeviceId = omp_get_default_device();
- }
- assert(InteropVal != omp_interop_none &&
- "Cannot use uninitialized interop_ptr!");
- assert((DeviceId == -1 || InteropVal->device_id == DeviceId) &&
- "Inconsistent device-id usage!");
+int __tgt_interop_release(ident_t *LocRef, omp_interop_val_t *Interop,
+ interop_ctx_t *Ctx, dep_pack_t *Deps) {
+ DP("Call to %s with interop " DPxMOD "\n", __func__, DPxPTR(Interop));
- auto DeviceOrErr = PM->getDevice(DeviceId);
- if (!DeviceOrErr) {
- InteropPtr->err_str = copyErrorString(DeviceOrErr.takeError());
- return;
+ if (OffloadPolicy::get(*PM).Kind == OffloadPolicy::DISABLED || !Interop)
+ return OFFLOAD_FAIL;
+
+ if (Interop->interop_type == kmp_interop_type_targetsync) {
+ if (Ctx->flags.nowait)
+ DP("Warning: nowait flag on interop destroy not supported "
+ "yet. Ignored\n");
+ if (Deps) {
+ __kmpc_omp_wait_deps(LocRef, Ctx->gtid, Deps->ndeps, Deps->deplist,
+ Deps->ndeps_noalias, Deps->noalias_deplist);
+ }
}
- if (InteropVal->interop_type == kmp_interop_type_tasksync) {
- __kmpc_omp_wait_deps(LocRef, Gtid, Ndeps, DepList, NdepsNoalias,
- NoaliasDepList);
+ return Interop->release();
+}
+
+EXTERN int ompx_interop_add_completion_callback(omp_interop_val_t *Interop,
+ ompx_interop_cb_t *cb,
+ void *data) {
+ DP("Call to %s with interop " DPxMOD ", property callback " DPxMOD
+ "and data " DPxMOD "\n",
+ __func__, DPxPTR(Interop), DPxPTR(cb), DPxPTR(data));
+
+ if (OffloadPolicy::get(*PM).Kind == OffloadPolicy::DISABLED || !Interop)
+ return omp_irc_other;
+
+ Interop->addCompletionCb(cb, data);
+
+ return omp_irc_success;
+}
+
+} // extern "C"
+
+bool omp_interop_val_t::isCompatibleWith(int32_t InteropType,
+ const interop_spec_t &Spec) {
+ if (interop_type != InteropType)
+ return false;
+ if (Spec.fr_id != fr_id)
+ return false;
+ if (Spec.attrs.inorder != attrs.inorder)
+ return false;
+ if (Spec.impl_attrs != impl_attrs)
+ return false;
+
+ return true;
+}
+
+bool omp_interop_val_t::isCompatibleWith(int32_t InteropType,
+ const interop_spec_t &Spec,
+ int64_t DeviceNum, int GTID) {
+ if (device_id != DeviceNum)
+ return false;
+
+ if (GTID != OwnerGtid)
+ return false;
+
+ return isCompatibleWith(InteropType, Spec);
+}
+
+int32_t omp_interop_val_t::flush(DeviceTy &Device) {
+ return Device.RTL->flush_queue(this);
+}
+
+int32_t omp_interop_val_t::sync_barrier(DeviceTy &Device) {
+ if (Device.RTL->sync_barrier(this) != OFFLOAD_SUCCESS) {
+ FATAL_MESSAGE(device_id, "Interop sync barrier failed for %p object\n",
+ this);
}
- // TODO Flush the queue associated with the interop through the plugin
+ DP("Calling completion callbacks for " DPxMOD "\n", DPxPTR(this));
+ runCompletionCbs();
+ return OFFLOAD_SUCCESS;
+}
+
+int32_t omp_interop_val_t::async_barrier(DeviceTy &Device) {
+ return Device.RTL->async_barrier(this);
}
-void __tgt_interop_destroy(ident_t *LocRef, int32_t Gtid,
- omp_interop_val_t *&InteropPtr, int32_t DeviceId,
- int32_t Ndeps, kmp_depend_info_t *DepList,
- int32_t HaveNowait) {
- int32_t NdepsNoalias = 0;
- kmp_depend_info_t *NoaliasDepList = NULL;
- assert(InteropPtr && "Cannot use nullptr!");
- omp_interop_val_t *InteropVal = InteropPtr;
- if (DeviceId == -1) {
- DeviceId = omp_get_default_device();
+int32_t omp_interop_val_t::release(DeviceTy &Device) {
+ if (async_info != nullptr && (!hasOwner() || !isClean())) {
+ flush();
+ syncBarrier();
----------------
kevinsala wrote:
I guess the device can be passed directly to these functions.
https://github.com/llvm/llvm-project/pull/143491
More information about the Openmp-commits
mailing list