mirror of https://github.com/pvnis/srsRAN_4G.git
implementation of memory pool with individual memory blocks per UE that get accessed via their rnti
parent
db496df1e6
commit
60d5c6df7b
@ -0,0 +1,105 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_CIRCULAR_MAP_STACK_POOL_H
|
||||
#define SRSRAN_CIRCULAR_MAP_STACK_POOL_H
|
||||
|
||||
#include "batch_mem_pool.h"
|
||||
#include "linear_allocator.h"
|
||||
#include "srsran/adt/circular_array.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
template <size_t NofStacks>
|
||||
class circular_stack_pool
|
||||
{
|
||||
struct mem_block_elem_t {
|
||||
std::mutex mutex;
|
||||
size_t key = std::numeric_limits<size_t>::max();
|
||||
size_t count = 0;
|
||||
linear_allocator alloc;
|
||||
|
||||
void clear()
|
||||
{
|
||||
key = std::numeric_limits<size_t>::max();
|
||||
count = 0;
|
||||
alloc.clear();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
circular_stack_pool(size_t nof_objs_per_batch, size_t stack_size, size_t batch_thres, int initial_size = -1) :
|
||||
central_cache(std::min(NofStacks, nof_objs_per_batch), stack_size, batch_thres, initial_size)
|
||||
{}
|
||||
circular_stack_pool(circular_stack_pool&&) = delete;
|
||||
circular_stack_pool(const circular_stack_pool&) = delete;
|
||||
circular_stack_pool& operator=(circular_stack_pool&&) = delete;
|
||||
circular_stack_pool& operator=(const circular_stack_pool&) = delete;
|
||||
~circular_stack_pool()
|
||||
{
|
||||
for (mem_block_elem_t& elem : pools) {
|
||||
std::unique_lock<std::mutex> lock(elem.mutex);
|
||||
srsran_assert(elem.count == 0, "There are missing deallocations for stack id=%zd", elem.key);
|
||||
if (elem.alloc.is_init()) {
|
||||
void* ptr = elem.alloc.memblock_ptr();
|
||||
elem.alloc.clear();
|
||||
central_cache.deallocate_node(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* allocate(size_t key, size_t size, size_t alignment) noexcept
|
||||
{
|
||||
size_t idx = key % NofStacks;
|
||||
mem_block_elem_t& elem = pools[idx];
|
||||
std::unique_lock<std::mutex> lock(elem.mutex);
|
||||
if (not elem.alloc.is_init()) {
|
||||
void* block = central_cache.allocate_node(central_cache.get_node_max_size());
|
||||
if (block == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
elem.key = key;
|
||||
elem.alloc = linear_allocator(block, central_cache.get_node_max_size());
|
||||
}
|
||||
void* ptr = elem.alloc.allocate(size, alignment);
|
||||
elem.count++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void deallocate(size_t key, void* p)
|
||||
{
|
||||
size_t idx = key % NofStacks;
|
||||
mem_block_elem_t& elem = pools[idx];
|
||||
std::lock_guard<std::mutex> lock(elem.mutex);
|
||||
elem.alloc.deallocate(p);
|
||||
elem.count--;
|
||||
if (elem.count == 0) {
|
||||
// return back to central cache
|
||||
void* ptr = elem.alloc.memblock_ptr();
|
||||
elem.clear();
|
||||
central_cache.deallocate_node(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void allocate_batch() { central_cache.allocate_batch(); }
|
||||
|
||||
size_t cache_size() const { return central_cache.cache_size(); }
|
||||
|
||||
private:
|
||||
srsran::circular_array<mem_block_elem_t, NofStacks> pools;
|
||||
srsran::background_mem_pool central_cache;
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_CIRCULAR_MAP_STACK_POOL_H
|
@ -0,0 +1,78 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_LINEAR_ALLOCATOR_H
|
||||
#define SRSRAN_LINEAR_ALLOCATOR_H
|
||||
|
||||
#include "pool_utils.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
class linear_allocator
|
||||
{
|
||||
public:
|
||||
linear_allocator() = default;
|
||||
linear_allocator(void* start_, void* end_) :
|
||||
start(static_cast<uint8_t*>(start_)), end(static_cast<uint8_t*>(end_)), cur(start)
|
||||
{}
|
||||
linear_allocator(void* start_, size_t sz) : start(static_cast<uint8_t*>(start_)), end(start + sz), cur(start) {}
|
||||
linear_allocator(const linear_allocator& other) = delete;
|
||||
linear_allocator(linear_allocator&& other) noexcept : start(other.start), end(other.end), cur(other.cur)
|
||||
{
|
||||
other.clear();
|
||||
}
|
||||
linear_allocator& operator=(const linear_allocator& other) = delete;
|
||||
linear_allocator& operator =(linear_allocator&& other) noexcept
|
||||
{
|
||||
start = other.start;
|
||||
end = other.end;
|
||||
cur = other.cur;
|
||||
other.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void* allocate(size_t sz, size_t alignment)
|
||||
{
|
||||
void* alloc_start = align_to(cur, alignment);
|
||||
cur = static_cast<uint8_t*>(alloc_start) + sz;
|
||||
srsran_assert(cur <= end,
|
||||
"Linear Allocator buffer of size=%zd was exceeded (current size=%zd)",
|
||||
size(),
|
||||
nof_bytes_allocated());
|
||||
return alloc_start;
|
||||
}
|
||||
|
||||
void deallocate(void* p) { srsran_assert(p >= start and p < end, "pointer does not belong to pool"); }
|
||||
|
||||
size_t nof_bytes_allocated() const { return cur - start; }
|
||||
size_t nof_bytes_left() const { return end - cur; }
|
||||
size_t size() const { return end - start; }
|
||||
bool is_init() const { return start != end; }
|
||||
void* memblock_ptr() { return static_cast<void*>(start); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
start = nullptr;
|
||||
cur = nullptr;
|
||||
end = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t* start = nullptr;
|
||||
uint8_t* end = nullptr;
|
||||
uint8_t* cur = nullptr;
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_LINEAR_ALLOCATOR_H
|
@ -0,0 +1,48 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_RNTI_POOL_H
|
||||
#define SRSRAN_RNTI_POOL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
// Allocation of Objects in UE dedicated memory pool
|
||||
void reserve_rnti_memblocks(size_t nof_blocks);
|
||||
void* allocate_rnti_dedicated_mem(uint16_t rnti, std::size_t size, std::size_t align);
|
||||
void deallocate_rnti_dedicated_mem(uint16_t rnti, void* p);
|
||||
|
||||
template <typename T>
|
||||
struct rnti_obj_deleter {
|
||||
uint16_t rnti;
|
||||
explicit rnti_obj_deleter(uint16_t rnti_ = 0) : rnti(rnti_) {}
|
||||
void operator()(void* p)
|
||||
{
|
||||
static_cast<T*>(p)->~T();
|
||||
deallocate_rnti_dedicated_mem(rnti, p);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
using unique_rnti_ptr = std::unique_ptr<T, rnti_obj_deleter<T> >;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
unique_rnti_ptr<T> make_rnti_obj(uint16_t rnti, Args&&... args)
|
||||
{
|
||||
void* block = allocate_rnti_dedicated_mem(rnti, sizeof(T), alignof(T));
|
||||
new (block) T(std::forward<Args>(args)...);
|
||||
return unique_rnti_ptr<T>(static_cast<T*>(block), rnti_obj_deleter<T>(rnti));
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_RNTI_POOL_H
|
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright 2013-2021 Software Radio Systems Limited
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set
|
||||
# forth in the LICENSE file which can be found at the top level of
|
||||
# the distribution.
|
||||
#
|
||||
|
||||
set(SOURCES rnti_pool.cc)
|
||||
add_library(srsenb_common STATIC ${SOURCES})
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/common/rnti_pool.h"
|
||||
#include "srsenb/hdr/common/common_enb.h"
|
||||
#include "srsran/adt/pool/circular_stack_pool.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
srsran::circular_stack_pool<SRSENB_MAX_UES>* get_rnti_pool()
|
||||
{
|
||||
static std::unique_ptr<srsran::circular_stack_pool<SRSENB_MAX_UES> > pool(
|
||||
new srsran::circular_stack_pool<SRSENB_MAX_UES>(8, 32768, 4));
|
||||
return pool.get();
|
||||
}
|
||||
|
||||
void reserve_rnti_memblocks(size_t nof_blocks)
|
||||
{
|
||||
while (get_rnti_pool()->cache_size() < nof_blocks) {
|
||||
get_rnti_pool()->allocate_batch();
|
||||
}
|
||||
}
|
||||
|
||||
void* allocate_rnti_dedicated_mem(uint16_t rnti, size_t size, size_t align)
|
||||
{
|
||||
return get_rnti_pool()->allocate(rnti, size, align);
|
||||
}
|
||||
void deallocate_rnti_dedicated_mem(uint16_t rnti, void* ptr)
|
||||
{
|
||||
get_rnti_pool()->deallocate(rnti, ptr);
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
Loading…
Reference in New Issue