ms: Hold a reference during ms_alloc

Make the caller hold a reference to the MS object just allocated, so
that it hs to explicitly unref it and, in turn, if no new references
were added during its use, trigger release of the MS object.
This is useful to avoid leaking MS object if it was allocated and then
no TBF is attached to it because allocation of TBF failed.

Related: OS#6002
Change-Id: I2088a7ddd76fe9157b6626ef96ae4315e88779ea
diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp
index bc68c3d..7b7d59a 100644
--- a/tests/ms/MsTest.cpp
+++ b/tests/ms/MsTest.cpp
@@ -85,7 +85,7 @@
 
 	printf("=== start %s ===\n", __func__);
 
-	ms = ms_alloc(bts);
+	ms = ms_alloc(bts, __func__);
 	ms_set_tlli(ms, tlli);
 	OSMO_ASSERT(ms_is_idle(ms));
 
@@ -105,6 +105,9 @@
 	OSMO_ASSERT(ms_tbf(ms, GPRS_RLCMAC_UL_TBF) == ul_tbf);
 	OSMO_ASSERT(ms_tbf(ms, GPRS_RLCMAC_DL_TBF) == dl_tbf);
 
+	/* The MS is kept alive references by the TBFs: */
+	ms_unref(ms, __func__);
+
 	ms_detach_tbf(ms, ul_tbf);
 	OSMO_ASSERT(!ms_is_idle(ms));
 	OSMO_ASSERT(ms_ul_tbf(ms) == NULL);
@@ -130,7 +133,7 @@
 
 	printf("=== start %s ===\n", __func__);
 
-	ms = ms_alloc(bts);
+	ms = ms_alloc(bts, __func__);
 	ms_confirm_tlli(ms, tlli);
 
 	OSMO_ASSERT(ms_is_idle(ms));
@@ -157,6 +160,8 @@
 	OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf[1]);
 	OSMO_ASSERT(!llist_empty(&ms->old_tbfs));
 
+	ms_unref(ms, __func__);
+
 	ms_detach_tbf(ms, ul_tbf);
 	OSMO_ASSERT(!ms_is_idle(ms));
 	OSMO_ASSERT(ms_ul_tbf(ms) == NULL);
@@ -190,7 +195,7 @@
 
 	printf("=== start %s ===\n", __func__);
 
-	ms = ms_alloc(bts);
+	ms = ms_alloc(bts, __func__);
 
 	OSMO_ASSERT(ms_is_idle(ms));
 
@@ -267,7 +272,9 @@
 	OSMO_ASSERT(ms_check_tlli(ms, new_ms_tlli));
 	OSMO_ASSERT(!ms_check_tlli(ms, start_tlli));
 
-	talloc_free(ms);
+	/* This frees the MS: */
+	ms_unref(ms, __func__);
+
 	talloc_free(bts);
 	printf("=== end %s ===\n", __func__);
 }
@@ -278,7 +285,7 @@
 	if (ms)
 		return ms;
 
-	ms = ms_alloc(bts);
+	ms = ms_alloc(bts, NULL);
 
 	if (dir == GPRS_RLCMAC_UL_TBF)
 		ms_set_tlli(ms, tlli);
@@ -371,7 +378,7 @@
 
 	printf("=== start %s ===\n", __func__);
 
-	ms = ms_alloc(bts);
+	ms = ms_alloc(bts, __func__);
 	ms_set_tlli(ms, tlli);
 	ms_set_timeout(ms, 1);
 
@@ -386,6 +393,9 @@
 	ms_attach_tbf(ms, dl_tbf);
 	OSMO_ASSERT(!ms_is_idle(ms));
 
+	/* MS is kept alive by TBFs referencing it: */
+	ms_unref(ms, __func__);
+
 	ms_detach_tbf(ms, ul_tbf);
 	OSMO_ASSERT(!ms_is_idle(ms));
 
@@ -422,7 +432,7 @@
 	the_pcu->vty.cs_downgrade_threshold = 0;
 	the_pcu->vty.cs_adj_lower_limit = 0;
 
-	ms = ms_alloc(bts);
+	ms = ms_alloc(bts, __func__);
 	ms_confirm_tlli(ms, tlli);
 
 	OSMO_ASSERT(ms_is_idle(ms));
@@ -430,6 +440,8 @@
 	dl_tbf = alloc_dl_tbf(bts, ms);
 	ms_attach_tbf(ms, dl_tbf);
 
+	ms_unref(ms, __func__);
+
 	OSMO_ASSERT(!ms_is_idle(ms));
 
 	OSMO_ASSERT(mcs_chan_code(ms_current_cs_dl(ms, ms_mode(ms))) == 3);
@@ -463,7 +475,7 @@
 
 	printf("=== start %s ===\n", __func__);
 
-	ms1 = ms_alloc(bts);
+	ms1 = ms_alloc(bts, __func__);
 	ms_confirm_tlli(ms1, tlli);
 	dump_ms(ms1, "1: no BTS defaults  ");
 
