2023-05-13 00:51:52 +08:00
|
|
|
/*
|
2023-12-21 23:44:11 +08:00
|
|
|
* Copyright (C) 2023-2024 Intel Corporation
|
2023-05-13 00:51:52 +08:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "shared/source/helpers/constants.h"
|
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
|
|
|
#include "shared/source/helpers/non_copyable_or_moveable.h"
|
2023-05-13 00:51:52 +08:00
|
|
|
#include "shared/source/utilities/stackvec.h"
|
|
|
|
|
|
|
|
#include <functional>
|
|
|
|
#include <iterator>
|
|
|
|
#include <memory>
|
|
|
|
#include <mutex>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace NEO {
|
|
|
|
|
|
|
|
class GraphicsAllocation;
|
|
|
|
class HeapAllocator;
|
|
|
|
class MemoryManager;
|
|
|
|
|
|
|
|
template <typename PoolT>
|
|
|
|
struct SmallBuffersParams {
|
|
|
|
protected:
|
2023-12-21 23:44:11 +08:00
|
|
|
static constexpr auto aggregatedSmallBuffersPoolSize = 2 * MemoryConstants::megaByte;
|
|
|
|
static constexpr auto smallBufferThreshold = 1 * MemoryConstants::megaByte;
|
|
|
|
static constexpr auto chunkAlignment = MemoryConstants::pageSize64k;
|
2023-05-13 00:51:52 +08:00
|
|
|
static constexpr auto startingOffset = chunkAlignment;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType = BufferType>
|
2023-10-11 21:57:07 +08:00
|
|
|
struct AbstractBuffersPool : public SmallBuffersParams<PoolT>, public NonCopyableClass {
|
2023-05-13 00:51:52 +08:00
|
|
|
// The prototype of a function allocating the `mainStorage` is not specified.
|
|
|
|
// That would be an unnecessary limitation here - it is completely up to derived class implementation.
|
|
|
|
// Perhaps the allocating function needs to leverage `HeapAllocator::allocate()` and also
|
|
|
|
// a BufferType-dependent function reserving chunks within `mainStorage`.
|
|
|
|
// Example: see `NEO::Context::BufferPool::allocate()`
|
|
|
|
using Params = SmallBuffersParams<PoolT>;
|
|
|
|
using Params::aggregatedSmallBuffersPoolSize;
|
|
|
|
using Params::chunkAlignment;
|
|
|
|
using Params::smallBufferThreshold;
|
|
|
|
using Params::startingOffset;
|
|
|
|
using AllocsVecCRef = const StackVec<NEO::GraphicsAllocation *, 1> &;
|
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
|
|
|
using OnChunkFreeCallback = void (PoolT::*)(uint64_t offset, size_t size);
|
2023-05-13 00:51:52 +08:00
|
|
|
|
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(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCallback);
|
2023-05-13 00:51:52 +08:00
|
|
|
AbstractBuffersPool(AbstractBuffersPool<PoolT, BufferType, BufferParentType> &&bufferPool);
|
2023-10-11 21:57:07 +08:00
|
|
|
AbstractBuffersPool &operator=(AbstractBuffersPool &&) = delete;
|
2023-05-13 00:51:52 +08:00
|
|
|
void tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size);
|
|
|
|
bool isPoolBuffer(const BufferParentType *buffer) const;
|
|
|
|
void drain();
|
|
|
|
|
|
|
|
// Derived class needs to provide its own implementation of getAllocationsVector().
|
|
|
|
// This is a CRTP-replacement for virtual functions.
|
|
|
|
AllocsVecCRef getAllocationsVector() {
|
|
|
|
return static_cast<PoolT *>(this)->getAllocationsVector();
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryManager *memoryManager{nullptr};
|
|
|
|
std::unique_ptr<BufferType> mainStorage;
|
|
|
|
std::unique_ptr<HeapAllocator> chunkAllocator;
|
|
|
|
std::vector<std::pair<uint64_t, size_t>> chunksToFree;
|
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
|
|
|
OnChunkFreeCallback onChunkFreeCallback = nullptr;
|
2023-05-13 00:51:52 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType = BufferType>
|
|
|
|
class AbstractBuffersAllocator : public SmallBuffersParams<BuffersPoolType> {
|
|
|
|
// The prototype of a function allocating buffers from the pool is not specified (see similar comment in `AbstractBufersPool`).
|
|
|
|
// By common sense, in order to allocate buffers from the pool the function should leverage a call provided by `BuffersPoolType`.
|
|
|
|
// Example: see `NEO::Context::BufferPoolAllocator::allocateBufferFromPool()`.
|
|
|
|
public:
|
|
|
|
using Params = SmallBuffersParams<BuffersPoolType>;
|
|
|
|
using Params::aggregatedSmallBuffersPoolSize;
|
|
|
|
using Params::chunkAlignment;
|
|
|
|
using Params::smallBufferThreshold;
|
|
|
|
using Params::startingOffset;
|
|
|
|
static_assert(aggregatedSmallBuffersPoolSize > smallBufferThreshold, "Largest allowed buffer needs to fit in pool");
|
|
|
|
|
|
|
|
void releaseSmallBufferPool() { this->bufferPools.clear(); }
|
|
|
|
bool isPoolBuffer(const BufferParentType *buffer) const;
|
|
|
|
void tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
inline bool isSizeWithinThreshold(size_t size) const { return smallBufferThreshold >= 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
|
|
|
void tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size, std::vector<BuffersPoolType> &bufferPoolsVec);
|
2023-05-13 00:51:52 +08:00
|
|
|
void 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
|
|
|
void drain(std::vector<BuffersPoolType> &bufferPoolsVec);
|
2023-05-13 00:51:52 +08:00
|
|
|
void 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
|
|
|
void addNewBufferPool(BuffersPoolType &&bufferPool, std::vector<BuffersPoolType> &bufferPoolsVec);
|
2023-05-13 00:51:52 +08:00
|
|
|
|
|
|
|
std::mutex mutex;
|
|
|
|
std::vector<BuffersPoolType> bufferPools;
|
|
|
|
};
|
|
|
|
} // namespace NEO
|