2023-05-13 00:51:52 +08:00
|
|
|
/*
|
2025-02-07 07:56:09 +08:00
|
|
|
* Copyright (C) 2023-2025 Intel Corporation
|
2023-05-13 00:51:52 +08:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "shared/source/memory_manager/memory_manager.h"
|
2025-02-07 07:56:09 +08:00
|
|
|
#include "shared/source/os_interface/product_helper.h"
|
2023-05-13 00:51:52 +08:00
|
|
|
#include "shared/source/utilities/buffer_pool_allocator.h"
|
|
|
|
#include "shared/source/utilities/heap_allocator.h"
|
|
|
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
namespace NEO {
|
|
|
|
|
2025-02-07 07:56:09 +08:00
|
|
|
inline SmallBuffersParams SmallBuffersParams::getPreferredBufferPoolParams(const ProductHelper &productHelper) {
|
|
|
|
return productHelper.is2MBLocalMemAlignmentEnabled() ? SmallBuffersParams::getLargePagesParams() : SmallBuffersParams::getDefaultParams();
|
|
|
|
}
|
|
|
|
|
2023-05-13 00:51:52 +08:00
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCb)
|
2025-02-07 07:56:09 +08:00
|
|
|
: AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(memoryManager, onChunkFreeCb, SmallBuffersParams::getDefaultParams()) {}
|
|
|
|
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
|
|
AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCb, const SmallBuffersParams ¶ms)
|
|
|
|
: memoryManager{memoryManager}, onChunkFreeCallback{onChunkFreeCb}, params{params} {
|
2023-05-13 00:51:52 +08:00
|
|
|
static_assert(std::is_base_of_v<BufferParentType, BufferType>);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
|
|
AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(AbstractBuffersPool<PoolT, BufferType, BufferParentType> &&bufferPool)
|
|
|
|
: memoryManager{bufferPool.memoryManager},
|
|
|
|
mainStorage{std::move(bufferPool.mainStorage)},
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
chunkAllocator{std::move(bufferPool.chunkAllocator)},
|
2025-02-07 07:56:09 +08:00
|
|
|
onChunkFreeCallback{bufferPool.onChunkFreeCallback},
|
|
|
|
params{bufferPool.params} {}
|
2023-05-13 00:51:52 +08:00
|
|
|
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersPool<PoolT, BufferType, BufferParentType>::tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size) {
|
|
|
|
if (this->isPoolBuffer(possiblePoolBuffer)) {
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
this->chunksToFree.push_back({offset, size});
|
2023-05-13 00:51:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
|
|
bool AbstractBuffersPool<PoolT, BufferType, BufferParentType>::isPoolBuffer(const BufferParentType *buffer) const {
|
|
|
|
static_assert(std::is_base_of_v<BufferParentType, BufferType>);
|
|
|
|
|
|
|
|
return (buffer && this->mainStorage.get() == buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersPool<PoolT, BufferType, BufferParentType>::drain() {
|
|
|
|
const auto &allocationsVec = this->getAllocationsVector();
|
|
|
|
for (auto allocation : allocationsVec) {
|
|
|
|
if (allocation && this->memoryManager->allocInUse(*allocation)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto &chunk : this->chunksToFree) {
|
2025-02-07 07:56:09 +08:00
|
|
|
this->chunkAllocator->free(chunk.first + params.startingOffset, chunk.second);
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
if (static_cast<PoolT *>(this)->onChunkFreeCallback) {
|
|
|
|
(static_cast<PoolT *>(this)->*onChunkFreeCallback)(chunk.first, chunk.second);
|
|
|
|
}
|
2023-05-13 00:51:52 +08:00
|
|
|
}
|
|
|
|
this->chunksToFree.clear();
|
|
|
|
}
|
|
|
|
|
2025-02-07 07:56:09 +08:00
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::AbstractBuffersAllocator(const SmallBuffersParams ¶ms)
|
|
|
|
: params{params} {
|
|
|
|
DEBUG_BREAK_IF(params.aggregatedSmallBuffersPoolSize < params.smallBufferThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::AbstractBuffersAllocator()
|
|
|
|
: AbstractBuffersAllocator(SmallBuffersParams::getDefaultParams()) {}
|
|
|
|
|
2023-05-13 00:51:52 +08:00
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
bool AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::isPoolBuffer(const BufferParentType *buffer) const {
|
|
|
|
static_assert(std::is_base_of_v<BufferParentType, BufferType>);
|
|
|
|
|
|
|
|
for (auto &bufferPool : this->bufferPools) {
|
|
|
|
if (bufferPool.isPoolBuffer(buffer)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size) {
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
this->tryFreeFromPoolBuffer(possiblePoolBuffer, offset, size, this->bufferPools);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size, std::vector<BuffersPoolType> &bufferPoolsVec) {
|
2023-05-13 00:51:52 +08:00
|
|
|
auto lock = std::unique_lock<std::mutex>(this->mutex);
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
for (auto &bufferPool : bufferPoolsVec) {
|
2023-05-13 00:51:52 +08:00
|
|
|
bufferPool.tryFreeFromPoolBuffer(possiblePoolBuffer, offset, size); // NOLINT(clang-analyzer-cplusplus.NewDelete)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::drain() {
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
this->drain(this->bufferPools);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::drain(std::vector<BuffersPoolType> &bufferPoolsVec) {
|
|
|
|
for (auto &bufferPool : bufferPoolsVec) {
|
2023-05-13 00:51:52 +08:00
|
|
|
bufferPool.drain();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::addNewBufferPool(BuffersPoolType &&bufferPool) {
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
this->addNewBufferPool(std::move(bufferPool), this->bufferPools);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::addNewBufferPool(BuffersPoolType &&bufferPool, std::vector<BuffersPoolType> &bufferPoolsVec) {
|
2023-05-13 00:51:52 +08:00
|
|
|
if (bufferPool.mainStorage) {
|
feature: add optional onChunkFree callback to AbstractBuffersPool
Instances returned by `getAllocationsVector()` in some cases cannot be
freed (in the `malloc/new` sense) until the `drain()` function invokes
`allocInUse()` on them. Plus, the `chunksToFree` container operates on
pairs `{offset, size}`, not pointers, so such pair cannot be used to
release allocations either.
Provide an optional callback, which can be implemented by the custom
pool derived from `AbstractBuffersPool`. This callback can be used, for
example, to perform actual release of an allocation related to the
currently processed chunk.
Additionally, provide the `drain()` and `tryFreeFromPoolBuffer()`
functions with pool-independent versions and keep the previous versions
as defaults (for allocators with a single pool). The new versions allow
reusing the code for cases when allocator has multiple pools.
In both cases, there was no such needs so far but it arose when working
on `IsaBuffersAllocator`. The latter is coming with future commits, but
the shared code modifications are extracted as an independent step.
Related-To: NEO-7788
Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
2023-06-29 23:15:50 +08:00
|
|
|
bufferPoolsVec.push_back(std::move(bufferPool));
|
2023-05-13 00:51:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace NEO
|