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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions