2121
2222using namespace srsran ;
2323
24- resource_grid_pool_impl::resource_grid_pool_impl (task_executor* async_executor_,
25- std::vector<resource_grid_ptr> grids_) :
26- logger(srslog::fetch_basic_logger(" PHY" , true )),
27- grids(std::move(grids_)),
28- grids_scope_count(grids.size()),
29- grids_str_zero(grids.size()),
30- grids_str_reserved(grids.size()),
31- async_executor(async_executor_)
24+ shared_resource_grid resource_grid_pool_wrapper::try_reserve (srsran::stop_event_token token)
3225{
33- // Create tracing list.
34- for (unsigned i_grid = 0 , i_grid_end = grids.size (); i_grid != i_grid_end; ++i_grid) {
35- grids_str_zero[i_grid] = " set_all_zero#" + std::to_string (i_grid);
36- grids_str_reserved[i_grid] = " rg_reserved#" + std::to_string (i_grid);
37- }
38-
39- // All grids scopes must be zero.
40- std::fill (grids_scope_count.begin (), grids_scope_count.end (), ref_counter_available);
41- }
42-
43- resource_grid_pool_impl::~resource_grid_pool_impl ()
44- {
45- // Wait for all resource grid to be returned to the pool.
46- std::for_each (grids_scope_count.begin (), grids_scope_count.end (), [](auto & ref_counter) {
47- for (unsigned current_ref_counter = ref_counter.load (std::memory_order_acquire);
48- current_ref_counter != ref_counter_available;
49- current_ref_counter = ref_counter.load (std::memory_order_acquire)) {
50- std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
51- };
52- });
53- }
54-
55- shared_resource_grid resource_grid_pool_impl::allocate_resource_grid (slot_point slot)
56- {
57- // Trace point for grid reservation.
58- trace_point tp = l1_common_tracer.now ();
59-
60- // Select an identifier from the current request counter.
61- unsigned identifier = counter;
26+ // Try to transition from available to one scope.
27+ unsigned expected = ref_counter_available;
28+ bool success = scope_count.compare_exchange_strong (expected, 1 , std::memory_order_acq_rel);
6229
63- // Increment request counter and wrap it with the number of grids.
64- counter = (counter + 1 ) % grids.size ();
65-
66- // Select counter for the selected identifier.
67- std::atomic<unsigned >& ref_count = grids_scope_count[identifier];
68-
69- // Try to reset the reference counter.
70- unsigned expected = ref_counter_available;
71- bool available = ref_count.compare_exchange_strong (expected, 1 , std::memory_order_acq_rel);
72-
73- // Return an invalid grid if not available.
74- if (!available) {
75- logger.warning (slot.sfn (), slot.slot_index (), " Resource grid with identifier {} is not available." , identifier);
30+ // Return an invalid shared grid if the state transition is unsuccessful.
31+ if (!success) {
7632 return {};
7733 }
7834
79- // Trace the resource grid reservation .
80- l1_common_tracer << trace_event (grids_str_reserved[identifier]. c_str (), tp );
35+ // Keep token if successful .
36+ stop_token = std::move (token );
8137
82- return {*this , ref_count, identifier};
38+ // Create valid shared resource grid.
39+ return shared_resource_grid{*this , scope_count};
8340}
8441
85- resource_grid& resource_grid_pool_impl::get ( unsigned identifier )
42+ void resource_grid_pool_wrapper::release ( )
8643{
87- srsran_assert (identifier < grids.size (),
88- " RG identifier (i.e., {}) is out of range {}." ,
89- identifier,
90- interval<unsigned >(0 , grids.size ()));
91- return *grids[identifier];
44+ // Move token to the scope of this method before transitioning to available.
45+ stop_event_token token = std::move (stop_token);
46+
47+ // Transition to available.
48+ [[maybe_unused]] unsigned prev_scope_count = scope_count.exchange (ref_counter_available, std::memory_order_acq_rel);
49+
50+ // Assert that the grid is not present in any scope before becoming available.
51+ srsran_assert ((prev_scope_count == ref_counter_available) || (prev_scope_count == 0 ),
52+ " The resource grid state cannot transition to available while it is present in {} scopes." ,
53+ prev_scope_count);
9254}
9355
94- void resource_grid_pool_impl ::notify_release_scope (unsigned identifier )
56+ void resource_grid_pool_wrapper ::notify_release_scope ()
9557{
96- // verify the identifier is valid.
97- srsran_assert (identifier < grids.size (),
98- " RG identifier (i.e., {}) is out of range {}." ,
99- identifier,
100- interval<unsigned >(0 , grids.size ()));
101-
10258 // Skip zeroing if the grid is empty.
103- if (grids[identifier] ->get_reader ().is_empty ()) {
104- grids_scope_count[identifier] = ref_counter_available ;
59+ if (grid ->get_reader ().is_empty ()) {
60+ release () ;
10561 return ;
10662 }
10763
10864 // If the pool is not configured with an asynchronous executor, it skips the zeroing process.
10965 if (async_executor == nullptr ) {
110- grids_scope_count[identifier] = ref_counter_available ;
66+ release () ;
11167 return ;
11268 }
11369
11470 // Create lambda function for setting the grid to zero.
115- auto set_all_zero_func = [this , identifier]() noexcept SRSRAN_RTSAN_NONBLOCKING {
116- trace_point tp = l1_common_tracer.now ();
117-
71+ auto set_all_zero_func = [this ]() noexcept SRSRAN_RTSAN_NONBLOCKING {
11872 // Set grid to zero.
119- grids[identifier] ->set_all_zero ();
73+ grid ->set_all_zero ();
12074
12175 // Make the grid available.
122- grids_scope_count[identifier] = ref_counter_available;
123-
124- l1_common_tracer << trace_event (grids_str_zero[identifier].c_str (), tp);
76+ release ();
12577 };
12678
12779 // Try to execute the asynchronous housekeeping task.
@@ -130,6 +82,41 @@ void resource_grid_pool_impl::notify_release_scope(unsigned identifier)
13082 // Ensure the resource grid is marked as available even if it is not empty.
13183 // Avoid warnings about failure to prevent false alarms during gNb teardown.
13284 if (!success) {
133- grids_scope_count[identifier] = ref_counter_available ;
85+ release () ;
13486 }
13587}
88+
89+ resource_grid& resource_grid_pool_wrapper::get ()
90+ {
91+ return *grid;
92+ }
93+
94+ resource_grid_pool_impl::~resource_grid_pool_impl ()
95+ {
96+ stop_control.stop ();
97+ }
98+
99+ shared_resource_grid resource_grid_pool_impl::allocate_resource_grid (slot_point slot)
100+ {
101+ // Get a stop token, return an invalid grid if it is stopping.
102+ stop_event_token token = stop_control.get_token ();
103+ if (token.stop_requested ()) {
104+ return {};
105+ }
106+
107+ // Select an identifier from the current request counter.
108+ unsigned identifier = counter;
109+
110+ // Increment request counter and wrap it with the number of grids.
111+ counter = (counter + 1 ) % grids.size ();
112+
113+ // Try reserving the resource grid.
114+ shared_resource_grid grid = grids[identifier].try_reserve (std::move (token));
115+
116+ // Log a warning message if the grid is not available.
117+ if (!grid) {
118+ logger.warning (slot.sfn (), slot.slot_index (), " Resource grid with identifier {} is not available." , identifier);
119+ }
120+
121+ return grid;
122+ }
0 commit comments