From 2d759e90f6593fb21671a17c187bc1dcd8100210 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 31 Jan 2018 17:00:06 +0100 Subject: Simplify TS alloc: split allocation * generalize TS allocation and move it into separate function * move single-slot allocation into separate function * use common functions for TS allocation on both UL and DL Change-Id: Ied45ae380c345bc76fe9d6fd9a6184d1109f83f2 Related: OS#2282 --- src/gprs_rlcmac_ts_alloc.cpp | 152 +++++++++++++++++++++++++++---------------- src/mslot_class.c | 8 +++ src/mslot_class.h | 2 + 3 files changed, 105 insertions(+), 57 deletions(-) diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 9c2b9211..8ab3b93f 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -709,6 +709,87 @@ int find_multi_slots(struct gprs_rlcmac_trx *trx, uint8_t mslot_class, uint8_t * return 0; } +/*! Count used bits in slots and reserved_slots bitmasks + * + * \param[in] slots Timeslots in use + * \param[in] reserved_slots Reserved timeslots + * \param[out] slotcount Number of TS in use + * \param[out] avail_count Number of reserved TS + */ +static void update_slot_counters(uint8_t slots, uint8_t reserved_slots, uint8_t *slotcount, uint8_t *avail_count) +{ + (*slotcount) = pcu_bitcount(slots); + (*avail_count) = pcu_bitcount(reserved_slots); +} + +/*! Return slot mask with single TS from a given UL/DL set according to TBF's direction, ts pointer is set to that TS + * number or to negative value on error + * + * \param[in] trx Pointer to TRX object + * \param[in] tbf Pointer to TBF object + * \param[in] dl_slots set of DL timeslots + * \param[in] ul_slots set of UL timeslots + * \param[in] ts corresponding TS or -1 for autoselection + * \returns slot mask with single UL or DL timeslot number if possible + */ +static uint8_t get_single_ts(const gprs_rlcmac_trx *trx, const gprs_rlcmac_tbf *tbf, uint8_t dl_slots, uint8_t ul_slots, + int ts) +{ + uint8_t ret = dl_slots & ul_slots; /* Make sure to consider the first common slot only */ + + if (ts < 0) + ts = find_least_busy_pdch(trx, tbf->direction, ret, compute_usage_by_num_tbfs, NULL, NULL); + + if (ts < 0) + return ffs(ret); + + return ret & (1 << ts); +} + +/*! Find set of timeslots available for allocation + * + * \param[in] trx Pointer to TRX object + * \param[in] tbf Pointer to TBF object + * \param[in] single Flag to force the single TS allocation + * \param[in] ul_slots set of UL timeslots + * \param[in] dl_slots set of DL timeslots + * \param[in] reserved_ul_slots set of reserved UL timeslots + * \param[in] reserved_dl_slots set of reserved DL timeslots + * \param[in] first_common_ts First TS common for both UL and DL or -1 if unknown + * \returns negative error code or selected TS on success + */ +static int tbf_select_slot_set(const gprs_rlcmac_tbf *tbf, const gprs_rlcmac_trx *trx, bool single, + uint8_t ul_slots, uint8_t dl_slots, + uint8_t reserved_ul_slots, uint8_t reserved_dl_slots, + int8_t first_common_ts) +{ + uint8_t sl = tbf->direction != GPRS_RLCMAC_DL_TBF ? ul_slots : dl_slots; + char slot_info[9] = { 0 }; + + if (single) + sl = get_single_ts(trx, tbf, dl_slots, ul_slots, first_common_ts); + + if (!sl) { + LOGP(DRLCMAC, LOGL_NOTICE, "No %s slots available\n", + tbf->direction != GPRS_RLCMAC_DL_TBF ? "uplink" : "downlink"); + return -EINVAL; + } + + if (tbf->direction != GPRS_RLCMAC_DL_TBF) { + snprintf(slot_info, 9, OSMO_BIT_SPEC, OSMO_BIT_PRINT_EX(reserved_ul_slots, 'u')); + masked_override_with(slot_info, sl, 'U'); + LOGPC(DRLCMAC, LOGL_DEBUG, "- Selected UL"); + } else { + snprintf(slot_info, 9, OSMO_BIT_SPEC, OSMO_BIT_PRINT_EX(reserved_dl_slots, 'd')); + masked_override_with(slot_info, sl, 'D'); + LOGPC(DRLCMAC, LOGL_DEBUG, "- Selected DL"); + } + + LOGPC(DRLCMAC, LOGL_DEBUG, " slots: (TS=0)\"%s\"(TS=7)%s\n", slot_info, single ? ", single" : ""); + + return sl; +} + /*! Slot Allocation: Algorithm B * * Assign as many downlink slots as possible. @@ -773,86 +854,43 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm reserved_dl_slots = dl_slots; reserved_ul_slots = ul_slots; - /* Step 3: Derive the slot set for the current TBF */ - if (single) { - /* Make sure to consider the first common slot only */ - ul_slots = dl_slots = dl_slots & ul_slots; - - ts = first_common_ts; - - if (ts < 0) - ts = find_least_busy_pdch(trx, tbf->direction, - dl_slots & ul_slots, compute_usage_by_num_tbfs, - NULL, NULL); - if (ts < 0) - ul_slots = dl_slots = pcu_lsb(dl_slots & ul_slots); - else - ul_slots = dl_slots = (dl_slots & ul_slots) & (1<direction == GPRS_RLCMAC_DL_TBF) { - LOGP(DRLCMAC, LOGL_DEBUG, - "- Selected DL slots: (TS=0)\"%s\"(TS=7)%s\n", - set_flag_chars(set_flag_chars(slot_info, - reserved_dl_slots, 'd', '.'), - dl_slots, 'D'), - single ? ", single" : ""); - - /* assign downlink */ - if (dl_slots == 0) { - LOGP(DRLCMAC, LOGL_NOTICE, "No downlink slots " - "available\n"); - return -EINVAL; - } - slotcount = pcu_bitcount(dl_slots); - first_ts = ffs(dl_slots) - 1; - avail_count = pcu_bitcount(reserved_dl_slots); - + dl_slots = rc; + update_slot_counters(dl_slots, reserved_dl_slots, &slotcount, &avail_count); } else { int free_usf = -1; + ul_slots = rc; + if (first_common_ts >= 0) ul_slots = 1 << first_common_ts; else ul_slots = ul_slots & dl_slots; - ts = find_least_busy_pdch(trx, GPRS_RLCMAC_UL_TBF, - ul_slots, compute_usage_by_num_tbfs, - NULL, &free_usf); + ts = find_least_busy_pdch(trx, GPRS_RLCMAC_UL_TBF, ul_slots, compute_usage_by_num_tbfs, NULL, &free_usf); if (free_usf < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No USF available\n"); return -EBUSY; } + OSMO_ASSERT(ts >= 0 && ts <= 8); + /* We will stick to that single UL slot, unreserve the others */ ul_slots = 1 << ts; usf[ts] = free_usf; - - LOGP(DRLCMAC, LOGL_DEBUG, - "- Selected UL slots: (TS=0)\"%s\"(TS=7)%s\n", - set_flag_chars(set_flag_chars(slot_info, - reserved_ul_slots, 'u', '.'), - ul_slots, 'U'), - single ? ", single" : ""); - - slotcount++; - first_ts = ts; - - /* We will stick to that single UL slot, unreserve the others */ reserved_ul_slots = ul_slots; - avail_count = pcu_bitcount(reserved_ul_slots); + update_slot_counters(ul_slots, reserved_ul_slots, &slotcount, &avail_count); } first_common_ts = ffs(dl_slots & ul_slots) - 1; diff --git a/src/mslot_class.c b/src/mslot_class.c index 87e37ca1..6a7e25b7 100644 --- a/src/mslot_class.c +++ b/src/mslot_class.c @@ -228,3 +228,11 @@ int8_t find_free_usf(uint8_t usf_map) return -1; } + +void masked_override_with(char *buf, uint8_t mask, char set_char) +{ + int i; + for (i = 0; mask; i++, mask >>= 1) + if (mask & 1) + buf[i] = set_char; +} diff --git a/src/mslot_class.h b/src/mslot_class.h index d2485262..c274337a 100644 --- a/src/mslot_class.h +++ b/src/mslot_class.h @@ -49,5 +49,7 @@ uint8_t mslot_class_get_sum(uint8_t ms_cl); uint8_t mslot_class_get_type(uint8_t ms_cl); uint8_t mslot_class_max(); +/* multislot allocation helper routines */ void mslot_fill_rx_mask(uint8_t mslot_class, uint8_t num_tx, uint8_t *rx_mask); int8_t find_free_usf(uint8_t usf_map); +void masked_override_with(char *buf, uint8_t mask, char set_char); -- cgit v1.2.3