aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/core/time_cc_rate_ctr.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/osmocom/core/time_cc_rate_ctr.h')
-rw-r--r--include/osmocom/core/time_cc_rate_ctr.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/include/osmocom/core/time_cc_rate_ctr.h b/include/osmocom/core/time_cc_rate_ctr.h
new file mode 100644
index 00000000..746ecf0c
--- /dev/null
+++ b/include/osmocom/core/time_cc_rate_ctr.h
@@ -0,0 +1,161 @@
+/* Report the cumulative counter of time for which a flag is true as rate counter. */
+#pragma once
+
+/*! Configuration for an osmo_time_cc_rate_ctr.
+ * Report the cumulative counter of time for which a flag is true as rate counter.
+ * For example, for each second that the flag is true, increment a rate counter.
+ *
+ * The flag to be monitored is reported by osmo_time_cc_rate_ctr_set_flag().
+ *
+ * The granularity defines how much time one rate counter increment represents:
+ * the "normal" configuration is gran_usec = 1000000, i.e. one rate counter increment represents one second.
+ *
+ * Reporting as rate counter is configurable by using either rate_ctr_early or rate_ctr_full,
+ * and by setting a nonzero reset_sum_usec value.
+ *
+ * Examples:
+ * - To see an increment for each gran_usec period where the flag was seen true, set reset_sum_usec = gran_usec and
+ * point rate_ctr_early at your rate_ctr instance.
+ * - To see an increment only for those gran_usec periods where the flag was true the entire time, set
+ * reset_sum_usec = gran_usec and point rate_ctr_full at your rate_ctr instance (leave rate_ctr_early = NULL).
+ * - To see an increment only when the cumulative time where the flag was true has surpassed another gran_usec step, no
+ * matter how long it takes to get there, set reset_sum_usec = 0 and use rate_ctr_full.
+ *
+ * Reporting modes in detail:
+ *
+ * - rate_ctr_early and rate_ctr_full report when the cumulative counter of time where the flag was true reaches a
+ * multiple of granularity period gran_usec, "early" at the start of a true flag, "full" only upon the sum reaching a full
+ * multiple of gran_usec.
+ *
+ * sum ^
+ * | ________
+ * | /
+ * | /
+ * | /
+ * 3*gran --+--------------------------------------+
+ * | /:
+ * | / :
+ * | / :
+ * | / :
+ * | / :
+ * 2*gran --+--------------------------------+ :
+ * | /: :
+ * | / : :
+ * | _________/ : :
+ * | / : :
+ * | / : :
+ * 1*gran --+-----------------+ : :
+ * | /: : :
+ * | / : : :
+ * | / : : :
+ * | / : : :
+ * | ....-------' : : :
+ * 0 +---------+---------+---------+---------+---------+----------------------> elapsed time
+ * 1*gran : 2*gran : :
+ * _ _ _______ ___________
+ * flag: __| |_| |____| : |________| : : |__________
+ * f t f t f t : f t : : f
+ * : : : :
+ * rate_ctr_early: 0 1 2 3 4 = inc when the sum starts the next granularity
+ * rate_ctr_full: 0 1 2 3 = inc when the sum becomes a full granularity
+ *
+ *
+ * - The sum can be reset periodically by setting a nonzero reset_sum_usec value:
+ * For example, with reset_sum_usec = 2 * gran_usec:
+ *
+ * sum ^
+ * |
+ * 2*gran --+
+ * | /|
+ * | / |
+ * | / |
+ * | /| / |
+ * | / | / |
+ * 1*gran --+-----------------+--|-------------+ |
+ * | /: | /: |
+ * | / : | / : |
+ * | / : | / : | ___
+ * | / : | / : | /
+ * | ....-------' : |________/ : |/
+ * 0 +---------+----------+---------+---------+-----> elapsed time
+ * 1*gran : 2*gran : 4*gran
+ * _ _ ______ ____________
+ * flag: __| |_| |____| : |_________| : : |__________
+ * f t f t f t : f t : : f
+ * : : : : :
+ * rate_ctr_early: 0 1 2 3 4 5
+ * rate_ctr_full: 0 1 2
+ *
+ * Like this,
+ * - rate_ctr_early increments once for each reset_sum_usec period in which the flag is seen true at any time,
+ * i.e. reports true flags quite sensitively, while guaranteeing a maximum of one increment per gran_usec.
+ * - rate_ctr_full increments only when there is a full gran_usec of "true" seen within one reset_sum_usec period,
+ * i.e. only reports counts for long durations of the flag being true, ignoring insignificantly short true flags.
+ */
+struct osmo_time_cc_rate_ctr_cfg {
+ /*! Granularity in microseconds: nr of microseconds that one rate_ctr increment represents. A typical value is
+ * gran_usec = 1000000, meaning one rate counter increment represents one second. */
+ uint64_t gran_usec;
+ /*! Nr of Microseconds over which to accumulate for reporting, or zero to accumulate indefinitely.
+ * When this value is nonzero, it should be >= gran_usec. */
+ uint64_t reset_sum_usec;
+ /*! Rate counter that reports every true flag seen, at most one per gran_usec period, or NULL to not use it. */
+ struct rate_ctr *rate_ctr_early;
+ /*! Rate counter that reports a count only for every full gran_usec duration of true flag, or NULL. */
+ struct rate_ctr *rate_ctr_full;
+
+ /*! Update gran_usec from this T-timer value, or zero to not use any T timer. */
+ int T_gran_usec;
+ /*! Update reset_sum_usec from this T-timer value, or zero to not use any T timer. */
+ int T_reset_sum_usec;
+ /*! Look up T_gran_usec and T_reset_sum_usec in this list of timers, or NULL to not use any T timers. */
+ struct osmo_tdef *Tdefs;
+};
+
+/*! Report the cumulative counter of time for which a flag is true as rate counter.
+ * See also osmo_time_cc_rate_ctr_cfg for details on configuring an osmo_time_cc_rate_ctr.
+ *
+ * Usage:
+ *
+ * struct my_obj {
+ * struct osmo_time_cc_rate_ctr flag_cc;
+ * };
+ *
+ * void my_obj_init(struct my_obj *my_obj)
+ * {
+ * my_obj->flag_cc.cfg = (struct osmo_time_cc_rate_ctr_cfg){
+ * .gran_usec = 1000000,
+ * .reset_sum_usec = 1000000,
+ * .rate_ctr_early = rate_ctr_group_get_ctr(my_ctrg, MY_CTR_IDX),
+ * };
+ * osmo_time_cc_rate_ctr_set_flag(&my_obj->flag_cc, false);
+ * }
+ *
+ * void my_obj_event(struct my_obj *my_obj, bool flag)
+ * {
+ * osmo_time_cc_rate_ctr_set_flag(&my_obj->flag_cc, flag);
+ * }
+ *
+ * void my_obj_destruct(struct my_obj *my_obj)
+ * {
+ * osmo_time_cc_rate_ctr_cleanup(&my_obj->flag_cc);
+ * }
+ */
+struct osmo_time_cc_rate_ctr {
+ struct osmo_time_cc_rate_ctr_cfg cfg;
+
+ struct osmo_timer_list timer;
+
+ bool flag_state;
+ uint64_t start_time;
+ uint64_t last_counted_time;
+ uint64_t last_reset_time;
+
+ uint64_t total_sum;
+ uint64_t sum;
+ uint64_t reported_sum_early;
+ uint64_t reported_sum_full;
+};
+
+void osmo_time_cc_rate_ctr_set_flag(struct osmo_time_cc_rate_ctr *tcr, bool flag);
+void osmo_time_cc_rate_ctr_cleanup(struct osmo_time_cc_rate_ctr *tcr);