implementation of memory pool with individual memory blocks per UE that get accessed via their rnti

master
Francisco 4 years ago committed by Francisco Paisana
parent db496df1e6
commit 60d5c6df7b

@ -47,7 +47,7 @@ public:
srsran_assert(cache_size() == size(), "Not all nodes have been deallocated yet (%zd < %zd)", cache_size(), size());
}
size_t get_node_max_size() const { return allocated.get_node_max_size(); }
size_t get_node_max_size() const { return memblock_size; }
void clear()
{
@ -132,7 +132,14 @@ public:
grow_pool.deallocate_node(p);
}
void allocate_batch()
{
std::lock_guard<std::mutex> lock(state->mutex);
grow_pool.allocate_batch();
}
size_t get_node_max_size() const { return grow_pool.get_node_max_size(); }
size_t cache_size() const { return grow_pool.cache_size(); }
private:
void allocate_batch_in_background()

@ -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

@ -27,7 +27,8 @@ public:
explicit pool_deallocator(obj_pool_itf<T>* pool_ = nullptr) : pool(pool_) {}
void operator()(void* ptr)
{
if (ptr != nullptr and pool != nullptr) {
if (ptr != nullptr) {
static_cast<T*>(ptr)->~T();
pool->do_deallocate(ptr);
}
}

@ -54,6 +54,10 @@ inline void* align_to(void* pos, size_t alignment)
{
return reinterpret_cast<void*>(align_next(reinterpret_cast<std::uintptr_t>(pos), alignment));
}
inline void* offset_byte_ptr(void* pos, size_t offset)
{
return static_cast<void*>(static_cast<uint8_t*>(pos) + offset);
}
} // namespace srsran

@ -15,10 +15,10 @@
#include <stdint.h>
#include "srsenb/hdr/common/common_enb.h"
#include "srsenb/hdr/phy/phy_metrics.h"
#include "srsenb/hdr/stack/mac/mac_metrics.h"
#include "srsenb/hdr/stack/rrc/rrc_metrics.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/stack/upper/s1ap_metrics.h"
#include "srsran/common/metrics_hub.h"
#include "srsran/radio/radio_metrics.h"

@ -17,6 +17,7 @@
INCLUDES
*******************************************************************************/
#include <memory>
#include <stdint.h>
namespace srsenb {

@ -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

@ -16,7 +16,8 @@
#include "rrc_bearer_cfg.h"
#include "rrc_cell_cfg.h"
#include "rrc_metrics.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsenb/hdr/common/rnti_pool.h"
#include "srsran/adt/circular_buffer.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
@ -156,7 +157,7 @@ private:
// state
std::unique_ptr<freq_res_common_list> cell_res_list;
std::map<uint16_t, std::unique_ptr<ue> > users; // NOTE: has to have fixed addr
std::map<uint16_t, unique_rnti_ptr<ue> > users; // NOTE: has to have fixed addr
std::map<uint32_t, asn1::rrc::paging_record_s> pending_paging;
void process_release_complete(uint16_t rnti);

@ -13,7 +13,7 @@
#ifndef SRSENB_RRC_METRICS_H
#define SRSENB_RRC_METRICS_H
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include <vector>
namespace srsenb {

@ -144,18 +144,10 @@ public:
rrc* parent = nullptr;
bool connect_notified = false;
std::unique_ptr<rrc_mobility> mobility_handler;
unique_rnti_ptr<rrc_mobility> mobility_handler;
bool is_csfb = false;
void* operator new(size_t sz);
void* operator new[](size_t sz) = delete;
void operator delete(void* ptr)noexcept;
void operator delete[](void* ptr) = delete;
using ue_pool_t = srsran::background_mem_pool;
static ue_pool_t* get_ue_pool();
private:
// args
srsran::timer_handler::unique_timer activity_timer;

@ -13,7 +13,7 @@
#include <map>
#include <string.h>
#include "common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/adt/bounded_vector.h"
#include "srsran/adt/circular_map.h"
#include "srsran/common/buffer_pool.h"

@ -15,7 +15,7 @@
#include <map>
#include "common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/common/s1ap_pcap.h"

@ -6,6 +6,7 @@
# the distribution.
#
add_subdirectory(common)
add_subdirectory(phy)
add_subdirectory(stack)
@ -25,7 +26,7 @@ target_link_libraries(enb_cfg_parser ${LIBCONFIGPP_LIBRARIES})
add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc)
set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_upper srsenb_mac srsenb_rrc srslog system)
set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_upper srsenb_mac srsenb_rrc srslog system)
set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_upper srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system)
set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_phy srsgnb_stack srsgnb_upper srsgnb_mac srsgnb_rrc)
@ -34,7 +35,7 @@ set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1)
target_link_libraries(srsenb ${SRSENB_SOURCES}
${SRSRAN_SOURCES}
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}
${Boost_LIBRARIES}
${SEC_LIBRARIES}
${LIBCONFIGPP_LIBRARIES}
${SCTP_LIBRARIES})

