ms: Use osmo_use_count to track references
Change-Id: Ib65629224e6bd5683bb9192ba4354e965e8d39ec
diff --git a/src/gprs_ms.c b/src/gprs_ms.c
index b9a1b76..f65ffb8 100644
--- a/src/gprs_ms.c
+++ b/src/gprs_ms.c
@@ -61,6 +61,40 @@
return (int64_t)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}
+static void ms_update_status(struct GprsMs *ms);
+
+static int ms_use_cb(struct osmo_use_count_entry *e, int32_t old_use_count, const char *file, int line)
+{
+ struct GprsMs *ms = e->use_count->talloc_object;
+ int32_t total;
+ int level;
+ char buf[1024];
+
+ if (!e->use)
+ return -EINVAL;
+
+ total = osmo_use_count_total(&ms->use_count);
+
+ if (total == 0
+ || (total == 1 && old_use_count == 0 && e->count == 1))
+ level = LOGL_INFO;
+ else
+ level = LOGL_DEBUG;
+
+
+ LOGPSRC(DRLCMAC, level, file, line, "%s: %s %s: now used by %s\n",
+ ms_name(ms),
+ (e->count - old_use_count) > 0 ? "+" : "-", e->use,
+ (osmo_use_count_to_str_buf(buf, sizeof(buf), &ms->use_count), buf));
+
+ if (e->count < 0)
+ return -ERANGE;
+
+ if (total == 0)
+ ms_update_status(ms);
+ return 0;
+}
+
void gprs_default_cb_ms_idle(struct GprsMs *ms)
{
if (ms_is_idle(ms))
@@ -84,7 +118,7 @@
if (ms->timer.data) {
ms->timer.data = NULL;
- ms_unref(ms);
+ ms_unref(ms, MS_USE_RELEASE_TIMER);
}
}
@@ -125,6 +159,11 @@
ms->is_idle = true;
INIT_LLIST_HEAD(&ms->old_tbfs);
+ ms->use_count = (struct osmo_use_count){
+ .talloc_object = ms,
+ .use_cb = ms_use_cb,
+ };
+
int codel_interval = LLC_CODEL_USE_DEFAULT;
LOGP(DRLCMAC, LOGL_INFO, "Creating MS object\n");
@@ -204,7 +243,7 @@
static void ms_update_status(struct GprsMs *ms)
{
- if (ms->ref > 0)
+ if (osmo_use_count_total(&ms->use_count) > 0)
return;
if (ms_is_idle(ms) && !ms->is_idle) {
@@ -220,20 +259,6 @@
}
}
-struct GprsMs *ms_ref(struct GprsMs *ms)
-{
- ms->ref += 1;
- return ms;
-}
-
-void ms_unref(struct GprsMs *ms)
-{
- OSMO_ASSERT(ms->ref >= 0);
- ms->ref -= 1;
- if (ms->ref == 0)
- ms_update_status(ms);
-}
-
static void ms_release_timer_start(struct GprsMs *ms)
{
/* Immediate free():
@@ -252,8 +277,10 @@
LOGPMS(ms, DRLCMAC, LOGL_DEBUG, "Schedule MS release in %u secs\n", ms->delay);
- if (!ms->timer.data)
- ms->timer.data = ms_ref(ms);
+ if (!ms->timer.data) {
+ ms_ref(ms, MS_USE_RELEASE_TIMER);
+ ms->timer.data = ms;
+ }
osmo_timer_schedule(&ms->timer, ms->delay, 0);
}
@@ -267,7 +294,7 @@
osmo_timer_del(&ms->timer);
ms->timer.data = NULL;
- ms_unref(ms);
+ ms_unref(ms, MS_USE_RELEASE_TIMER);
}
void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode)
@@ -328,7 +355,7 @@
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Attaching UL TBF: %s\n", tbf_name((struct gprs_rlcmac_tbf *)tbf));
- ms_ref(ms);
+ ms_ref(ms, __func__);
if (ms->ul_tbf)
llist_add_tail(tbf_ms_list(ul_tbf_as_tbf(ms->ul_tbf)), &ms->old_tbfs);
@@ -338,7 +365,7 @@
if (tbf)
ms_release_timer_stop(ms);
- ms_unref(ms);
+ ms_unref(ms, __func__);
}
static void ms_attach_dl_tbf(struct GprsMs *ms, struct gprs_rlcmac_dl_tbf *tbf)
@@ -348,7 +375,7 @@
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Attaching DL TBF: %s\n", tbf_name((struct gprs_rlcmac_tbf *)tbf));
- ms_ref(ms);
+ ms_ref(ms, __func__);
if (ms->dl_tbf)
llist_add_tail(tbf_ms_list(dl_tbf_as_tbf(ms->dl_tbf)), &ms->old_tbfs);
@@ -358,7 +385,7 @@
if (tbf)
ms_release_timer_stop(ms);
- ms_unref(ms);
+ ms_unref(ms, __func__);
}
void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf)
@@ -452,7 +479,7 @@
{
char old_ms_name[128];
OSMO_ASSERT(old_ms != ms);
- ms_ref(old_ms);
+ ms_ref(old_ms, __func__);
ms_name_buf(old_ms, old_ms_name, sizeof(old_ms_name));
@@ -478,7 +505,7 @@
ms_reset(old_ms);
- ms_unref(old_ms);
+ ms_unref(old_ms, __func__);
}
/* Apply changes to the TLLI directly, used interally by functions below: */
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index d976235..123db0e 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -31,6 +31,7 @@
#include <osmocom/core/timer.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/rate_ctr.h>
+#include <osmocom/core/use_count.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm48.h>
@@ -84,7 +85,7 @@
struct osmo_timer_list llc_timer;
bool is_idle;
- int ref;
+ struct osmo_use_count use_count;
struct osmo_timer_list timer;
unsigned delay;
@@ -107,8 +108,6 @@
void ms_set_first_common_ts(struct GprsMs *ms, struct gprs_rlcmac_pdch *pdch);
void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx,
uint8_t ul_slots, uint8_t dl_slots);
-struct GprsMs *ms_ref(struct GprsMs *ms);
-void ms_unref(struct GprsMs *ms);
void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode);
void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_);
void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_);
@@ -157,7 +156,9 @@
static inline bool ms_is_idle(const struct GprsMs *ms)
{
- return !ms->ul_tbf && !ms->dl_tbf && !ms->ref && llist_empty(&ms->old_tbfs);
+ return !ms->ul_tbf && !ms->dl_tbf &&
+ llist_empty(&ms->old_tbfs) &&
+ osmo_use_count_total(&ms->use_count) == 0;
}
static inline struct gprs_llc_queue *ms_llc_queue(struct GprsMs *ms)
@@ -250,6 +251,12 @@
return ms->current_trx;
}
+#define MS_USE_RELEASE_TIMER "release_timer"
+#define ms_ref(ms, use) \
+ OSMO_ASSERT(osmo_use_count_get_put(&(ms)->use_count, use, 1) == 0)
+#define ms_unref(ms, use) \
+ OSMO_ASSERT(osmo_use_count_get_put(&(ms)->use_count, use, -1) == 0)
+
#define LOGPMS(ms, category, level, fmt, args...) \
LOGP(category, level, "%s " fmt, ms_name(ms), ## args)
diff --git a/src/pdch.cpp b/src/pdch.cpp
index 1c39ceb..4495e21 100644
--- a/src/pdch.cpp
+++ b/src/pdch.cpp
@@ -697,7 +697,7 @@
* temporarily, in order to avoid it being freed if we free any of its
* resources (TBF). */
OSMO_ASSERT(ms);
- ms_ref(ms);
+ ms_ref(ms, __func__);
switch (item->type) {
@@ -843,7 +843,7 @@
/* schedule uplink assignment */
osmo_fsm_inst_dispatch(new_ul_tbf->ul_ass_fsm.fi, TBF_UL_ASS_EV_SCHED_ASS, NULL);
return_unref:
- ms_unref(ms);
+ ms_unref(ms, __func__);
return;
}
diff --git a/src/tbf_ul_fsm.c b/src/tbf_ul_fsm.c
index a7d24ec..8778e32 100644
--- a/src/tbf_ul_fsm.c
+++ b/src/tbf_ul_fsm.c
@@ -227,7 +227,7 @@
/* Ref the MS, otherwise it may be freed after ul_tbf is
* detached when sending event below. */
ms = tbf_ms(ctx->tbf);
- ms_ref(ms);
+ ms_ref(ms, __func__);
/* UL TBF ACKed our transmitted UL ACK/NACK with final Ack
* Indicator set to '1'. We can free the TBF right away, the MS
* also just released its TBF on its side. */
@@ -242,7 +242,7 @@
* now. */
if (!new_ul_tbf_requested && ms_need_dl_tbf(ms))
ms_new_dl_tbf_assigned_on_pch(ms);
- ms_unref(ms);
+ ms_unref(ms, __func__);
break;
case TBF_EV_MAX_N3103:
ctx->T_release = 3169;