diff --git a/src/bts.cpp b/src/bts.cpp index ff1a0650..77c3f3ef 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -138,6 +138,7 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv) { uint8_t l, trx, ts, any_tbf = 0; struct gprs_rlcmac_tbf *tbf; + struct llist_pods *lpods; struct gprs_rlcmac_paging *pag; uint8_t slot_mask[8]; int8_t first_ts; /* must be signed */ @@ -158,7 +159,7 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv) * Don't mark, if TBF uses a different slot that is already marked. */ memset(slot_mask, 0, sizeof(slot_mask)); for (l = 0; tbfs_lists[l]; l++) { - llist_for_each_entry(tbf, tbfs_lists[l], list) { + llist_pods_for_each_entry(tbf, tbfs_lists[l], list, lpods) { first_ts = -1; for (ts = 0; ts < 8; ts++) { if (tbf->pdch[ts]) { @@ -232,15 +233,16 @@ gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_tlli(uint32_t tlli) gprs_rlcmac_tbf *BTS::tbf_by_tlli(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir) { struct gprs_rlcmac_tbf *tbf; + struct llist_pods *lpods; if (dir == GPRS_RLCMAC_UL_TBF) { - llist_for_each_entry(tbf, &m_bts.ul_tbfs, list) { + llist_pods_for_each_entry(tbf, &m_bts.ul_tbfs, list, lpods) { OSMO_ASSERT(tbf->direction == dir); if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) && tbf->tlli() == tlli && tbf->is_tlli_valid()) return tbf; } } else { - llist_for_each_entry(tbf, &m_bts.dl_tbfs, list) { + llist_pods_for_each_entry(tbf, &m_bts.dl_tbfs, list, lpods) { OSMO_ASSERT(tbf->direction == dir); if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) && tbf->tlli() == tlli) @@ -253,10 +255,11 @@ gprs_rlcmac_tbf *BTS::tbf_by_tlli(uint32_t tlli, enum gprs_rlcmac_tbf_direction gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) { struct gprs_rlcmac_dl_tbf *tbf; + struct llist_pods *lpods; /* only one TBF can poll on specific TS/FN, because scheduler can only * schedule one downlink control block (with polling) at a FN per TS */ - llist_for_each_entry(tbf, &m_bts.dl_tbfs, list) { + llist_pods_for_each_entry(tbf, &m_bts.dl_tbfs, list, lpods) { if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED && tbf->poll_fn == fn && tbf->trx->trx_no == trx @@ -270,10 +273,11 @@ gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) { struct gprs_rlcmac_ul_tbf *tbf; + struct llist_pods *lpods; /* only one TBF can poll on specific TS/FN, because scheduler can only * schedule one downlink control block (with polling) at a FN per TS */ - llist_for_each_entry(tbf, &m_bts.ul_tbfs, list) { + llist_pods_for_each_entry(tbf, &m_bts.ul_tbfs, list, lpods) { if (tbf->state_is_not(GPRS_RLCMAC_RELEASING) && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED && tbf->poll_fn == fn && tbf->trx->trx_no == trx @@ -1042,8 +1046,9 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l enum gprs_rlcmac_tbf_direction dir) { gprs_rlcmac_tbf *tbf; + struct llist_pods *lpods; - llist_for_each_entry(tbf, tbf_list, list) { + llist_pods_for_each_entry(tbf, tbf_list, list, lpods) { OSMO_ASSERT(tbf->direction == dir); if (tbf->tfi() != tfi) continue; diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 92e97ece..dab38d83 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -31,6 +31,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_tbf **ul_ack_tbf) { struct gprs_rlcmac_tbf *tbf; + struct llist_pods *lpods; uint32_t poll_fn; /* check special TBF for events */ @@ -38,7 +39,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts, if ((block_nr % 3) == 2) poll_fn ++; poll_fn = poll_fn % 2715648; - llist_for_each_entry(tbf, &bts->ul_tbfs, list) { + llist_pods_for_each_entry(tbf, &bts->ul_tbfs, list, lpods) { /* this trx, this ts */ if (tbf->trx->trx_no != trx || tbf->control_ts != ts) continue; @@ -54,7 +55,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts, *ul_ass_tbf = tbf; #warning "Is this supposed to be fair? The last TBF for each wins? Maybe use llist_add_tail and skip once we have all states?" } - llist_for_each_entry(tbf, &bts->dl_tbfs, list) { + llist_pods_for_each_entry(tbf, &bts->dl_tbfs, list, lpods) { /* this trx, this ts */ if (tbf->trx->trx_no != trx || tbf->control_ts != ts) continue; diff --git a/src/poll_controller.cpp b/src/poll_controller.cpp index 0f46472f..dea75edf 100644 --- a/src/poll_controller.cpp +++ b/src/poll_controller.cpp @@ -33,10 +33,11 @@ void PollController::expireTimedout(int frame_number) struct gprs_rlcmac_bts *bts = m_bts.bts_data(); struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_sba *sba, *sba2; + struct llist_pods *lpods; uint32_t elapsed; /* check for poll timeout */ - llist_for_each_entry(tbf, &bts->ul_tbfs, list) { + llist_pods_for_each_entry(tbf, &bts->ul_tbfs, list, lpods) { if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) { elapsed = (frame_number + 2715648 - tbf->poll_fn) % 2715648; @@ -44,7 +45,7 @@ void PollController::expireTimedout(int frame_number) tbf->poll_timeout(); } } - llist_for_each_entry(tbf, &bts->dl_tbfs, list) { + llist_pods_for_each_entry(tbf, &bts->dl_tbfs, list, lpods) { if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) { elapsed = (frame_number + 2715648 - tbf->poll_fn) % 2715648; diff --git a/src/tbf.cpp b/src/tbf.cpp index 12016425..22570185 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -286,7 +286,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf) #warning "TODO: Could/Should generate bssgp_tx_llc_discarded" tbf->m_llc.clear(tbf->bts); tbf_unlink_pdch(tbf); - llist_del(&tbf->list); + llist_del(&tbf->list.list); if (tbf->direction == GPRS_RLCMAC_UL_TBF) tbf->bts->tbf_ul_freed(); @@ -491,6 +491,9 @@ static int setup_tbf(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_bts *bts, if (!tbf) return -1; + /* Back pointer for PODS llist compatibility */ + tbf->list.back = tbf; + tbf->m_created_ts = time(NULL); tbf->bts = bts->bts; tbf->m_tfi = tfi; @@ -548,7 +551,7 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, return NULL; } - llist_add(&tbf->list, &bts->ul_tbfs); + llist_add(&tbf->list.list, &bts->ul_tbfs); tbf->bts->tbf_ul_created(); return tbf; @@ -581,7 +584,7 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, return NULL; } - llist_add(&tbf->list, &bts->dl_tbfs); + llist_add(&tbf->list.list, &bts->dl_tbfs); tbf->bts->tbf_dl_created(); return tbf; @@ -1805,11 +1808,11 @@ bool gprs_rlcmac_tbf::dl_window_stalled() const void gprs_rlcmac_tbf::rotate_in_list() { - llist_del(&list); + llist_del(&list.list); if (direction == GPRS_RLCMAC_UL_TBF) - llist_add(&list, &bts->bts_data()->ul_tbfs); + llist_add(&list.list, &bts->bts_data()->ul_tbfs); else - llist_add(&list, &bts->bts_data()->dl_tbfs); + llist_add(&list.list, &bts->bts_data()->dl_tbfs); } uint8_t gprs_rlcmac_tbf::tsc() const @@ -1819,7 +1822,7 @@ uint8_t gprs_rlcmac_tbf::tsc() const void tbf_print_vty_info(struct vty *vty, llist_head *ltbf) { - gprs_rlcmac_tbf *tbf = llist_entry(ltbf, gprs_rlcmac_tbf, list); + gprs_rlcmac_tbf *tbf = llist_pods_entry(ltbf, gprs_rlcmac_tbf); vty_out(vty, "TBF: TFI=%d TLLI=0x%08x (%s) DIR=%s IMSI=%s%s", tbf->tfi(), tbf->tlli(), tbf->is_tlli_valid() ? "valid" : "invalid", diff --git a/src/tbf.h b/src/tbf.h index 4d209879..95355bd6 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -84,6 +84,28 @@ enum gprs_rlcmac_tbf_direction { #define GPRS_RLCMAC_FLAG_TO_DL_ASS 7 #define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */ +struct llist_pods { + struct llist_head list; + void *back; +}; + +#define llist_pods_entry(ptr, type) \ + ((type *)(container_of(ptr, struct llist_pods, list)->back)) + +/** + * llist_pods_for_each_entry - like llist_for_each_entry, but uses + * struct llist_pods ->back to access the entry. + * This is necessary for non-PODS classes because container_of is + * not guaranteed to work anymore. */ +#define llist_pods_for_each_entry(pos, head, member, lpods) \ + for (lpods = llist_entry((head)->next, typeof(struct llist_pods), list), \ + pos = ((typeof(pos))lpods->back), \ + prefetch(pos->member.list.next); \ + &lpods->list != (head); \ + lpods = llist_entry(lpods->list.next, typeof(struct llist_pods), list), \ + pos = ((typeof(pos))lpods->back),\ + prefetch(pos->member.list.next)) + struct gprs_rlcmac_tbf { static void free_all(struct gprs_rlcmac_trx *trx); @@ -143,7 +165,7 @@ struct gprs_rlcmac_tbf { /* attempt to make things a bit more fair */ void rotate_in_list(); - struct llist_head list; + struct llist_pods list; uint32_t state_flags; enum gprs_rlcmac_tbf_direction direction; struct gprs_rlcmac_trx *trx;