diff --git a/rocclr/platform/object.hpp b/rocclr/platform/object.hpp index 3d9348570e..dece674ea5 100644 --- a/rocclr/platform/object.hpp +++ b/rocclr/platform/object.hpp @@ -197,15 +197,23 @@ class SysmemPool { public: SysmemPool(): chunk_access_(true) /* Sysmem Pool Lock */ {} ~SysmemPool() { - // Release current chunk - if (chunks_.size() == 1) { - auto it = chunks_.begin(); - auto idx = kAllocChunkSize - (current_alloc_.load() % kAllocChunkSize); - // Make sure all allocations were released - if (idx == (*it)->free_) { - delete [] (*it)->allocs_; - delete (*it); - chunks_.erase(it); + if (free_chunk_num_ != max_chunk_idx_) { + for (int i = 0; i < kActiveAllocSize; ++i) { + // Free any active chunks + if (active_allocs_[i] != nullptr) { + auto chunk = active_allocs_[i]->base_; + // Check if this chunk contains unreleased memory objects + if ((chunk->busy_ + chunk->free_) != kAllocChunkSize) { + LogPrintfError("Unreleased slots in sysmem pool %ld", + kAllocChunkSize - (chunk->busy_ + chunk->free_)); + } + delete chunk; + free_chunk_num_++; + } + } + // Validate if sysmempool released all memory + if (free_chunk_num_ != max_chunk_idx_) { + LogPrintfError("Unreleased chunk in sysmem pool %ld", max_chunk_idx_ - free_chunk_num_); } } } @@ -217,53 +225,87 @@ public: ScopedLock lock(chunk_access_); // Second check in a case of multiple waiters if (idx == max_chunk_idx_) { - auto allocs = new T[kAllocChunkSize]; - chunks_.emplace(new AllocChunk(allocs)); + auto allocs = new MemoryObject[kAllocChunkSize]; + // Save the base in the first slot of all allocations + allocs[0].base_ = new AllocChunk(allocs); + // Check if the overwritten chunk has still empty slots + if (active_allocs_[idx % kActiveAllocSize] != nullptr) { + auto stale = active_allocs_[idx % kActiveAllocSize]->base_; + if (stale->busy_ != kAllocChunkSize) { + // The pool contains the stale slots, hence make sure it's marked as free + auto freed = stale->free_ - stale->busy_; + if (freed == 0) { + delete stale; + free_chunk_num_++; + } + } + } + // Keep the chunk in the list of active chunks active_allocs_[idx % kActiveAllocSize] = allocs; max_chunk_idx_++; + } else if ((idx < max_chunk_idx_) && ((max_chunk_idx_ - idx) >= kActiveAllocSize)) { + // If a wait was very long, then drop the old slot and find a more recent one + current = current_alloc_++; + idx = current / kAllocChunkSize; } } - return &active_allocs_[idx % kActiveAllocSize][current % kAllocChunkSize]; + + // Find a slot in the active pool of allocations + auto chunk_idx = idx % kActiveAllocSize; + MemoryObject* obj = &active_allocs_[chunk_idx][current % kAllocChunkSize]; + // Save the chunk allocation + obj->base_ = active_allocs_[chunk_idx]->base_; + obj->base_->busy_++; + assert((reinterpret_cast
(&obj->object_) - + reinterpret_cast(obj)) == sizeof(AllocChunk*) && "Incorrect mem obj offset!"); + return &obj->object_; } void Free(void* ptr) { - ScopedLock lock(chunk_access_); - bool found = false; - // Search for the pointer in all valid chunks - for (auto it : chunks_) { - if (reinterpret_cast