core: osmo_tdef_fsm_inst_state_chg(): allow millisecond precision

This API predates commit 7b74551b9, which added support for millisecond
granularity to osmo_fsm.  Let's do the same for the tdef FSM wrapper
API, allowing the millisecond precision without rounding-up to seconds.

Of course, this patch changes behavior of the existing API, but having
more precise state timeouts is not going to make the API user
experience worse.

The old behavior of using seconds is for kept for:

* OSMO_TDEF_CUSTOM -- still treated as if it was OSMO_TDEF_S.
* \param[in] default_timeout -- still expected to be in seconds.

Change-Id: I4c4ee89e7e32e86f74cd215f5cbfa44ace5426c1
Related: 7b74551b9 "fsm: Allow millisecond granularity in osmo_fsm built-in timer"
diff --git a/src/core/tdef.c b/src/core/tdef.c
index abbe581..f0c0f2e 100644
--- a/src/core/tdef.c
+++ b/src/core/tdef.c
@@ -337,26 +337,37 @@
 				  const char *file, int line)
 {
 	const struct osmo_tdef_state_timeout *t = osmo_tdef_get_state_timeout(state, timeouts_array);
-	unsigned long val = 0;
+	unsigned long val_ms = 0;
 
 	/* No timeout defined for this state? */
 	if (!t)
 		return _osmo_fsm_inst_state_chg(fi, state, 0, 0, file, line);
 
-	if (t->T)
-		val = osmo_tdef_get(tdefs, t->T, OSMO_TDEF_S, default_timeout);
+	if (t->T) {
+		const struct osmo_tdef *tdef = osmo_tdef_get_entry((struct osmo_tdef *)tdefs, t->T);
+		if (tdef == NULL) {
+			/* emulate the old behavior: treat default_timeout as OSMO_TDEF_S */
+			OSMO_ASSERT(default_timeout >= 0);
+			val_ms = default_timeout * 1000;
+		} else {
+			val_ms = osmo_tdef_round(tdef->val, tdef->unit, OSMO_TDEF_MS);
+			/* emulate the old behavior: treat OSMO_TDEF_CUSTOM as OSMO_TDEF_S */
+			if (tdef->unit == OSMO_TDEF_CUSTOM)
+				val_ms *= 1000;
+		}
+	}
 
 	if (t->keep_timer) {
 		if (t->T)
-			return _osmo_fsm_inst_state_chg_keep_or_start_timer(fi, state, val, t->T, file, line);
+			return _osmo_fsm_inst_state_chg_keep_or_start_timer_ms(fi, state, val_ms, t->T, file, line);
 		else
 			return _osmo_fsm_inst_state_chg_keep_timer(fi, state, file, line);
 	}
 
-	/* val is always initialized here, because if t->keep_timer is false, t->T must be != 0.
+	/* val_ms is always initialized here, because if t->keep_timer is false, t->T must be != 0.
 	 * Otherwise osmo_tdef_get_state_timeout() would have returned NULL. */
 	OSMO_ASSERT(t->T);
-	return _osmo_fsm_inst_state_chg(fi, state, val, t->T, file, line);
+	return _osmo_fsm_inst_state_chg_ms(fi, state, val_ms, t->T, file, line);
 }
 
 const struct value_string osmo_tdef_unit_names[] = {