@@ -471,7 +483,7 @@
 	bts->initial_cs_ul = 1;
 	the_pcu->vty.cs_downgrade_threshold = 0;
 
-	ms2 = ms_alloc(bts);
+	ms2 = ms_alloc(bts,__func__);
 	ms_confirm_tlli(ms2, tlli + 1);
 	dump_ms(ms2, "2: with BTS defaults");
 
diff --git a/tests/ms/MsTest.err b/tests/ms/MsTest.err
index 0cc351b..84a948e 100644
--- a/tests/ms/MsTest.err
+++ b/tests/ms/MsTest.err
@@ -1,16 +1,16 @@
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_state: now used by 1 (test_ms_state)
 Modifying MS object, UL TLLI: 0xffffffff -> 0xffeeddbb, not yet confirmed
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Attaching UL TBF: TBF(UL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
-MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL): + tbf: now used by 1 (tbf)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL) Attaching DL TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL:DL) Detaching TBF: TBF(UL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL) Detaching TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0): - tbf: now used by 0 (-)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Destroying MS object
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_replace_tbf: now used by 1 (test_ms_replace_tbf)
 The MS object cannot fully confirm an unexpected TLLI: 0xffeeddbb, partly confirmed
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Attaching DL TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
-MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL): + tbf: now used by 1 (tbf)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL) Attaching DL TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL) Attaching UL TBF: TBF(UL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL:DL) Detaching TBF: TBF(UL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
@@ -19,6 +19,7 @@
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0): - tbf: now used by 0 (-)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Destroying MS object
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_change_tlli: now used by 1 (test_ms_change_tlli)
 Modifying MS object, UL TLLI: 0xffffffff -> 0xff001111, not yet confirmed
 Modifying MS object, TLLI: 0xff001111 confirmed
 Modifying MS object, UL TLLI: 0xff001111 -> 0xaa000000, not yet confirmed
@@ -34,6 +35,7 @@
 Modifying MS object, TLLI: 0xaa000000 confirmed
 The MS object cannot fully confirm an unexpected TLLI: 0xff001111, partly confirmed
 Modifying MS object, TLLI: 0xaa000000 -> 0xff001111, already confirmed partly
+MS(TLLI-0xff001111:TA-220:MSCLS-0-0): - test_ms_change_tlli: now used by 0 (-)
 MS(TLLI-0xff001111:TA-220:MSCLS-0-0) Destroying MS object
 Creating MS object
 Modifying MS object, UL TLLI: 0xffffffff -> 0xffeeddbb, not yet confirmed
@@ -52,9 +54,9 @@
 MS(IMSI-001001987654322:TLLI-0xffeeddbc:TA-220:MSCLS-0-0): - tbf: now used by 0 (-)
 MS(IMSI-001001987654322:TLLI-0xffeeddbc:TA-220:MSCLS-0-0) Destroying MS object
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_timeout: now used by 1 (test_ms_timeout)
 Modifying MS object, UL TLLI: 0xffffffff -> 0xffeeddbb, not yet confirmed
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Attaching UL TBF: TBF(UL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
-MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL): + tbf: now used by 1 (tbf)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL) Attaching DL TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:UL:DL) Detaching TBF: TBF(UL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL) Detaching TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
@@ -62,19 +64,19 @@
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Release timer expired
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Destroying MS object
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_cs_selection: now used by 1 (test_ms_cs_selection)
 The MS object cannot fully confirm an unexpected TLLI: 0xffeeddbb, partly confirmed
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0) Attaching DL TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
-MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL): + tbf: now used by 1 (tbf)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL) Destroying MS object
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0:DL) Detaching TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xffeeddbb)
 MS(TLLI-0xffeeddbb:TA-220:MSCLS-0-0): - tbf: now used by 0 (-)
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_mcs_mode: now used by 1 (test_ms_mcs_mode)
 The MS object cannot fully confirm an unexpected TLLI: 0xdeadbeef, partly confirmed
 Creating MS object
+MS(TA-220:MSCLS-0-0): + test_ms_mcs_mode: now used by 1 (test_ms_mcs_mode)
 The MS object cannot fully confirm an unexpected TLLI: 0xdeadbef0, partly confirmed
 MS(TLLI-0xdeadbef0:TA-220:MSCLS-0-0) Attaching DL TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xdeadbef0)
-MS(TLLI-0xdeadbef0:TA-220:MSCLS-0-0:DL): + tbf: now used by 1 (tbf)
 MS(TLLI-0xdeadbeef:TA-220:MSCLS-0-0) Destroying MS object
 MS(TLLI-0xdeadbef0:TA-220:MSCLS-0-0:DL) Destroying MS object
 MS(TLLI-0xdeadbef0:TA-220:MSCLS-0-0:DL) Detaching TBF: TBF(DL:STATE-NEW:GPRS:TLLI-0xdeadbef0)
-MS(TLLI-0xdeadbef0:TA-220:MSCLS-0-0): - tbf: now used by 0 (-)