@ -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

@ -11,8 +11,8 @@
*/
#include "srsenb/hdr/stack/enb_stack_lte.h"
#include "srsenb/hdr/common/rnti_pool.h"
#include "srsenb/hdr/enb.h"
#include "srsran/common/network_utils.h"
#include "srsran/interfaces/enb_metrics_interface.h"
#include "srsran/srslog/event_trace.h"
@ -71,6 +71,9 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
args = args_;
rrc_cfg = rrc_cfg_;
// Init RNTI memory pool
reserve_rnti_memblocks(args.mac.max_nof_ues);
// setup logging for each layer
mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level));
mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit);

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/rrc/mac_controller.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/asn1/rrc_utils.h"
#include "srsran/interfaces/enb_mac_interfaces.h"

@ -16,7 +16,6 @@
#include "srsran/asn1/asn1_utils.h"
#include "srsran/asn1/rrc_utils.h"
#include "srsran/common/bcd_helpers.h"
#include "srsran/common/int_helpers.h"
#include "srsran/common/standard_streams.h"
#include "srsran/interfaces/enb_mac_interfaces.h"
#include "srsran/interfaces/enb_pdcp_interfaces.h"
@ -24,8 +23,6 @@
#include "srsran/interfaces/sched_interface.h"
using srsran::byte_buffer_t;
using srsran::uint32_to_uint8;
using srsran::uint8_to_uint32;
using namespace asn1::rrc;
@ -33,10 +30,7 @@ namespace srsenb {
rrc::rrc(srsran::task_sched_handle task_sched_) :
logger(srslog::fetch_basic_logger("RRC")), task_sched(task_sched_), rx_pdu_queue(64)
{
// initialize ue pool
rrc::ue::get_ue_pool();
}
{}
rrc::~rrc() {}
@ -174,7 +168,7 @@ int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg)
if (user_it == users.end()) {
if (rnti != SRSRAN_MRNTI) {
// only non-eMBMS RNTIs are present in user map
std::unique_ptr<ue> u{new ue(this, rnti, sched_ue_cfg)};
unique_rnti_ptr<ue> u = make_rnti_obj<ue>(rnti, this, rnti, sched_ue_cfg);
if (u->init() != SRSRAN_SUCCESS) {
logger.error("Adding user rnti=0x%x - Failed to allocate user resources", rnti);
return SRSRAN_ERROR;

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/rrc/rrc_bearer_cfg.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/asn1/rrc_utils.h"
#include "srsran/rrc/rrc_cfg_utils.h"

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/rrc/rrc_nr.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/asn1/rrc_nr_utils.h"
#include "srsran/interfaces/nr_common_interface_types.h"
@ -216,7 +216,7 @@ int32_t rrc_nr::generate_sibs()
logger.error("Couldn't allocate PDU in %s().", __FUNCTION__);
return SRSRAN_ERROR;
}
asn1::bit_ref bref(mib_buf->msg, mib_buf->get_tailroom());
asn1::bit_ref bref(mib_buf->msg, mib_buf->get_tailroom());
mib_msg.pack(bref);
mib_buf->N_bytes = bref.distance_bytes();
logger.debug(mib_buf->msg, mib_buf->N_bytes, "MIB payload (%d B)", mib_buf->N_bytes);
@ -254,7 +254,7 @@ int32_t rrc_nr::generate_sibs()
logger.error("Couldn't allocate PDU in %s().", __FUNCTION__);
return SRSRAN_ERROR;
}
asn1::bit_ref bref(sib->msg, sib->get_tailroom());
asn1::bit_ref bref(sib->msg, sib->get_tailroom());
msg[msg_index].pack(bref);
sib->N_bytes = bref.distance_bytes();
sib_buffer.push_back(std::move(sib));

@ -61,27 +61,10 @@ int rrc::ue::init()
set_activity_timeout(MSG3_RX_TIMEOUT); // next UE response is Msg3
set_rlf_timeout();
mobility_handler.reset(new rrc_mobility(this));
mobility_handler = make_rnti_obj<rrc_mobility>(rnti, this);
return SRSRAN_SUCCESS;
}
rrc::ue::ue_pool_t* rrc::ue::get_ue_pool()
{
// Note: batch allocation is going to be explicitly called in enb class construction. The pool object, therefore,
// will only be initialized if we instantiate an eNB
static rrc::ue::ue_pool_t ue_pool(16, sizeof(ue), 4);
return &ue_pool;
}
void* rrc::ue::operator new(size_t sz)
{
return rrc::ue::get_ue_pool()->allocate_node(sz);
}
void rrc::ue::operator delete(void* ptr)noexcept
{
rrc::ue::get_ue_pool()->deallocate_node(ptr);
}
rrc_state_t rrc::ue::get_state()
{
return state;

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/upper/pdcp.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/interfaces/enb_gtpu_interfaces.h"
#include "srsran/interfaces/enb_rlc_interfaces.h"
#include "srsran/interfaces/enb_rrc_interfaces.h"

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/upper/rlc.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/interfaces/enb_mac_interfaces.h"
#include "srsran/interfaces/enb_pdcp_interfaces.h"
#include "srsran/interfaces/enb_rrc_interfaces.h"

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/upper/s1ap.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/adt/scope_exit.h"
#include "srsran/common/bcd_helpers.h"
#include "srsran/common/enb_events.h"

@ -11,8 +11,8 @@
*/
#include "sched_test_common.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsenb/hdr/stack/mac/sched.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "sched_common_test_suite.h"
#include "sched_ue_ded_test_suite.h"

@ -13,8 +13,8 @@
#ifndef SRSRAN_SCHED_TEST_UTILS_H
#define SRSRAN_SCHED_TEST_UTILS_H
#include "srsenb/hdr/common/common_enb.h"
#include "srsenb/hdr/stack/mac/sched.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsran/common/test_common.h"
#include "srsran/interfaces/sched_interface.h"
#include <algorithm>

@ -7,7 +7,7 @@
#
add_library(test_helpers test_helpers.cc)
target_link_libraries(test_helpers srsenb_rrc rrc_asn1 s1ap_asn1 srsran_common enb_cfg_parser ${LIBCONFIGPP_LIBRARIES})
target_link_libraries(test_helpers srsenb_rrc srsenb_common rrc_asn1 s1ap_asn1 srsran_common enb_cfg_parser ${LIBCONFIGPP_LIBRARIES})
# Simple PLMN -> MCC/MNC test
add_executable(plmn_test plmn_test.cc)
@ -17,7 +17,7 @@ add_executable(rrc_mobility_test rrc_mobility_test.cc)
target_link_libraries(rrc_mobility_test srsran_asn1 test_helpers)
add_executable(erab_setup_test erab_setup_test.cc)
target_link_libraries(erab_setup_test srsenb_rrc rrc_asn1 s1ap_asn1 srsran_common srsran_asn1 enb_cfg_parser test_helpers ${LIBCONFIGPP_LIBRARIES})
target_link_libraries(erab_setup_test test_helpers ${LIBCONFIGPP_LIBRARIES})
add_executable(rrc_meascfg_test rrc_meascfg_test.cc)
target_link_libraries(rrc_meascfg_test test_helpers)

@ -10,7 +10,7 @@
*
*/
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/asn1/rrc/common.h"
#include "srsran/asn1/rrc_utils.h"
#include "srsran/common/bcd_helpers.h"

Loading…
Cancel
Save