================================================================================================
| 245 | |
| 246 | // ================================================================================================ |
| 247 | bool MemoryPool::FreeMemory(amd::Memory* memory, Stream* stream, Event* event) { |
| 248 | { |
| 249 | amd::ScopedLock lock(lock_pool_ops_); |
| 250 | |
| 251 | if (!state_.use_vm_heap_ && memory->getUserData().phys_mem_obj != nullptr) { |
| 252 | memory = memory->getUserData().phys_mem_obj; |
| 253 | } |
| 254 | |
| 255 | // If the free heap grows over the busy heap, then force release |
| 256 | if (AMD_DIRECT_DISPATCH && (free_heap_.GetTotalSize() > busy_heap_.GetTotalSize())) { |
| 257 | // Use event base release to reduce memory pressure |
| 258 | constexpr size_t kBytesToHold = 0; |
| 259 | free_heap_.ReleaseAllMemory(kBytesToHold); |
| 260 | |
| 261 | // If free mmeory is less than 12.5% of total, then force wait release |
| 262 | size_t free = 0; |
| 263 | size_t total = 0; |
| 264 | hipError_t err = hipMemGetInfo(&free, &total); |
| 265 | if ((err == hipSuccess) && (free < (total >> 3))) { |
| 266 | constexpr bool kSafeRelease = true; |
| 267 | free_heap_.ReleaseAllMemory(free_heap_.GetTotalSize() >> 1, kSafeRelease); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | MemoryTimestamp ts; |
| 272 | // Remove memory object from the busy pool |
| 273 | if (!busy_heap_.RemoveMemory(memory, &ts)) { |
| 274 | // This pool doesn't contain memory |
| 275 | return false; |
| 276 | } |
| 277 | ClPrint(amd::LOG_INFO, amd::LOG_MEM_POOL, "Pool FreeMem: %p, %p", memory->getSvmPtr(), memory); |
| 278 | |
| 279 | if (memory->getUserData().vaddr_mem_obj != nullptr) { |
| 280 | auto va_mem = memory->getUserData().vaddr_mem_obj; |
| 281 | if (stream == nullptr) { |
| 282 | stream = g_devices[memory->getUserData().deviceId]->NullStream(); |
| 283 | } |
| 284 | // Unmap virtual address from memory |
| 285 | auto cmd = new amd::VirtualMapCommand(*stream, amd::Command::EventWaitList{}, |
| 286 | va_mem->getSvmPtr(), va_mem->getSize(), nullptr); |
| 287 | cmd->enqueue(); |
| 288 | cmd->release(); |
| 289 | } |
| 290 | |
| 291 | if (stream != nullptr) { |
| 292 | // The stream of destruction is a safe stream, because the app must handle sync |
| 293 | ts.AddSafeStream(stream); |
| 294 | |
| 295 | if (event == nullptr) { |
| 296 | // Add a marker to the stream to trace availability of this memory |
| 297 | Event* e = new hip::Event(0); |
| 298 | if (e != nullptr) { |
| 299 | if (hipSuccess == e->addMarker(stream, nullptr)) { |
| 300 | ts.SetEvent(e); |
| 301 | // Make sure runtime sends a notification |
| 302 | auto result = e->ready(); |
| 303 | } |
| 304 | } |
nothing calls this directly
no test coverage detected