tbf: Use plain old data structure (PODS) for llist management
The PODS struct has a back pointer to access the actual object. llist_pods_for_each_entry traverses the list of struct llist_pods and makes the entry available (through the back pointer). Ticket: SYS#389 Sponsored-by: On-Waves ehf
This commit is contained in:
parent
4bbe3349c2
commit
1b3864fc47
17
src/bts.cpp
17
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;
|
uint8_t l, trx, ts, any_tbf = 0;
|
||||||
struct gprs_rlcmac_tbf *tbf;
|
struct gprs_rlcmac_tbf *tbf;
|
||||||
|
struct llist_pods *lpods;
|
||||||
struct gprs_rlcmac_paging *pag;
|
struct gprs_rlcmac_paging *pag;
|
||||||
uint8_t slot_mask[8];
|
uint8_t slot_mask[8];
|
||||||
int8_t first_ts; /* must be signed */
|
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. */
|
* Don't mark, if TBF uses a different slot that is already marked. */
|
||||||
memset(slot_mask, 0, sizeof(slot_mask));
|
memset(slot_mask, 0, sizeof(slot_mask));
|
||||||
for (l = 0; tbfs_lists[l]; l++) {
|
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;
|
first_ts = -1;
|
||||||
for (ts = 0; ts < 8; ts++) {
|
for (ts = 0; ts < 8; ts++) {
|
||||||
if (tbf->pdch[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)
|
gprs_rlcmac_tbf *BTS::tbf_by_tlli(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)
|
||||||
{
|
{
|
||||||
struct gprs_rlcmac_tbf *tbf;
|
struct gprs_rlcmac_tbf *tbf;
|
||||||
|
struct llist_pods *lpods;
|
||||||
if (dir == GPRS_RLCMAC_UL_TBF) {
|
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);
|
OSMO_ASSERT(tbf->direction == dir);
|
||||||
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
|
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
|
||||||
&& tbf->tlli() == tlli && tbf->is_tlli_valid())
|
&& tbf->tlli() == tlli && tbf->is_tlli_valid())
|
||||||
return tbf;
|
return tbf;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
OSMO_ASSERT(tbf->direction == dir);
|
||||||
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
|
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
|
||||||
&& tbf->tlli() == tlli)
|
&& 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)
|
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 gprs_rlcmac_dl_tbf *tbf;
|
||||||
|
struct llist_pods *lpods;
|
||||||
|
|
||||||
/* only one TBF can poll on specific TS/FN, because scheduler can only
|
/* 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 */
|
* 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)
|
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
|
||||||
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
|
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
|
||||||
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
|
&& 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)
|
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 gprs_rlcmac_ul_tbf *tbf;
|
||||||
|
struct llist_pods *lpods;
|
||||||
|
|
||||||
/* only one TBF can poll on specific TS/FN, because scheduler can only
|
/* 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 */
|
* 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)
|
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
|
||||||
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
|
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
|
||||||
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
|
&& 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)
|
enum gprs_rlcmac_tbf_direction dir)
|
||||||
{
|
{
|
||||||
gprs_rlcmac_tbf *tbf;
|
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);
|
OSMO_ASSERT(tbf->direction == dir);
|
||||||
if (tbf->tfi() != tfi)
|
if (tbf->tfi() != tfi)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -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 **ul_ack_tbf)
|
||||||
{
|
{
|
||||||
struct gprs_rlcmac_tbf *tbf;
|
struct gprs_rlcmac_tbf *tbf;
|
||||||
|
struct llist_pods *lpods;
|
||||||
uint32_t poll_fn;
|
uint32_t poll_fn;
|
||||||
|
|
||||||
/* check special TBF for events */
|
/* check special TBF for events */
|
||||||
|
@ -38,7 +39,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
|
||||||
if ((block_nr % 3) == 2)
|
if ((block_nr % 3) == 2)
|
||||||
poll_fn ++;
|
poll_fn ++;
|
||||||
poll_fn = poll_fn % 2715648;
|
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 */
|
/* this trx, this ts */
|
||||||
if (tbf->trx->trx_no != trx || tbf->control_ts != ts)
|
if (tbf->trx->trx_no != trx || tbf->control_ts != ts)
|
||||||
continue;
|
continue;
|
||||||
|
@ -54,7 +55,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
|
||||||
*ul_ass_tbf = tbf;
|
*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?"
|
#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 */
|
/* this trx, this ts */
|
||||||
if (tbf->trx->trx_no != trx || tbf->control_ts != ts)
|
if (tbf->trx->trx_no != trx || tbf->control_ts != ts)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -33,10 +33,11 @@ void PollController::expireTimedout(int frame_number)
|
||||||
struct gprs_rlcmac_bts *bts = m_bts.bts_data();
|
struct gprs_rlcmac_bts *bts = m_bts.bts_data();
|
||||||
struct gprs_rlcmac_tbf *tbf;
|
struct gprs_rlcmac_tbf *tbf;
|
||||||
struct gprs_rlcmac_sba *sba, *sba2;
|
struct gprs_rlcmac_sba *sba, *sba2;
|
||||||
|
struct llist_pods *lpods;
|
||||||
uint32_t elapsed;
|
uint32_t elapsed;
|
||||||
|
|
||||||
/* check for poll timeout */
|
/* 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) {
|
if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
|
||||||
elapsed = (frame_number + 2715648 - tbf->poll_fn)
|
elapsed = (frame_number + 2715648 - tbf->poll_fn)
|
||||||
% 2715648;
|
% 2715648;
|
||||||
|
@ -44,7 +45,7 @@ void PollController::expireTimedout(int frame_number)
|
||||||
tbf->poll_timeout();
|
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) {
|
if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
|
||||||
elapsed = (frame_number + 2715648 - tbf->poll_fn)
|
elapsed = (frame_number + 2715648 - tbf->poll_fn)
|
||||||
% 2715648;
|
% 2715648;
|
||||||
|
|
17
src/tbf.cpp
17
src/tbf.cpp
|
@ -286,7 +286,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
|
||||||
#warning "TODO: Could/Should generate bssgp_tx_llc_discarded"
|
#warning "TODO: Could/Should generate bssgp_tx_llc_discarded"
|
||||||
tbf->m_llc.clear(tbf->bts);
|
tbf->m_llc.clear(tbf->bts);
|
||||||
tbf_unlink_pdch(tbf);
|
tbf_unlink_pdch(tbf);
|
||||||
llist_del(&tbf->list);
|
llist_del(&tbf->list.list);
|
||||||
|
|
||||||
if (tbf->direction == GPRS_RLCMAC_UL_TBF)
|
if (tbf->direction == GPRS_RLCMAC_UL_TBF)
|
||||||
tbf->bts->tbf_ul_freed();
|
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)
|
if (!tbf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* Back pointer for PODS llist compatibility */
|
||||||
|
tbf->list.back = tbf;
|
||||||
|
|
||||||
tbf->m_created_ts = time(NULL);
|
tbf->m_created_ts = time(NULL);
|
||||||
tbf->bts = bts->bts;
|
tbf->bts = bts->bts;
|
||||||
tbf->m_tfi = tfi;
|
tbf->m_tfi = tfi;
|
||||||
|
@ -548,7 +551,7 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
llist_add(&tbf->list, &bts->ul_tbfs);
|
llist_add(&tbf->list.list, &bts->ul_tbfs);
|
||||||
tbf->bts->tbf_ul_created();
|
tbf->bts->tbf_ul_created();
|
||||||
|
|
||||||
return tbf;
|
return tbf;
|
||||||
|
@ -581,7 +584,7 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
llist_add(&tbf->list, &bts->dl_tbfs);
|
llist_add(&tbf->list.list, &bts->dl_tbfs);
|
||||||
tbf->bts->tbf_dl_created();
|
tbf->bts->tbf_dl_created();
|
||||||
|
|
||||||
return tbf;
|
return tbf;
|
||||||
|
@ -1805,11 +1808,11 @@ bool gprs_rlcmac_tbf::dl_window_stalled() const
|
||||||
|
|
||||||
void gprs_rlcmac_tbf::rotate_in_list()
|
void gprs_rlcmac_tbf::rotate_in_list()
|
||||||
{
|
{
|
||||||
llist_del(&list);
|
llist_del(&list.list);
|
||||||
if (direction == GPRS_RLCMAC_UL_TBF)
|
if (direction == GPRS_RLCMAC_UL_TBF)
|
||||||
llist_add(&list, &bts->bts_data()->ul_tbfs);
|
llist_add(&list.list, &bts->bts_data()->ul_tbfs);
|
||||||
else
|
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
|
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)
|
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(),
|
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",
|
tbf->tlli(), tbf->is_tlli_valid() ? "valid" : "invalid",
|
||||||
|
|
24
src/tbf.h
24
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_DL_ASS 7
|
||||||
#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
|
#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 {
|
struct gprs_rlcmac_tbf {
|
||||||
|
|
||||||
static void free_all(struct gprs_rlcmac_trx *trx);
|
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 */
|
/* attempt to make things a bit more fair */
|
||||||
void rotate_in_list();
|
void rotate_in_list();
|
||||||
|
|
||||||
struct llist_head list;
|
struct llist_pods list;
|
||||||
uint32_t state_flags;
|
uint32_t state_flags;
|
||||||
enum gprs_rlcmac_tbf_direction direction;
|
enum gprs_rlcmac_tbf_direction direction;
|
||||||
struct gprs_rlcmac_trx *trx;
|
struct gprs_rlcmac_trx *trx;
|
||||||
|
|
Loading…
Reference in New Issue