From 1c6d774baad44fa758899e467cd24df80edc2e65 Mon Sep 17 00:00:00 2001 From: fineg74 <61437305+fineg74@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:53:00 -0800 Subject: [PATCH] [OFFLOAD] Extend olMemRegister API to handle cases when a memory block may have been mapped outside of liboffload. (#172226) This PR adds extends liboffload olMemRegister API to handle a case when a memory block may have been mapped before calling olMemRegister to support some use cases in libomptarget --- offload/liboffload/API/Memory.td | 35 ++-- offload/liboffload/src/OffloadImpl.cpp | 11 +- .../common/include/PluginInterface.h | 99 +++++------- .../common/src/PluginInterface.cpp | 151 +++++++----------- .../OffloadAPI/memory/olMemRegister.cpp | 99 +++++++++--- 5 files changed, 203 insertions(+), 192 deletions(-) diff --git a/offload/liboffload/API/Memory.td b/offload/liboffload/API/Memory.td index 7e8c013819f8..4a62bbc8ea1a 100644 --- a/offload/liboffload/API/Memory.td +++ b/offload/liboffload/API/Memory.td @@ -24,6 +24,15 @@ def ol_memory_register_flags_t : Typedef { let value = "uint32_t"; } +def ol_memory_register_flag_t : Enum { + let desc = "Memory registering/locking flags"; + let is_bit_field = 1; + let etors =[ + Etor<"LOCK_MEMORY", "Page-lock the memory">, + Etor<"UNLOCK_MEMORY", "Page-unlock the memory">, + ]; +} + def olMemAlloc : Function { let desc = "Creates a memory allocation on the specified device."; let details = [ @@ -138,13 +147,14 @@ def olMemFill : Function { } def olMemRegister : Function { - let desc = "Register and page-lock host memory so it can be accessible by the device."; + let desc = "Register and optionally page-lock host memory so it can be accessible by the device."; let details = [ - "Pins host memory to optimize transfers and returns the device accessible", - "stable pointer that devices should use for memory transfers involving the host", - "pinned allocation. If the buffer intersects with other existing buffer,", - "a new user will be registered. A partial overlapping is not allowed.", - "The pinned pointer can be accessed both on host and device and", + "Registers host memory and optionally page-locks it to optimize transfers and returns", + "the device accessible stable pointer that devices should use for memory transfers", + "involving the host pinned allocation. If the buffer intersects with other existing buffer,", + "if the buffer is locked outside of this API, or Flags doesn't contain LOCK_MEMORY + "flag a new user will be registered. Partial overlapping with an already registered range is", + "not allowed. The pinned pointer can be accessed both on host and device and", "no guarantees are made about consistency.", "The pinned pointer should be used to execute memory transfers", "as it is a stable pointer for memory access." @@ -153,7 +163,7 @@ def olMemRegister : Function { Param<"ol_device_handle_t", "Device", "handle of the device", PARAM_IN>, Param<"void *", "Ptr", "host pointer", PARAM_IN>, Param<"size_t", "Size", "size of the memory in bytes", PARAM_IN>, - Param<"ol_memory_register_flags_t", "Flags", "flags. Reserved for future use", PARAM_IN>, + Param<"ol_memory_register_flags_t", "Flags", "flags controlling various aspects of registration", PARAM_IN>, Param<"void**", "PinnedPtr", "pointer to the pinned memory", PARAM_OUT> ]; let returns = [ @@ -164,15 +174,16 @@ def olMemRegister : Function { } def olMemUnregister : Function { - let desc = "Unregister and page-unlock host memory."; + let desc = "Unregister host memory and optionally page-unlock it."; let details = [ - "Unpins host memory that was previously pinned or unregister the buffer", - "if other users are still using the buffer. If no users are using the buffer", - "the memory is unlocked." + "Unregisters host memory and optionally page-unlocks it.", + "If other users are still using the buffer or Flags doesn't contain UNLOCK_MEMORY flag" + "the memory is unregistered, otherwise the memory is unlocked." ]; let params = [ Param<"ol_device_handle_t", "Device", "handle of the device", PARAM_IN>, - Param<"void *", "Ptr", "host pointer", PARAM_IN> + Param<"void *", "Ptr", "host pointer", PARAM_IN>, + Param<"ol_memory_register_flags_t", "Flags", "flags controlling various aspects of unregistration", PARAM_IN>, ]; let returns = []; } diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index 939664ff5925..768d81de59be 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -1176,8 +1176,9 @@ Error olLaunchHostFunction_impl(ol_queue_handle_t Queue, } Error olMemRegister_impl(ol_device_handle_t Device, void *Ptr, size_t Size, - ol_memory_register_flags_t flags, void **LockedPtr) { - Expected LockedPtrOrErr = Device->Device->dataLock(Ptr, Size); + ol_memory_register_flags_t Flags, void **LockedPtr) { + Expected LockedPtrOrErr = Device->Device->registerMemory( + Ptr, Size, Flags & OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY); if (!LockedPtrOrErr) return LockedPtrOrErr.takeError(); @@ -1186,8 +1187,10 @@ Error olMemRegister_impl(ol_device_handle_t Device, void *Ptr, size_t Size, return Error::success(); } -Error olMemUnregister_impl(ol_device_handle_t Device, void *Ptr) { - return Device->Device->dataUnlock(Ptr); +Error olMemUnregister_impl(ol_device_handle_t Device, void *Ptr, + ol_memory_register_flags_t Flags) { + return Device->Device->unregisterMemory( + Ptr, Flags & OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY); } Error olQueryQueue_impl(ol_queue_handle_t Queue, bool *IsQueueWorkCompleted) { diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h index 19db44cf0465..4c15294999d7 100644 --- a/offload/plugins-nextgen/common/include/PluginInterface.h +++ b/offload/plugins-nextgen/common/include/PluginInterface.h @@ -620,12 +620,6 @@ class PinnedAllocationMapTy { /// Reference to the corresponding device. GenericDeviceTy &Device; - /// Indicate whether mapped host buffers should be locked automatically. - bool LockMappedBuffers; - - /// Indicate whether failures when locking mapped buffers should be ignored. - bool IgnoreLockMappedFailures; - /// Find an allocation that intersects with \p HstPtr pointer. Assume the /// map's mutex is acquired. const EntryTy *findIntersecting(const void *HstPtr) const { @@ -691,34 +685,7 @@ class PinnedAllocationMapTy { public: /// Create the map of pinned allocations corresponding to a specific device. - PinnedAllocationMapTy(GenericDeviceTy &Device) : Device(Device) { - - // Envar that indicates whether mapped host buffers should be locked - // automatically. The possible values are boolean (on/off) and a special: - // off: Mapped host buffers are not locked. - // on: Mapped host buffers are locked in a best-effort approach. - // Failure to lock the buffers are silent. - // mandatory: Mapped host buffers are always locked and failures to lock - // a buffer results in a fatal error. - StringEnvar OMPX_LockMappedBuffers("LIBOMPTARGET_LOCK_MAPPED_HOST_BUFFERS", - "off"); - - bool Enabled; - if (StringParser::parse(OMPX_LockMappedBuffers.get().data(), Enabled)) { - // Parsed as a boolean value. Enable the feature if necessary. - LockMappedBuffers = Enabled; - IgnoreLockMappedFailures = true; - } else if (OMPX_LockMappedBuffers.get() == "mandatory") { - // Enable the feature and failures are fatal. - LockMappedBuffers = true; - IgnoreLockMappedFailures = false; - } else { - // Disable by default. - ODBG(OLDT_Alloc) << "Invalid value LIBOMPTARGET_LOCK_MAPPED_HOST_BUFFERS=" - << OMPX_LockMappedBuffers.get(); - LockMappedBuffers = false; - } - } + PinnedAllocationMapTy(GenericDeviceTy &Device) : Device(Device) {} /// Register a buffer that was recently allocated as a locked host buffer. /// None of the already registered pinned allocations should intersect with @@ -734,25 +701,20 @@ public: /// not be unlocked by this function. Error unregisterHostBuffer(void *HstPtr); - /// Lock the host buffer at \p HstPtr or register a new user if it intersects - /// with an already existing one. A partial overlapping with extension is not - /// allowed. The function returns the device accessible pointer of the pinned - /// buffer. The buffer must be unlocked using the unlockHostBuffer function. - Expected lockHostBuffer(void *HstPtr, size_t Size); + /// Registers and optionally page-locks host memory at \p HstPtr . Registers + /// a new user if it intersects with an already existing one, locked outside + /// of this API or passed LockMemory parameter as false. A partial overlapping + /// with extension is not allowed. The function returns the device accessible + /// pointer of the pinned buffer. The buffer must be unlocked using the + /// unlockHostBuffer function. + Expected registerMemory(void *HstPtr, size_t Size, + bool LockMemory = true); - /// Unlock the host buffer at \p HstPtr or unregister a user if other users - /// are still using the pinned allocation. If this was the last user, the - /// pinned allocation is removed from the map and the memory is unlocked. - Error unlockHostBuffer(void *HstPtr); - - /// Lock or register a host buffer that was recently mapped by libomptarget. - /// This behavior is applied if LIBOMPTARGET_LOCK_MAPPED_HOST_BUFFERS is - /// enabled. Even if not enabled, externally locked buffers are registered - /// in order to optimize their transfers. - Error lockMappedHostBuffer(void *HstPtr, size_t Size); - - /// Unlock or unregister a host buffer that was unmapped by libomptarget. - Error unlockUnmappedHostBuffer(void *HstPtr); + /// Unregisters and optionally unlocks host memory at \p HstPtr . Unregister a + /// user if other users are still using the pinned allocation or passed + /// UnlockMemory parameter as false. If this was the last user, the pinned + /// allocation is removed from the map and the memory is unlocked. + Error unregisterMemory(void *HstPtr, bool UnlockMemory = true); /// Return the device accessible pointer associated to the host pinned /// allocation which the \p HstPtr belongs, if any. Return null in case the @@ -880,16 +842,17 @@ struct GenericDeviceTy : public DeviceAllocatorTy { /// Deallocate data from the device or involving the device. Error dataDelete(void *TgtPtr, TargetAllocTy Kind); - /// Pin host memory to optimize transfers and return the device accessible - /// pointer that devices should use for memory transfers involving the host - /// pinned allocation. - Expected dataLock(void *HstPtr, int64_t Size) { - return PinnedAllocs.lockHostBuffer(HstPtr, Size); + /// Pin or register host memory to optimize transfers and return the device + /// accessible pointer that devices should use for memory transfers involving + /// the host pinned allocation. + Expected registerMemory(void *HstPtr, int64_t Size, + bool LockMemory = true) { + return PinnedAllocs.registerMemory(HstPtr, Size, LockMemory); } - /// Unpin a host memory buffer that was previously pinned. - Error dataUnlock(void *HstPtr) { - return PinnedAllocs.unlockHostBuffer(HstPtr); + /// Unregisters and optionally page-unlocks a host memory buffer. + Error unregisterMemory(void *HstPtr, bool UnlockMemory = true) { + return PinnedAllocs.unregisterMemory(HstPtr, UnlockMemory); } /// Lock the host buffer \p HstPtr with \p Size bytes with the vendor-specific @@ -905,14 +868,20 @@ struct GenericDeviceTy : public DeviceAllocatorTy { /// as source/destination of memory transfers. We can use this information to /// lock the host buffer and optimize its memory transfers. Error notifyDataMapped(void *HstPtr, int64_t Size) { - return PinnedAllocs.lockMappedHostBuffer(HstPtr, Size); + auto Err = PinnedAllocs.registerMemory(HstPtr, Size, LockMappedBuffers); + if (!Err && !IgnoreLockMappedFailures) + return Err.takeError(); + return Plugin::success(); } /// Mark the host buffer with address \p HstPtr as unmapped. This means that /// libomptarget removed an existing mapping. If the plugin locked the buffer /// in notifyDataMapped, this function should unlock it. Error notifyDataUnmapped(void *HstPtr) { - return PinnedAllocs.unlockUnmappedHostBuffer(HstPtr); + auto Err = PinnedAllocs.unregisterMemory(HstPtr, LockMappedBuffers); + if (IgnoreLockMappedFailures) + return Plugin::success(); + return Err; } /// Check whether the host buffer with address \p HstPtr is pinned by the @@ -1208,6 +1177,12 @@ private: BoolEnvar OMPX_ReuseBlocksForHighTripCount = BoolEnvar("LIBOMPTARGET_REUSE_BLOCKS_FOR_HIGH_TRIP_COUNT", true); + /// Indicate whether mapped host buffers should be locked automatically. + bool LockMappedBuffers; + + /// Indicate whether failures when locking mapped buffers should be ignored. + bool IgnoreLockMappedFailures; + protected: /// Environment variables defined by the LLVM OpenMP implementation /// regarding the initial number of streams and events. diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp index 807df0ffd787..99af126b6829 100644 --- a/offload/plugins-nextgen/common/src/PluginInterface.cpp +++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp @@ -733,6 +733,32 @@ GenericDeviceTy::GenericDeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, #undef bindOmptCallback #endif + + // Envar that indicates whether mapped host buffers should be locked + // automatically. The possible values are boolean (on/off) and a special: + // off: Mapped host buffers are not locked. + // on: Mapped host buffers are locked in a best-effort approach. + // Failure to lock the buffers are silent. + // mandatory: Mapped host buffers are always locked and failures to lock + // a buffer results in a fatal error. + StringEnvar OMPX_LockMappedBuffers("LIBOMPTARGET_LOCK_MAPPED_HOST_BUFFERS", + "off"); + + bool Enabled; + if (StringParser::parse(OMPX_LockMappedBuffers.get().data(), Enabled)) { + // Parsed as a boolean value. Enable the feature if necessary. + LockMappedBuffers = Enabled; + IgnoreLockMappedFailures = true; + } else if (OMPX_LockMappedBuffers.get() == "mandatory") { + // Enable the feature and failures are fatal. + LockMappedBuffers = true; + IgnoreLockMappedFailures = false; + } else { + // Disable by default. + ODBG(OLDT_Alloc) << "Invalid value LIBOMPTARGET_LOCK_MAPPED_HOST_BUFFERS=" + << OMPX_LockMappedBuffers.get(); + LockMappedBuffers = false; + } } Error GenericDeviceTy::init(GenericPluginTy &Plugin) { @@ -1024,8 +1050,9 @@ Error PinnedAllocationMapTy::unregisterHostBuffer(void *HstPtr) { return eraseEntry(*Entry); } -Expected PinnedAllocationMapTy::lockHostBuffer(void *HstPtr, - size_t Size) { +Expected PinnedAllocationMapTy::registerMemory(void *HstPtr, + size_t Size, + bool LockMemory) { assert(HstPtr && "Invalid pointer"); assert(Size && "Invalid size"); @@ -1043,11 +1070,32 @@ Expected PinnedAllocationMapTy::lockHostBuffer(void *HstPtr, utils::getPtrDiff(HstPtr, Entry->HstPtr)); } + size_t BaseSize; + void *BaseHstPtr, *BaseDevAccessiblePtr; + + // Check if it was externally pinned by a vendor-specific API. + auto IsPinnedOrErr = Device.isPinnedPtrImpl(HstPtr, BaseHstPtr, + BaseDevAccessiblePtr, BaseSize); + if (!IsPinnedOrErr) + return std::move(IsPinnedOrErr.takeError()); + + // If pinned, just insert the entry representing the whole pinned buffer. + if (*IsPinnedOrErr) { + if (auto Err = insertEntry(BaseHstPtr, BaseDevAccessiblePtr, BaseSize, + /*Externallylocked=*/true)) + return std::move(Err); + return BaseDevAccessiblePtr; + } + + // Not externally pinned. Do nothing if locking of mapped buffers is disabled. + if (!LockMemory) + return nullptr; + // No intersecting registered allocation found in the map. First, lock the // host buffer and retrieve the device accessible pointer. auto DevAccessiblePtrOrErr = Device.dataLockImpl(HstPtr, Size); if (!DevAccessiblePtrOrErr) - return DevAccessiblePtrOrErr.takeError(); + return std::move(DevAccessiblePtrOrErr.takeError()); // Now insert the new entry into the map. if (auto Err = insertEntry(HstPtr, *DevAccessiblePtrOrErr, Size)) @@ -1057,12 +1105,18 @@ Expected PinnedAllocationMapTy::lockHostBuffer(void *HstPtr, return *DevAccessiblePtrOrErr; } -Error PinnedAllocationMapTy::unlockHostBuffer(void *HstPtr) { +Error PinnedAllocationMapTy::unregisterMemory(void *HstPtr, bool UnlockMemory) { assert(HstPtr && "Invalid pointer"); std::lock_guard Lock(Mutex); const EntryTy *Entry = findIntersecting(HstPtr); + + // No entry but automatic locking of mapped buffers is disabled, so + // nothing to do. + if (!Entry && !UnlockMemory) + return Plugin::success(); + if (!Entry) return Plugin::error(ErrorCode::INVALID_ARGUMENT, "cannot find locked buffer"); @@ -1088,91 +1142,6 @@ Error PinnedAllocationMapTy::unlockHostBuffer(void *HstPtr) { return eraseEntry(*Entry); } -Error PinnedAllocationMapTy::lockMappedHostBuffer(void *HstPtr, size_t Size) { - assert(HstPtr && "Invalid pointer"); - assert(Size && "Invalid size"); - - std::lock_guard Lock(Mutex); - - // If previously registered, just register a new user on the entry. - const EntryTy *Entry = findIntersecting(HstPtr); - if (Entry) - return registerEntryUse(*Entry, HstPtr, Size); - - size_t BaseSize; - void *BaseHstPtr, *BaseDevAccessiblePtr; - - // Check if it was externally pinned by a vendor-specific API. - auto IsPinnedOrErr = Device.isPinnedPtrImpl(HstPtr, BaseHstPtr, - BaseDevAccessiblePtr, BaseSize); - if (!IsPinnedOrErr) - return IsPinnedOrErr.takeError(); - - // If pinned, just insert the entry representing the whole pinned buffer. - if (*IsPinnedOrErr) - return insertEntry(BaseHstPtr, BaseDevAccessiblePtr, BaseSize, - /*Externallylocked=*/true); - - // Not externally pinned. Do nothing if locking of mapped buffers is disabled. - if (!LockMappedBuffers) - return Plugin::success(); - - // Otherwise, lock the buffer and insert the new entry. - auto DevAccessiblePtrOrErr = Device.dataLockImpl(HstPtr, Size); - if (!DevAccessiblePtrOrErr) { - // Errors may be tolerated. - if (!IgnoreLockMappedFailures) - return DevAccessiblePtrOrErr.takeError(); - - consumeError(DevAccessiblePtrOrErr.takeError()); - return Plugin::success(); - } - - return insertEntry(HstPtr, *DevAccessiblePtrOrErr, Size); -} - -Error PinnedAllocationMapTy::unlockUnmappedHostBuffer(void *HstPtr) { - assert(HstPtr && "Invalid pointer"); - - std::lock_guard Lock(Mutex); - - // Check whether there is any intersecting entry. - const EntryTy *Entry = findIntersecting(HstPtr); - - // No entry but automatic locking of mapped buffers is disabled, so - // nothing to do. - if (!Entry && !LockMappedBuffers) - return Plugin::success(); - - // No entry, automatic locking is enabled, but the locking may have failed, so - // do nothing. - if (!Entry && IgnoreLockMappedFailures) - return Plugin::success(); - - // No entry, but the automatic locking is enabled, so this is an error. - if (!Entry) - return Plugin::error(ErrorCode::INVALID_ARGUMENT, - "locked buffer not found"); - - // There is entry, so unregister a user and check whether it was the last one. - auto LastUseOrErr = unregisterEntryUse(*Entry); - if (!LastUseOrErr) - return LastUseOrErr.takeError(); - - // If it is not the last one, there is nothing to do. - if (!(*LastUseOrErr)) - return Plugin::success(); - - // Otherwise, if it was the last and the buffer was locked by the plugin, - // unlock it. - if (!Entry->ExternallyLocked) - if (auto Err = Device.dataUnlockImpl(Entry->HstPtr)) - return Err; - - // Finally erase the entry from the map. - return eraseEntry(*Entry); -} - Error GenericDeviceTy::synchronize(__tgt_async_info *AsyncInfo, bool ReleaseQueue) { if (!AsyncInfo) @@ -1822,7 +1791,7 @@ int32_t GenericPluginTy::data_delete(int32_t DeviceId, void *TgtPtr, int32_t GenericPluginTy::data_lock(int32_t DeviceId, void *Ptr, int64_t Size, void **LockedPtr) { - auto LockedPtrOrErr = getDevice(DeviceId).dataLock(Ptr, Size); + auto LockedPtrOrErr = getDevice(DeviceId).registerMemory(Ptr, Size); if (!LockedPtrOrErr) { auto Err = LockedPtrOrErr.takeError(); REPORT() << "Failure to lock memory " << Ptr << ": " @@ -1841,7 +1810,7 @@ int32_t GenericPluginTy::data_lock(int32_t DeviceId, void *Ptr, int64_t Size, } int32_t GenericPluginTy::data_unlock(int32_t DeviceId, void *Ptr) { - auto Err = getDevice(DeviceId).dataUnlock(Ptr); + auto Err = getDevice(DeviceId).unregisterMemory(Ptr); if (Err) { REPORT() << "Failure to unlock memory " << Ptr << ": " << toString(std::move(Err)); diff --git a/offload/unittests/OffloadAPI/memory/olMemRegister.cpp b/offload/unittests/OffloadAPI/memory/olMemRegister.cpp index e98dafc54598..60f49c641798 100644 --- a/offload/unittests/OffloadAPI/memory/olMemRegister.cpp +++ b/offload/unittests/OffloadAPI/memory/olMemRegister.cpp @@ -15,29 +15,32 @@ OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olMemRegisterTest); TEST_P(olMemRegisterTest, SuccessRegister) { int Arr[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t FlagsReg = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; + ol_memory_register_flags_t FlagsUnreg = OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY; void *PinnedPtr = nullptr; - ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), FlagsReg, &PinnedPtr)); ASSERT_NE(PinnedPtr, nullptr); - ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr)); + ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr, FlagsUnreg)); } TEST_P(olMemRegisterTest, SuccessMultipleRegister) { int Arr[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t FlagsReg = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; + ol_memory_register_flags_t FlagsUnreg = OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY; void *PinnedPtr = nullptr; void *PinnedPtr1 = nullptr; - ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), FlagsReg, &PinnedPtr)); ASSERT_NE(PinnedPtr, nullptr); - ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr1)); + ASSERT_SUCCESS( + olMemRegister(Device, Arr, sizeof(Arr), FlagsReg, &PinnedPtr1)); ASSERT_NE(PinnedPtr1, nullptr); - ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr)); - ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr1)); + ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr, FlagsUnreg)); + ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr1, FlagsUnreg)); } TEST_P(olMemRegisterTest, InvalidSizeRegister) { int Arr[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t Flags = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; void *PinnedPtr = nullptr; ASSERT_ERROR(OL_ERRC_INVALID_SIZE, olMemRegister(Device, Arr, 0, Flags, &PinnedPtr)); @@ -45,7 +48,7 @@ TEST_P(olMemRegisterTest, InvalidSizeRegister) { TEST_P(olMemRegisterTest, InvalidPtrRegister) { int Arr[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t Flags = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; void *PinnedPtr = nullptr; ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, olMemRegister(Device, nullptr, sizeof(Arr), Flags, &PinnedPtr)); @@ -53,32 +56,82 @@ TEST_P(olMemRegisterTest, InvalidPtrRegister) { TEST_P(olMemRegisterTest, InvalidPtrUnRegister) { int Arr[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t FlagsReg = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; + ol_memory_register_flags_t FlagsUnreg = OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY; void *PinnedPtr = nullptr; - ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), FlagsReg, &PinnedPtr)); ASSERT_NE(PinnedPtr, nullptr); - ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, olMemUnregister(Device, nullptr)); - ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr)); + ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, + olMemUnregister(Device, nullptr, FlagsUnreg)); + ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr, FlagsUnreg)); } TEST_P(olMemRegisterTest, UnregisteredPtrUnRegister) { int Arr[50]; int Arr1[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t FlagsReg = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; + ol_memory_register_flags_t FlagsUnreg = OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY; void *PinnedPtr = nullptr; - ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), FlagsReg, &PinnedPtr)); ASSERT_NE(PinnedPtr, nullptr); - ASSERT_ERROR(OL_ERRC_INVALID_ARGUMENT, olMemUnregister(Device, Arr1)); - ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr)); + ASSERT_ERROR(OL_ERRC_INVALID_ARGUMENT, + olMemUnregister(Device, Arr1, FlagsUnreg)); + ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr, FlagsUnreg)); } TEST_P(olMemRegisterTest, PartialOverlapPtrRegister) { int Arr[50]; - ol_memory_register_flags_t Flags = {}; + ol_memory_register_flags_t FlagsReg = OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY; + ol_memory_register_flags_t FlagsUnreg = OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY; + void *PinnedPtr = nullptr; + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), FlagsReg, &PinnedPtr)); + ASSERT_NE(PinnedPtr, nullptr); + ASSERT_ERROR( + OL_ERRC_INVALID_ARGUMENT, + olMemRegister(Device, Arr + 2, sizeof(Arr), FlagsReg, &PinnedPtr)); + ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr, FlagsUnreg)); +} + +TEST_P(olMemRegisterTest, SuccessRegisterNoLock) { + int Arr[50]; + ol_memory_register_flags_t Flags = {0}; void *PinnedPtr = nullptr; ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); - ASSERT_NE(PinnedPtr, nullptr); - ASSERT_ERROR(OL_ERRC_INVALID_ARGUMENT, - olMemRegister(Device, Arr + 2, sizeof(Arr), Flags, &PinnedPtr)); - ASSERT_SUCCESS(olMemUnregister(Device, PinnedPtr)); + ASSERT_SUCCESS(olMemUnregister(Device, Arr, Flags)); +} + +TEST_P(olMemRegisterTest, SuccessMultipleRegisterNoLock) { + int Arr[50]; + void *PinnedPtr = nullptr; + ol_memory_register_flags_t Flags = {0}; + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_SUCCESS(olMemUnregister(Device, Arr, Flags)); + ASSERT_SUCCESS(olMemUnregister(Device, Arr, Flags)); +} + +TEST_P(olMemRegisterTest, InvalidSizeRegisterNoLock) { + int Arr[50]; + void *PinnedPtr = nullptr; + ol_memory_register_flags_t Flags = {0}; + ASSERT_ERROR(OL_ERRC_INVALID_SIZE, + olMemRegister(Device, Arr, 0, Flags, &PinnedPtr)); +} + +TEST_P(olMemRegisterTest, InvalidPtrRegisterNoLock) { + int Arr[50]; + void *PinnedPtr = nullptr; + ol_memory_register_flags_t Flags = {0}; + ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, + olMemRegister(Device, nullptr, sizeof(Arr), Flags, &PinnedPtr)); +} + +TEST_P(olMemRegisterTest, InvalidPtrUnRegisterNoLock) { + int Arr[50]; + void *PinnedPtr = nullptr; + ol_memory_register_flags_t Flags = {0}; + ASSERT_SUCCESS(olMemRegister(Device, Arr, sizeof(Arr), Flags, &PinnedPtr)); + ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, + olMemUnregister(Device, nullptr, Flags)); + ASSERT_SUCCESS(olMemUnregister(Device, Arr, Flags)); }