Skip to content

PHR codelet causing infinite loop in ck_epoch_dispatch. #26

@matthewbalkwill

Description

@matthewbalkwill

In srsRAN, in lib/scheduler/ue_scheduling/ue_event_managr.cpp, we call hook_mac_sched_ul_phr_indication as below.
This in slightkl incorrect .... the for loop walks the "phr" vector, but we pass the higher level phr_ind to to the codelet. Ideally should pass "cell_phr".

void ue_event_manager::handle_ul_phr_indication(const ul_phr_indication_message& phr_ind)
{
auto phr_ind_ptr = ind_pdu_pool->create_pdu(phr_ind);
if (phr_ind_ptr == nullptr) {
return;
}

auto handle_phr_impl = this, phr_ind = std::move(phr_ind_ptr) {
auto& u = ue_db[phr_ind->ue_index];
for (const cell_ph_report& cell_phr : phr_ind->phr.get_phr()) {
srsran_sanity_check(cell_phr.serv_cell_id < u.nof_cells(),
"Invalid serving cell index={}",
fmt::underlying(cell_phr.serv_cell_id));
auto& ue_cc = u.get_cell(cell_phr.serv_cell_id);

  ue_cc.get_pusch_power_controller().handle_phr(cell_phr, phr_ind->slot_rx);

#ifdef JBPF_ENABLED
hook_mac_sched_ul_phr_indication(const_cast<void*>(static_cast<const void*>(&cell_phr)),
0, phr_ind->ue_index, ue_cc.cfg().cell_cfg_common.pci, (uint16_t)phr_ind->rnti, sizeof(cell_ph_report));
#endif

The codelet (codelets/mac/mac_sched_phr_stats.cpp) also does the walk of the vector …

auto ph_reports = mac_ctx.phr.get_phr();
for (int i=0; i<srsran::MAX_NOF_DU_CELLS; i++) {
    if (i < ph_reports.size()) {
        int new_val = 0;
        //uint64_t key = ((uint64_t)ph_reports[i].serv_cell_id << 31) << 1 | (uint64_t)ctx->du_ue_index;
        uint32_t ind = JBPF_PROTOHASH_LOOKUP_ELEM_64(out, stats, phr_hash, ph_reports[i].serv_cell_id, ctx->du_ue_index, new_val);
        if (new_val) {

For some reason , this manifests as an infinite loop in srsRAN_project/external/jbpf/3p/ck/src/ck_epoch.c, function ck_epoch_dispatch …

for (cursor = head; cursor != NULL; cursor = next) {
struct ck_epoch_entry *entry =
ck_epoch_entry_container(cursor);

    next = CK_STACK_NEXT(cursor);
    if (deferred != NULL)
        ck_stack_push_spnc(deferred, &entry->stack_entry);
    else
        entry->function(entry);

    i++;
}

For debug code, I updated this as below. This shows that there are duplicate pointers on the list, which causes the infinite loop.

// Use a simple array to detect cycles (addresses of nodes already seen)
ck_stack_entry_t *seen[1024]; // adjust size if your lists are longer
unsigned int seen_count = 0;

for (cursor = head; cursor != NULL; cursor = next) {
    struct ck_epoch_entry *entry =
        ck_epoch_entry_container(cursor);

    next = CK_STACK_NEXT(cursor);

// Check for self-loop or cycles
for (unsigned int s = 0; s < seen_count; s++) {
if (seen[s] == cursor) {
printf("[ERROR] Detected cycle in pending[%u] at node %p (epoch=%u)\n",
epoch, cursor, epoch);
return i; // stop to prevent infinite loop
}
}

if (seen_count < sizeof(seen)/sizeof(seen[0])) {
seen[seen_count++] = cursor;
}

    if (deferred != NULL)
        ck_stack_push_spnc(deferred, &entry->stack_entry);
    else
        entry->function(entry);
    i++;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions