mirror of https://gerrit.osmocom.org/libosmocore
add osmo_time_cc, moved from osmo-bsc
Related: SYS#4878 Related: Ica9f908a1a30f334a24c59471affa11225117e12 (osmo-bsc) Change-Id: Iabb17a08e6e1a86f168cdb008fba05ecd4776bdd
This commit is contained in:
parent
5eb67c2d66
commit
25c9741445
|
@ -60,6 +60,7 @@ nobase_include_HEADERS = \
|
|||
osmocom/core/utils.h \
|
||||
osmocom/core/write_queue.h \
|
||||
osmocom/core/sockaddr_str.h \
|
||||
osmocom/core/time_cc.h \
|
||||
osmocom/core/use_count.h \
|
||||
osmocom/crypt/auth.h \
|
||||
osmocom/crypt/gprs_cipher.h \
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/*! \file time_cc.h
|
||||
* Report the cumulative counter of time for which a flag is true as rate counter.
|
||||
*/
|
||||
/* Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
|
||||
/*! \defgroup time_cc Cumulative counter of time as rate counter.
|
||||
* @{
|
||||
* \file time_cc.h
|
||||
*/
|
||||
|
||||
struct osmo_tdef;
|
||||
struct rate_ctr;
|
||||
|
||||
/*! Configuration for osmo_time_cc.
|
||||
* 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_set_flag().
|
||||
*
|
||||
* The granularity defines how much time one rate counter increment represents:
|
||||
* the default configuration is gran_usec = 1000000, i.e. one rate counter increment represents one second.
|
||||
*
|
||||
* Reporting as rate counter is configurable by round_threshold_usec and forget_sum_usec, examples:
|
||||
*
|
||||
* round_threshold_usec:
|
||||
* - To get "ceil()" behavior, set round_threshold_usec = 1. This increments the rate counter for each gran_usec period
|
||||
* where the flag was seen true, even if it was true for only a very short fraction of a gran_usec period.
|
||||
* - To get "round()" behavior, set round_threshold_usec = half of gran_usec. The rate counter increments when the flag
|
||||
* has been true for 0.5 of a gran_usec (and then again at 1.5 * gran_usec) of 'true' flag. round_threshold_usec = 0
|
||||
* is a special value that means to use half of gran_usec.
|
||||
* - To get "floor()" behavior, set round_threshold_usec >= gran_usec. The rate counter increments when reaching full
|
||||
* gran_usec periods of the flag being true.
|
||||
*
|
||||
* forget_sum_usec:
|
||||
* This is a tradeoff between the accuracy of the reported rate counter and making sure that the events reported are not
|
||||
* irrelevantly long ago.
|
||||
* - To keep sub-granularity-period surplus time forever, set forget_sum_usec = 0.
|
||||
* - To keep surplus time for up to a minute, set forget_sum_usec = 60000000 (60 seconds).
|
||||
* - To get rid of "leftover" time (almost) immediately after the flag goes false, set forget_sum_usec = 1.
|
||||
* - If gran_usec is set to one second and forget_sum_usec is set to one minute, the reported rate counter has a
|
||||
* possible inaccuracy of 1/60th, but makes sure that no timings older than a minute affect the current reports.
|
||||
*
|
||||
* Reporting modes in detail:
|
||||
*
|
||||
* The rate_ctr increments when the cumulative counter passes round_threshold_usec (default: half of gran_usec).
|
||||
*
|
||||
* sum ^
|
||||
* | ________
|
||||
* | /
|
||||
* | /
|
||||
* | /
|
||||
* 3*gran --+--------------------------------------+
|
||||
* | /:
|
||||
* | / :
|
||||
* | - - - - - - - - - - - - - - - - - / :
|
||||
* | /. :
|
||||
* | / . :
|
||||
* 2*gran --+--------------------------------+ . :
|
||||
* | /: . :
|
||||
* | / : . :
|
||||
* | - - - - - - - - - -_________/ : . :
|
||||
* | / . : . :
|
||||
* | / . : . :
|
||||
* 1*gran --+-----------------+ . : . :
|
||||
* | /: . : . :
|
||||
* | / : . : . :
|
||||
* | - - - - - - -/ : . : . :
|
||||
* | /. : . : . :
|
||||
* | ....-------' . : . : . :
|
||||
* 0 +------------------------------------------------------------------------> elapsed time
|
||||
* . : . : . :
|
||||
* _ _ _______ ____________
|
||||
* flag: __| |_| |____| . : |_______|. : . : |__________
|
||||
* f t f t f t . : f t. : . : f
|
||||
* round_threshold_usec : . : . : . :
|
||||
* = 1 usec: 0 1 . :2 . :3 . :4 = "ceil()"
|
||||
* = 0 == gran_usec/2: 0 1 : 2 : 3 : = "round()"
|
||||
* >= gran_usec: 0 1 2 3 = "floor()"
|
||||
*
|
||||
*/
|
||||
struct osmo_time_cc_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. When zero, use 1000000. */
|
||||
uint64_t gran_usec;
|
||||
/*! Nr of microseconds above n * gran_usec at which to trigger a counter increment. When zero, use half a
|
||||
* gran_usec. */
|
||||
uint64_t round_threshold_usec;
|
||||
/*! Forget counted sub-gran time after the flag was false for this long. */
|
||||
uint64_t forget_sum_usec;
|
||||
/*! Rate counter to report to, or NULL to not use it. */
|
||||
struct rate_ctr *rate_ctr;
|
||||
|
||||
/*! Update gran_usec from this T timer value, or zero to not use any T timer. */
|
||||
int T_gran;
|
||||
/*! Update round_threshold_usec from this T timer value, or zero to not use any T timer. */
|
||||
int T_round_threshold;
|
||||
/*! Update forget_sum_usec from this T timer value, or zero to not use any T timer. */
|
||||
int T_forget_sum;
|
||||
/*! Look up T_gran and T_forget_sum in this list of timers, or NULL to not use any T timers. */
|
||||
struct osmo_tdef *T_defs;
|
||||
};
|
||||
|
||||
/*! Report the cumulative counter of time for which a flag is true as rate counter.
|
||||
* See also osmo_time_cc_cfg for details on configuring.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* struct my_obj {
|
||||
* struct osmo_time_cc flag_cc;
|
||||
* };
|
||||
*
|
||||
* void my_obj_init(struct my_obj *my_obj)
|
||||
* {
|
||||
* osmo_time_cc_init(&my_obj->flag_cc);
|
||||
* my_obj->flag_cc.cfg = (struct osmo_time_cc_cfg){
|
||||
* .gran_usec = 1000000,
|
||||
* .forget_sum_usec = 60000000,
|
||||
* .rate_ctr = rate_ctr_group_get_ctr(my_ctrg, MY_CTR_IDX),
|
||||
* };
|
||||
* // optional: set initial flag state, default is 'false':
|
||||
* // osmo_time_cc_set_flag(&my_obj->flag_cc, false);
|
||||
* }
|
||||
*
|
||||
* void my_obj_event(struct my_obj *my_obj, bool flag)
|
||||
* {
|
||||
* osmo_time_cc_set_flag(&my_obj->flag_cc, flag);
|
||||
* }
|
||||
*
|
||||
* void my_obj_destruct(struct my_obj *my_obj)
|
||||
* {
|
||||
* osmo_time_cc_cleanup(&my_obj->flag_cc);
|
||||
* }
|
||||
*/
|
||||
struct osmo_time_cc {
|
||||
struct osmo_time_cc_cfg cfg;
|
||||
|
||||
bool flag_state;
|
||||
|
||||
/*! Overall cumulative sum. Does not get reset for the entire lifetime of an osmo_time_cc.
|
||||
* (Informational only, not used by the osmo_time_cc implementation.) */
|
||||
uint64_t total_sum;
|
||||
|
||||
struct osmo_timer_list timer;
|
||||
|
||||
/*! CLOCK_MONOTONIC reading in microseconds, at the time when the osmo_time_cc instance started counting. */
|
||||
uint64_t start_time;
|
||||
/*! CLOCK_MONOTONIC reading in microseconds, at the time when the osmo_time_cc last evaluated the flag state and
|
||||
* possibly added to the cumulated sum. */
|
||||
uint64_t last_counted_time;
|
||||
|
||||
/*! Internal cumulative counter of time that flag_state was true. It may get reset to zero regularly, depending
|
||||
* on cfg.forget_sum_usec. This is the basis for incrementing cfg.rate_ctr. */
|
||||
uint64_t sum;
|
||||
/*! The amount of time that already reported cfg.rate_ctr increments account for. This may be ahead of or behind
|
||||
* 'sum', depending on cfg.round_threshold_usec. */
|
||||
uint64_t reported_sum;
|
||||
};
|
||||
|
||||
void osmo_time_cc_init(struct osmo_time_cc *tc);
|
||||
void osmo_time_cc_set_flag(struct osmo_time_cc *tc, bool flag);
|
||||
void osmo_time_cc_cleanup(struct osmo_time_cc *tc);
|
||||
|
||||
/*! @} */
|
|
@ -26,6 +26,7 @@ libosmocore_la_SOURCES = context.c timer.c timer_gettimeofday.c timer_clockgetti
|
|||
isdnhdlc.c \
|
||||
tdef.c \
|
||||
thread.c \
|
||||
time_cc.c \
|
||||
sockaddr_str.c \
|
||||
use_count.c \
|
||||
exec.c \
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
/*! \file foo.c
|
||||
* Report the cumulative counter of time for which a flag is true as rate counter.
|
||||
*/
|
||||
/* Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \addtogroup time_cc
|
||||
*
|
||||
* Report the cumulative counter of time for which a flag is true as rate counter.
|
||||
*
|
||||
* Useful for reporting cumulative time counters as defined in 3GPP TS 52.402, for example allAvailableSDCCHAllocated,
|
||||
* allAvailableTCHAllocated, availablePDCHAllocatedTime.
|
||||
*
|
||||
* For a usage example, see the description of struct osmo_time_cc.
|
||||
*
|
||||
* @{
|
||||
* \file time_cc.c
|
||||
*/
|
||||
#include "config.h"
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <osmocom/core/tdef.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/time_cc.h>
|
||||
|
||||
#define GRAN_USEC(TIME_CC) ((TIME_CC)->cfg.gran_usec ? : 1000000)
|
||||
#define ROUND_THRESHOLD_USEC(TIME_CC) ((TIME_CC)->cfg.round_threshold_usec ? \
|
||||
OSMO_MIN((TIME_CC)->cfg.round_threshold_usec, GRAN_USEC(TIME_CC)) \
|
||||
: (GRAN_USEC(TIME_CC) / 2))
|
||||
|
||||
static uint64_t time_now_usec()
|
||||
{
|
||||
struct timespec tp;
|
||||
if (osmo_clock_gettime(CLOCK_MONOTONIC, &tp))
|
||||
return 0;
|
||||
return (uint64_t)tp.tv_sec * 1000000 + tp.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
static void osmo_time_cc_forget_sum(struct osmo_time_cc *tc, uint64_t now);
|
||||
|
||||
static void osmo_time_cc_update_from_tdef(struct osmo_time_cc *tc, uint64_t now)
|
||||
{
|
||||
bool do_forget_sum = false;
|
||||
if (!tc->cfg.T_defs)
|
||||
return;
|
||||
if (tc->cfg.T_gran) {
|
||||
uint64_t was = GRAN_USEC(tc);
|
||||
tc->cfg.gran_usec = osmo_tdef_get(tc->cfg.T_defs, tc->cfg.T_gran, OSMO_TDEF_US, -1);
|
||||
if (was != GRAN_USEC(tc))
|
||||
do_forget_sum = true;
|
||||
}
|
||||
if (tc->cfg.T_round_threshold)
|
||||
tc->cfg.round_threshold_usec = osmo_tdef_get(tc->cfg.T_defs, tc->cfg.T_round_threshold,
|
||||
OSMO_TDEF_US, -1);
|
||||
if (tc->cfg.T_forget_sum) {
|
||||
uint64_t was = tc->cfg.forget_sum_usec;
|
||||
tc->cfg.forget_sum_usec = osmo_tdef_get(tc->cfg.T_defs, tc->cfg.T_forget_sum, OSMO_TDEF_US, -1);
|
||||
if (tc->cfg.forget_sum_usec && was != tc->cfg.forget_sum_usec)
|
||||
do_forget_sum = true;
|
||||
}
|
||||
|
||||
if (do_forget_sum && tc->sum)
|
||||
osmo_time_cc_forget_sum(tc, now);
|
||||
}
|
||||
|
||||
static void osmo_time_cc_schedule_timer(struct osmo_time_cc *tc, uint64_t now);
|
||||
|
||||
/*! Clear out osmo_timer and internal counting state of struct osmo_time_cc. The .cfg remains unaffected. After calling,
|
||||
* the osmo_time_cc instance can be used again to accumulate state as if it had just been initialized. */
|
||||
void osmo_time_cc_cleanup(struct osmo_time_cc *tc)
|
||||
{
|
||||
osmo_timer_del(&tc->timer);
|
||||
*tc = (struct osmo_time_cc){
|
||||
.cfg = tc->cfg,
|
||||
};
|
||||
}
|
||||
|
||||
static void osmo_time_cc_start(struct osmo_time_cc *tc, uint64_t now)
|
||||
{
|
||||
osmo_time_cc_cleanup(tc);
|
||||
tc->start_time = now;
|
||||
tc->last_counted_time = now;
|
||||
osmo_time_cc_update_from_tdef(tc, now);
|
||||
osmo_time_cc_schedule_timer(tc, now);
|
||||
}
|
||||
|
||||
static void osmo_time_cc_count_time(struct osmo_time_cc *tc, uint64_t now)
|
||||
{
|
||||
uint64_t time_delta = now - tc->last_counted_time;
|
||||
tc->last_counted_time = now;
|
||||
if (!tc->flag_state)
|
||||
return;
|
||||
/* Flag is currently true, cumulate the elapsed time */
|
||||
tc->total_sum += time_delta;
|
||||
tc->sum += time_delta;
|
||||
}
|
||||
|
||||
static void osmo_time_cc_report(struct osmo_time_cc *tc, uint64_t now)
|
||||
{
|
||||
uint64_t delta;
|
||||
uint64_t n;
|
||||
if (!tc->cfg.rate_ctr)
|
||||
return;
|
||||
/* We report a sum "rounded up", ahead of time. If the granularity period has not yet elapsed after the last
|
||||
* reporting, do not report again yet. */
|
||||
if (tc->reported_sum > tc->sum)
|
||||
return;
|
||||
delta = tc->sum - tc->reported_sum;
|
||||
/* elapsed full periods */
|
||||
n = delta / GRAN_USEC(tc);
|
||||
/* If the delta has passed round_threshold (normally half of gran_usec), increment. */
|
||||
delta -= n * GRAN_USEC(tc);
|
||||
if (delta >= ROUND_THRESHOLD_USEC(tc))
|
||||
n++;
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
/* integer sanity, since rate_ctr_add() takes an int argument. */
|
||||
if (n > INT_MAX)
|
||||
n = INT_MAX;
|
||||
rate_ctr_add(tc->cfg.rate_ctr, n);
|
||||
/* Store the increments of gran_usec that were counted. */
|
||||
tc->reported_sum += n * GRAN_USEC(tc);
|
||||
}
|
||||
|
||||
static void osmo_time_cc_forget_sum(struct osmo_time_cc *tc, uint64_t now)
|
||||
{
|
||||
tc->reported_sum = 0;
|
||||
tc->sum = 0;
|
||||
|
||||
if (tc->last_counted_time < now)
|
||||
tc->last_counted_time = now;
|
||||
}
|
||||
|
||||
/*! Initialize struct osmo_time_cc. Call this once before use, and before setting up the .cfg items. */
|
||||
void osmo_time_cc_init(struct osmo_time_cc *tc)
|
||||
{
|
||||
*tc = (struct osmo_time_cc){0};
|
||||
}
|
||||
|
||||
/*! Report state to be recorded by osmo_time_cc instance. Setting an unchanged state repeatedly has no effect. */
|
||||
void osmo_time_cc_set_flag(struct osmo_time_cc *tc, bool flag)
|
||||
{
|
||||
uint64_t now = time_now_usec();
|
||||
if (!tc->start_time)
|
||||
osmo_time_cc_start(tc, now);
|
||||
/* No flag change == no effect */
|
||||
if (flag == tc->flag_state)
|
||||
return;
|
||||
/* Sum up elapsed time, report increments for that. */
|
||||
osmo_time_cc_count_time(tc, now);
|
||||
osmo_time_cc_report(tc, now);
|
||||
tc->flag_state = flag;
|
||||
osmo_time_cc_schedule_timer(tc, now);
|
||||
}
|
||||
|
||||
static void osmo_time_cc_timer_cb(void *data)
|
||||
{
|
||||
struct osmo_time_cc *tc = data;
|
||||
uint64_t now = time_now_usec();
|
||||
|
||||
osmo_time_cc_update_from_tdef(tc, now);
|
||||
|
||||
if (tc->flag_state) {
|
||||
osmo_time_cc_count_time(tc, now);
|
||||
osmo_time_cc_report(tc, now);
|
||||
} else if (tc->cfg.forget_sum_usec && tc->sum
|
||||
&& (now >= tc->last_counted_time + tc->cfg.forget_sum_usec)) {
|
||||
osmo_time_cc_forget_sum(tc, now);
|
||||
}
|
||||
osmo_time_cc_schedule_timer(tc, now);
|
||||
}
|
||||
|
||||
/*! Figure out the next time we should do anything, if the flag state remains unchanged. */
|
||||
static void osmo_time_cc_schedule_timer(struct osmo_time_cc *tc, uint64_t now)
|
||||
{
|
||||
uint64_t next_event = UINT64_MAX;
|
||||
|
||||
osmo_time_cc_update_from_tdef(tc, now);
|
||||
|
||||
/* If it is required, when will the next forget_sum happen? */
|
||||
if (tc->cfg.forget_sum_usec && !tc->flag_state && tc->sum > 0) {
|
||||
uint64_t next_forget_time = tc->last_counted_time + tc->cfg.forget_sum_usec;
|
||||
next_event = OSMO_MIN(next_event, next_forget_time);
|
||||
}
|
||||
/* Next rate_ctr increment? */
|
||||
if (tc->flag_state && tc->cfg.rate_ctr) {
|
||||
uint64_t next_inc = now + (tc->reported_sum - tc->sum) + ROUND_THRESHOLD_USEC(tc);
|
||||
next_event = OSMO_MIN(next_event, next_inc);
|
||||
}
|
||||
|
||||
/* No event coming up? */
|
||||
if (next_event == UINT64_MAX)
|
||||
return;
|
||||
|
||||
if (next_event <= now)
|
||||
next_event = 0;
|
||||
else
|
||||
next_event -= now;
|
||||
|
||||
osmo_timer_setup(&tc->timer, osmo_time_cc_timer_cb, tc);
|
||||
osmo_timer_del(&tc->timer);
|
||||
osmo_timer_schedule(&tc->timer, next_event / 1000000, next_event % 1000000);
|
||||
}
|
||||
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
|
||||
/*! @} */
|
|
@ -42,6 +42,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
|
|||
bsslap/bsslap_test \
|
||||
bssmap_le/bssmap_le_test \
|
||||
it_q/it_q_test \
|
||||
time_cc/time_cc_test \
|
||||
gsm48/rest_octets_test \
|
||||
base64/base64_test \
|
||||
$(NULL)
|
||||
|
@ -324,6 +325,9 @@ bssmap_le_bssmap_le_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
|||
it_q_it_q_test_SOURCES = it_q/it_q_test.c
|
||||
it_q_it_q_test_LDADD = $(LDADD)
|
||||
|
||||
time_cc_time_cc_test_SOURCES = time_cc/time_cc_test.c
|
||||
time_cc_time_cc_test_LDADD = $(LDADD)
|
||||
|
||||
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
|
||||
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
|
||||
:;{ \
|
||||
|
@ -413,6 +417,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
|
|||
bsslap/bsslap_test.ok \
|
||||
bssmap_le/bssmap_le_test.ok \
|
||||
it_q/it_q_test.ok \
|
||||
time_cc/time_cc_test.ok \
|
||||
gsm48/rest_octets_test.ok \
|
||||
base64/base64_test.ok \
|
||||
$(NULL)
|
||||
|
@ -609,6 +614,8 @@ endif
|
|||
>$(srcdir)/bssmap_le/bssmap_le_test.ok
|
||||
it_q/it_q_test \
|
||||
>$(srcdir)/it_q/it_q_test.ok
|
||||
time_cc/time_cc_test \
|
||||
>$(srcdir)/time_cc/time_cc_test.ok
|
||||
|
||||
check-local: atconfig $(TESTSUITE)
|
||||
[ -e /proc/cpuinfo ] && cat /proc/cpuinfo
|
||||
|
|
|
@ -452,3 +452,9 @@ AT_KEYWORDS([base64])
|
|||
cat $abs_srcdir/base64/base64_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/base64/base64_test], [0], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([time_cc])
|
||||
AT_KEYWORDS([time_cc])
|
||||
cat $abs_srcdir/time_cc/time_cc_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/time_cc/time_cc_test], [0], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
|
|
@ -0,0 +1,768 @@
|
|||
/* (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/tdef.h>
|
||||
#include <osmocom/core/time_cc.h>
|
||||
|
||||
enum my_ctrs {
|
||||
CTR_CEIL,
|
||||
CTR_ROUND,
|
||||
CTR_FLOOR,
|
||||
};
|
||||
|
||||
const struct rate_ctr_desc my_ctr_desc[] = {
|
||||
[CTR_CEIL] = {"ceil", "testing round_threshold_usec = 1"},
|
||||
[CTR_ROUND] = {"round", "testing round_threshold_usec = 0 = gran_usec/2"},
|
||||
[CTR_FLOOR] = {"floor", "testing round_threshold_usec = gran_usec"},
|
||||
};
|
||||
|
||||
const struct rate_ctr_group_desc my_ctrg_desc = {
|
||||
"time_cc_test",
|
||||
"Counters for osmo_time_cc test",
|
||||
0,
|
||||
ARRAY_SIZE(my_ctr_desc),
|
||||
my_ctr_desc,
|
||||
};
|
||||
|
||||
struct rate_ctr_group *my_ctrg;
|
||||
|
||||
|
||||
enum my_obj_timers {
|
||||
T_GRAN = -23,
|
||||
T_ROUND_THRESH = -24,
|
||||
T_FORGET_SUM = -25,
|
||||
};
|
||||
|
||||
struct osmo_tdef g_my_obj_tdefs[] = {
|
||||
{ .T = T_GRAN, .default_val = 0, .unit = OSMO_TDEF_MS, .desc = "flag_cc granularity, or zero for 1 second" },
|
||||
{ .T = T_ROUND_THRESH, .default_val = 0, .unit = OSMO_TDEF_MS,
|
||||
.desc = "flag_cc rounding threshold, or zero for half a granularity" },
|
||||
{ .T = T_FORGET_SUM, .default_val = 0, .unit = OSMO_TDEF_MS,
|
||||
.desc = "flag_cc inactivity forget period, or zero to not forget any timings" },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct my_obj {
|
||||
struct osmo_time_cc flag_cc_ceil;
|
||||
struct osmo_time_cc flag_cc_round;
|
||||
struct osmo_time_cc flag_cc_floor;
|
||||
};
|
||||
|
||||
void my_obj_init(struct my_obj *my_obj)
|
||||
{
|
||||
osmo_time_cc_init(&my_obj->flag_cc_ceil);
|
||||
my_obj->flag_cc_ceil.cfg = (struct osmo_time_cc_cfg){
|
||||
.rate_ctr = rate_ctr_group_get_ctr(my_ctrg, CTR_CEIL),
|
||||
.round_threshold_usec = 1,
|
||||
.T_gran = T_GRAN,
|
||||
.T_forget_sum = T_FORGET_SUM,
|
||||
.T_defs = g_my_obj_tdefs,
|
||||
};
|
||||
|
||||
osmo_time_cc_init(&my_obj->flag_cc_round);
|
||||
my_obj->flag_cc_round.cfg = (struct osmo_time_cc_cfg){
|
||||
.rate_ctr = rate_ctr_group_get_ctr(my_ctrg, CTR_ROUND),
|
||||
.T_gran = T_GRAN,
|
||||
.T_round_threshold = T_ROUND_THRESH,
|
||||
.T_forget_sum = T_FORGET_SUM,
|
||||
.T_defs = g_my_obj_tdefs,
|
||||
};
|
||||
|
||||
osmo_time_cc_init(&my_obj->flag_cc_floor);
|
||||
my_obj->flag_cc_floor.cfg = (struct osmo_time_cc_cfg){
|
||||
.rate_ctr = rate_ctr_group_get_ctr(my_ctrg, CTR_FLOOR),
|
||||
.round_threshold_usec = UINT64_MAX, /* always >= gran_usec */
|
||||
.T_gran = T_GRAN,
|
||||
.T_forget_sum = T_FORGET_SUM,
|
||||
.T_defs = g_my_obj_tdefs,
|
||||
};
|
||||
}
|
||||
|
||||
void my_obj_event(struct my_obj *my_obj, bool flag)
|
||||
{
|
||||
osmo_time_cc_set_flag(&my_obj->flag_cc_ceil, flag);
|
||||
osmo_time_cc_set_flag(&my_obj->flag_cc_round, flag);
|
||||
osmo_time_cc_set_flag(&my_obj->flag_cc_floor, flag);
|
||||
}
|
||||
|
||||
void my_obj_destruct(struct my_obj *my_obj)
|
||||
{
|
||||
osmo_time_cc_cleanup(&my_obj->flag_cc_ceil);
|
||||
osmo_time_cc_cleanup(&my_obj->flag_cc_round);
|
||||
osmo_time_cc_cleanup(&my_obj->flag_cc_floor);
|
||||
}
|
||||
|
||||
static const struct log_info_cat log_categories[] = {
|
||||
};
|
||||
|
||||
static const struct log_info log_info = {
|
||||
.cat = log_categories,
|
||||
.num_cat = ARRAY_SIZE(log_categories),
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
void *ctx = talloc_named_const(NULL, 0, "time_cc_test");
|
||||
struct timespec *now;
|
||||
struct my_obj my_obj = {0};
|
||||
|
||||
osmo_init_logging2(ctx, &log_info);
|
||||
|
||||
/* enable override for CLOCK_MONOTONIC */
|
||||
osmo_clock_override_enable(CLOCK_MONOTONIC, true);
|
||||
now = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
|
||||
now->tv_sec = 23000;
|
||||
now->tv_nsec = 0;
|
||||
|
||||
/* enable override for osmo_gettimeofday(), for osmo_timer_schedule() */
|
||||
osmo_gettimeofday_override = true;
|
||||
osmo_gettimeofday_override_time = (struct timeval){23000, 0};
|
||||
|
||||
my_ctrg = rate_ctr_group_alloc(ctx, &my_ctrg_desc, 0);
|
||||
|
||||
#define CHECK_RATE_CTRS(exp_ceil, exp_round, exp_floor) do { \
|
||||
printf("%d CHECK_RATE_CTRS(" #exp_ceil ", " #exp_round ", " #exp_floor ")", \
|
||||
my_obj.flag_cc_round.flag_state); \
|
||||
while (osmo_select_main_ctx(1) > 0); \
|
||||
if (exp_ceil != my_obj.flag_cc_ceil.cfg.rate_ctr->current \
|
||||
|| exp_round != my_obj.flag_cc_round.cfg.rate_ctr->current \
|
||||
|| exp_floor != my_obj.flag_cc_floor.cfg.rate_ctr->current) \
|
||||
printf("\n ERROR on line %d: ctr_ceil=%"PRIu64" ctr_round=%"PRIu64" ctr_floor=%"PRIu64"\n", \
|
||||
__LINE__, \
|
||||
my_obj.flag_cc_ceil.cfg.rate_ctr->current, \
|
||||
my_obj.flag_cc_round.cfg.rate_ctr->current, \
|
||||
my_obj.flag_cc_floor.cfg.rate_ctr->current); \
|
||||
else \
|
||||
printf(" ok\n"); \
|
||||
} while (0)
|
||||
|
||||
#define ADD_MILLISECS_NO_SELECT(ms) do { \
|
||||
osmo_clock_override_add(CLOCK_MONOTONIC, ms / 1000, (uint64_t)(ms % 1000) * 1000000); \
|
||||
osmo_gettimeofday_override_add(ms / 1000, (uint64_t)(ms % 1000) * 1000); \
|
||||
printf("%d ADD_MILLISECS(" #ms ") --> %ld.%03ld", my_obj.flag_cc_round.flag_state, \
|
||||
now->tv_sec, now->tv_nsec/1000000); \
|
||||
printf("\n"); \
|
||||
} while (0)
|
||||
|
||||
#define ADD_MILLISECS(ms) do { \
|
||||
ADD_MILLISECS_NO_SELECT(ms); \
|
||||
while (osmo_select_main_ctx(1) > 0); \
|
||||
} while (0)
|
||||
|
||||
#define FLAG(VAL) do { \
|
||||
printf(" flag: %s -> %s\n", my_obj.flag_cc_round.flag_state ? "TRUE" : "FALSE", VAL ? "TRUE" : "FALSE"); \
|
||||
my_obj_event(&my_obj, VAL); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* sum ^
|
||||
* | ________
|
||||
* | /
|
||||
* | /
|
||||
* | /
|
||||
* 3*gran --+--------------------------------------+
|
||||
* | /:
|
||||
* | / :
|
||||
* | - - - - - - - - - - - - - - - - - / :
|
||||
* | /. :
|
||||
* | / . :
|
||||
* 2*gran --+--------------------------------+ . :
|
||||
* | /: . :
|
||||
* | / : . :
|
||||
* | - - - - - - - - - -_________/ : . :
|
||||
* | / . : . :
|
||||
* | / . : . :
|
||||
* 1*gran --+-----------------+ . : . :
|
||||
* | /: . : . :
|
||||
* | / : . : . :
|
||||
* | - - - - - - -/ : . : . :
|
||||
* | /. : . : . :
|
||||
* | ....-------' . : . : . :
|
||||
* 0 +----------------------------------------------------------> elapsed time
|
||||
* . : . : . :
|
||||
* _ _ _______ ____________
|
||||
* flag: __| |_| |____| . : |_______|. : . : |__________
|
||||
* f t f t f t . : f t. : . : f
|
||||
* round_threshold_usec : . : . : . :
|
||||
* = 1 usec: 0 1 . :2 . :3 . :4 = "ceil()"
|
||||
* = 0 == gran_usec/2: 0 1 : 2 : 3 : = "round()"
|
||||
* = gran_usec: 0 1 2 3 = "floor()"
|
||||
*/
|
||||
|
||||
printf("\n----------- cumulating time, without forget_sum\n\n");
|
||||
|
||||
my_obj_init(&my_obj);
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
ADD_MILLISECS(100);
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
/* flag has just turned true the first time */
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
ADD_MILLISECS(1);
|
||||
/* flag has been true for 0.001s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS(99);
|
||||
/* flag has been true for 0.1s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS(100);
|
||||
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS(100);
|
||||
/* flag has been true for 0.2s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS(300);
|
||||
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS(299);
|
||||
/* flag has been true for 0.499s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS(1);
|
||||
/* flag has been true for 0.5s */
|
||||
CHECK_RATE_CTRS(1, 1, 0);
|
||||
ADD_MILLISECS(499);
|
||||
/* flag has been true for 0.999s */
|
||||
CHECK_RATE_CTRS(1, 1, 0);
|
||||
ADD_MILLISECS(1);
|
||||
/* flag has been true for 1.0s */
|
||||
CHECK_RATE_CTRS(1, 1, 1);
|
||||
ADD_MILLISECS(1);
|
||||
/* flag has been true for 1.001s */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(299);
|
||||
/* flag has been true for 1.3s */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
|
||||
ADD_MILLISECS(400);
|
||||
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(199);
|
||||
/* flag has been true for 1.499s */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(2);
|
||||
/* flag has been true for 1.501s */
|
||||
CHECK_RATE_CTRS(2, 2, 1);
|
||||
ADD_MILLISECS(498);
|
||||
/* flag has been true for 1.999s */
|
||||
CHECK_RATE_CTRS(2, 2, 1);
|
||||
ADD_MILLISECS(2);
|
||||
/* flag has been true for 2.001s */
|
||||
CHECK_RATE_CTRS(3, 2, 2);
|
||||
ADD_MILLISECS(500);
|
||||
/* flag has been true for 2.501s */
|
||||
CHECK_RATE_CTRS(3, 3, 2);
|
||||
ADD_MILLISECS(498);
|
||||
/* flag has been true for 2.999s */
|
||||
CHECK_RATE_CTRS(3, 3, 2);
|
||||
ADD_MILLISECS(3);
|
||||
/* flag has been true for 3.003s */
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
ADD_MILLISECS(200);
|
||||
/* flag has been true for 3.203s */
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
|
||||
ADD_MILLISECS(4321);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
ADD_MILLISECS(5678);
|
||||
CHECK_RATE_CTRS(9, 9, 8);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(9, 9, 8);
|
||||
|
||||
my_obj_destruct(&my_obj);
|
||||
rate_ctr_group_reset(my_ctrg);
|
||||
|
||||
printf("\n----------- test forget_sum_usec\n\n");
|
||||
osmo_tdef_set(g_my_obj_tdefs, T_FORGET_SUM, 10, OSMO_TDEF_S);
|
||||
|
||||
now->tv_sec = 23000;
|
||||
now->tv_nsec = 0;
|
||||
osmo_gettimeofday_override_time = (struct timeval){23000, 0};
|
||||
|
||||
my_obj_init(&my_obj);
|
||||
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
/* flag has just turned true the first time */
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
ADD_MILLISECS(100);
|
||||
/* flag has been true for 0.1s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS(1000);
|
||||
/* 1 s of being false, forget_sum_usec has not yet occurred */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS(8999);
|
||||
/* 9.999 s of being false, forget_sum_usec has not yet occurred */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS(1);
|
||||
/* 10 s of being false, forget_sum_usec has occurred */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS(1);
|
||||
/* Since previous sums were forgotton, ceil() triggers again */
|
||||
CHECK_RATE_CTRS(2, 0, 0);
|
||||
/* If the sum had not been forgotten, adding 400 ms to the initial 100 ms would have triggered round(). Verify
|
||||
* that this does not occur, since now full 500 ms are required */
|
||||
ADD_MILLISECS(399);
|
||||
CHECK_RATE_CTRS(2, 0, 0);
|
||||
/* Adding another 100 ms will trigger round() */
|
||||
ADD_MILLISECS(99);
|
||||
CHECK_RATE_CTRS(2, 0, 0);
|
||||
ADD_MILLISECS(1);
|
||||
CHECK_RATE_CTRS(2, 1, 0);
|
||||
/* If the sum had not been forgotten, adding 900 ms to the initial 100 ms would have triggered floor(). Verify
|
||||
* that this does not occur, since now full 1000 ms are required. We already added 500 ms above. */
|
||||
ADD_MILLISECS(400);
|
||||
CHECK_RATE_CTRS(2, 1, 0);
|
||||
/* Adding another 100 ms will trigger floor() */
|
||||
ADD_MILLISECS(99);
|
||||
CHECK_RATE_CTRS(2, 1, 0);
|
||||
ADD_MILLISECS(1);
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
|
||||
/* Test that durations of false below forget_sum_usec never trigger a forget */
|
||||
ADD_MILLISECS(300);
|
||||
CHECK_RATE_CTRS(3, 1, 1);
|
||||
/* internal counter is now at 0.3s above the last reported rate counter */
|
||||
FLAG(false);
|
||||
ADD_MILLISECS(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS(25);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS(25);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS(25);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS(25);
|
||||
/* internal counter is now at 0.4s above the last reported rate counter */
|
||||
CHECK_RATE_CTRS(3, 1, 1);
|
||||
ADD_MILLISECS(100);
|
||||
CHECK_RATE_CTRS(3, 2, 1);
|
||||
ADD_MILLISECS(500);
|
||||
CHECK_RATE_CTRS(3, 2, 2);
|
||||
|
||||
/* Test that repeated osmo_time_cc_set_flag(false) does not cancel a forget_sum_usec */
|
||||
ADD_MILLISECS(300);
|
||||
/* internal counter is now at 0.3s above the last reported rate counter */
|
||||
CHECK_RATE_CTRS(4, 2, 2);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS(5000);
|
||||
/* Repeat 'false', must not affect forget_sum_usec */
|
||||
FLAG(false);
|
||||
ADD_MILLISECS(5000);
|
||||
CHECK_RATE_CTRS(4, 2, 2);
|
||||
/* 10 s have passed, forget_sum_usec has occurred.
|
||||
* Hence ceil() will trigger again right away: */
|
||||
FLAG(true);
|
||||
ADD_MILLISECS(1);
|
||||
CHECK_RATE_CTRS(5, 2, 2);
|
||||
/* Adding 200 ms to the initial 300 ms would have triggered round(), but no more after forget_sum_usec */
|
||||
ADD_MILLISECS(199);
|
||||
CHECK_RATE_CTRS(5, 2, 2);
|
||||
/* Adding another 300 ms will trigger round() */
|
||||
ADD_MILLISECS(299);
|
||||
CHECK_RATE_CTRS(5, 2, 2);
|
||||
ADD_MILLISECS(1);
|
||||
CHECK_RATE_CTRS(5, 3, 2);
|
||||
/* Adding 700 ms to the initial 300 ms would have triggered ceil(), but no more after forget_sum_usec */
|
||||
ADD_MILLISECS(200);
|
||||
CHECK_RATE_CTRS(5, 3, 2);
|
||||
/* Adding another 300 ms will trigger ceil() */
|
||||
ADD_MILLISECS(299);
|
||||
CHECK_RATE_CTRS(5, 3, 2);
|
||||
ADD_MILLISECS(1);
|
||||
CHECK_RATE_CTRS(5, 3, 3);
|
||||
|
||||
my_obj_destruct(&my_obj);
|
||||
rate_ctr_group_reset(my_ctrg);
|
||||
|
||||
|
||||
/* Verify correctness when select() lags and runs timer callbacks too late */
|
||||
printf("\n----------- cumulating time, without forget_sum, when timer cb are invoked late\n\n");
|
||||
osmo_tdef_set(g_my_obj_tdefs, T_FORGET_SUM, 0, OSMO_TDEF_S);
|
||||
now->tv_sec = 23000;
|
||||
now->tv_nsec = 0;
|
||||
osmo_gettimeofday_override_time = (struct timeval){23000, 0};
|
||||
|
||||
my_obj_init(&my_obj);
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(100);
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
/* flag has just turned true the first time */
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
ADD_MILLISECS_NO_SELECT(100);
|
||||
/* flag has been true for 0.1s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(100);
|
||||
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS_NO_SELECT(100);
|
||||
/* flag has been true for 0.2s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(300);
|
||||
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS_NO_SELECT(799);
|
||||
/* flag has been true for 0.999s */
|
||||
CHECK_RATE_CTRS(1, 1, 0);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
/* flag has been true for 1.0s */
|
||||
CHECK_RATE_CTRS(1, 1, 1);
|
||||
ADD_MILLISECS_NO_SELECT(300);
|
||||
/* flag has been true for 1.3s */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(400);
|
||||
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS_NO_SELECT(699);
|
||||
/* flag has been true for 1.999s */
|
||||
CHECK_RATE_CTRS(2, 2, 1);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
/* flag has been true for 2.0s */
|
||||
CHECK_RATE_CTRS(2, 2, 2);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
/* flag has been true for 2.001s */
|
||||
CHECK_RATE_CTRS(3, 2, 2);
|
||||
ADD_MILLISECS_NO_SELECT(499);
|
||||
/* flag has been true for 2.5s */
|
||||
CHECK_RATE_CTRS(3, 3, 2);
|
||||
ADD_MILLISECS_NO_SELECT(499);
|
||||
/* flag has been true for 2.999s */
|
||||
CHECK_RATE_CTRS(3, 3, 2);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
/* flag has been true for 3.0s */
|
||||
CHECK_RATE_CTRS(3, 3, 3);
|
||||
ADD_MILLISECS_NO_SELECT(200);
|
||||
/* flag has been true for 3.2s */
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(4321);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
ADD_MILLISECS_NO_SELECT(5678);
|
||||
CHECK_RATE_CTRS(9, 9, 8);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(9, 9, 8);
|
||||
|
||||
my_obj_destruct(&my_obj);
|
||||
rate_ctr_group_reset(my_ctrg);
|
||||
|
||||
|
||||
printf("\n----------- test forget_sum, when timer cb are invoked late\n\n");
|
||||
osmo_tdef_set(g_my_obj_tdefs, T_FORGET_SUM, 10, OSMO_TDEF_S);
|
||||
|
||||
now->tv_sec = 23000;
|
||||
now->tv_nsec = 0;
|
||||
osmo_gettimeofday_override_time = (struct timeval){23000, 0};
|
||||
|
||||
my_obj_init(&my_obj);
|
||||
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
/* flag has just turned true the first time */
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
ADD_MILLISECS_NO_SELECT(100);
|
||||
/* flag has been true for 0.1s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
FLAG(false);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(1000);
|
||||
/* 1 s of being false, forget_sum_usec has not yet occurred */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(8999);
|
||||
/* 9.999 s of being false, forget_sum_usec has not yet occurred */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
/* 10 s of being false, forget_sum_usec has occurred */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
/* Since previous sums were forgotton, ceil() triggers again */
|
||||
CHECK_RATE_CTRS(2, 0, 0);
|
||||
/* If the sum had not been forgotten, adding 400 ms to the initial 100 ms would have triggered round(). Verify
|
||||
* that this does not occur, since now full 500 ms are required */
|
||||
ADD_MILLISECS_NO_SELECT(399);
|
||||
CHECK_RATE_CTRS(2, 0, 0);
|
||||
/* Adding another 100 ms will trigger round() */
|
||||
ADD_MILLISECS_NO_SELECT(99);
|
||||
CHECK_RATE_CTRS(2, 0, 0);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
CHECK_RATE_CTRS(2, 1, 0);
|
||||
/* If the sum had not been forgotten, adding 900 ms to the initial 100 ms would have triggered floor(). Verify
|
||||
* that this does not occur, since now full 1000 ms are required. We already added 500 ms above. */
|
||||
ADD_MILLISECS_NO_SELECT(400);
|
||||
CHECK_RATE_CTRS(2, 1, 0);
|
||||
/* Adding another 100 ms will trigger floor() */
|
||||
ADD_MILLISECS_NO_SELECT(99);
|
||||
CHECK_RATE_CTRS(2, 1, 0);
|
||||
ADD_MILLISECS_NO_SELECT(1);
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
|
||||
/* Test that durations of false below forget_sum_usec never trigger a forget */
|
||||
ADD_MILLISECS_NO_SELECT(300);
|
||||
CHECK_RATE_CTRS(3, 1, 1);
|
||||
/* internal counter is now at 0.3s above the last reported rate counter */
|
||||
FLAG(false);
|
||||
ADD_MILLISECS_NO_SELECT(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS_NO_SELECT(25);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS_NO_SELECT(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS_NO_SELECT(25);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS_NO_SELECT(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS_NO_SELECT(25);
|
||||
FLAG(false);
|
||||
ADD_MILLISECS_NO_SELECT(9999);
|
||||
FLAG(true);
|
||||
ADD_MILLISECS_NO_SELECT(25);
|
||||
/* internal counter is now at 0.4s above the last reported rate counter */
|
||||
CHECK_RATE_CTRS(3, 1, 1);
|
||||
ADD_MILLISECS_NO_SELECT(100);
|
||||
CHECK_RATE_CTRS(3, 2, 1);
|
||||
ADD_MILLISECS_NO_SELECT(500);
|
||||
CHECK_RATE_CTRS(3, 2, 2);
|
||||
|
||||
my_obj_destruct(&my_obj);
|
||||
rate_ctr_group_reset(my_ctrg);
|
||||
|
||||
|
||||
#define SET_TDEFS(gran, round_thresh, forget_sum) do { \
|
||||
osmo_tdef_set(g_my_obj_tdefs, T_GRAN, gran, OSMO_TDEF_MS); \
|
||||
osmo_tdef_set(g_my_obj_tdefs, T_ROUND_THRESH, round_thresh, OSMO_TDEF_MS); \
|
||||
osmo_tdef_set(g_my_obj_tdefs, T_FORGET_SUM, forget_sum, OSMO_TDEF_S); \
|
||||
printf("T_defs: T_gran=%luusec T_round_threshold=%luusec T_forget_sum=%luusec\n", \
|
||||
osmo_tdef_get(g_my_obj_tdefs, T_GRAN, OSMO_TDEF_US, -1), \
|
||||
osmo_tdef_get(g_my_obj_tdefs, T_ROUND_THRESH, OSMO_TDEF_US, -1), \
|
||||
osmo_tdef_get(g_my_obj_tdefs, T_FORGET_SUM, OSMO_TDEF_US, -1)); \
|
||||
} while (0)
|
||||
|
||||
printf("\n----------- test T_defs\n\n");
|
||||
now->tv_sec = 23000;
|
||||
now->tv_nsec = 0;
|
||||
osmo_gettimeofday_override_time = (struct timeval){23000, 0};
|
||||
|
||||
SET_TDEFS(100, 10, 0);
|
||||
|
||||
my_obj_init(&my_obj);
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
ADD_MILLISECS(100);
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
|
||||
FLAG(true);
|
||||
/* flag has just turned true the first time */
|
||||
CHECK_RATE_CTRS(0, 0, 0);
|
||||
ADD_MILLISECS(9);
|
||||
/* flag has been true for 0.009s */
|
||||
CHECK_RATE_CTRS(1, 0, 0);
|
||||
ADD_MILLISECS(1);
|
||||
/* flag has been true for 0.010s */
|
||||
CHECK_RATE_CTRS(1, 1, 0);
|
||||
ADD_MILLISECS(90);
|
||||
/* flag has been true for 0.1s */
|
||||
CHECK_RATE_CTRS(1, 1, 1);
|
||||
|
||||
SET_TDEFS(200, 190, 1);
|
||||
/* gran is changed to 200ms, but still continues until the next scheduled event until the change is picked up.
|
||||
* For ceil(), it is 1 ms ahead.
|
||||
* For round(), it is 10 ms ahead.
|
||||
* For floor(), it is at the next full (previous) gran 100 ms ahead.
|
||||
* When T_defs change, all internal sums are reset to zero without reporting.
|
||||
*/
|
||||
CHECK_RATE_CTRS(1, 1, 1);
|
||||
ADD_MILLISECS(1);
|
||||
/* 1ms elapsed: ceil() picks up the T_gran change, starts anew. */
|
||||
/* elapsed: ceil 0 ms */
|
||||
CHECK_RATE_CTRS(1, 1, 1);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 1 ms */
|
||||
/* ceil() increments because flag has been true for more than 1 us after reset */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(8);
|
||||
/* 10 ms elapsed: round() picks up the T_gran change, starts anew */
|
||||
/* elapsed: ceil 9 ms, round 0 ms */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(90);
|
||||
/* 100 ms elapsed: floor() picks up the T_gran change, starts anew */
|
||||
/* elapsed: ceil 99 ms, round 90 ms, floor 0 ms */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(99);
|
||||
/* elapsed: ceil 198 ms, round 189 ms, floor 99 ms */
|
||||
CHECK_RATE_CTRS(2, 1, 1);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 199 ms, round 190 ms, floor 100 ms */
|
||||
CHECK_RATE_CTRS(2, 2, 1);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 200 ms, round 191 ms, floor 101 ms */
|
||||
CHECK_RATE_CTRS(2, 2, 1);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 201 ms, round 192 ms, floor 102 ms */
|
||||
CHECK_RATE_CTRS(3, 2, 1);
|
||||
ADD_MILLISECS(98);
|
||||
/* elapsed: ceil 299 ms, round 290 ms, floor 200 ms */
|
||||
CHECK_RATE_CTRS(3, 2, 2);
|
||||
ADD_MILLISECS(99);
|
||||
/* elapsed: ceil 398 ms, round 389 ms, floor 299 ms */
|
||||
CHECK_RATE_CTRS(3, 2, 2);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 399 ms, round 390 ms, floor 300 ms */
|
||||
CHECK_RATE_CTRS(3, 3, 2);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 400 ms, round 391 ms, floor 301 ms */
|
||||
CHECK_RATE_CTRS(3, 3, 2);
|
||||
ADD_MILLISECS(1);
|
||||
/* elapsed: ceil 401 ms, round 392 ms, floor 302 ms */
|
||||
CHECK_RATE_CTRS(4, 3, 2);
|
||||
ADD_MILLISECS(98);
|
||||
/* elapsed: ceil 499 ms, round 490 ms, floor 400 ms */
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
|
||||
|
||||
SET_TDEFS(100, 0, 0);
|
||||
/* T_defs change, but they only get picked up upon the next event:
|
||||
* For ceil(), it is 102 ms ahead.
|
||||
* For round(), it is 100 ms ahead (thresh is still 190, currently at 90).
|
||||
* For floor(), it is 200 ms ahead.
|
||||
* When T_defs change, all internal sums are reset to zero without reporting.
|
||||
*/
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
ADD_MILLISECS(100);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
/* round() picks up the new T_defs. Internal sum resets, nothing else happens yet.
|
||||
* round() schedules the next event 50 ms ahead. */
|
||||
ADD_MILLISECS(2);
|
||||
CHECK_RATE_CTRS(4, 3, 3);
|
||||
/* ceil() picks up the change, its next event is 1 ms ahead. */
|
||||
ADD_MILLISECS(1);
|
||||
/* ceil: 0.001
|
||||
* round: 0.003
|
||||
* floor: still 97 ms until it picks up the change */
|
||||
CHECK_RATE_CTRS(5, 3, 3);
|
||||
ADD_MILLISECS(46);
|
||||
CHECK_RATE_CTRS(5, 3, 3);
|
||||
ADD_MILLISECS(1);
|
||||
/* round() has first counter trigger after T_defs change. */
|
||||
CHECK_RATE_CTRS(5, 4, 3);
|
||||
/* ceil: 0.048
|
||||
* round: 0.050
|
||||
* floor: still 50 ms until it picks up the change */
|
||||
ADD_MILLISECS(50);
|
||||
/* floor() picks up the change. nothing happens yet. */
|
||||
/* ceil: 0.098
|
||||
* round: 0.100
|
||||
* floor: 0.0 */
|
||||
ADD_MILLISECS(2);
|
||||
/* ceil: 0.100
|
||||
* round: 0.102
|
||||
* floor: 0.002 */
|
||||
CHECK_RATE_CTRS(5, 4, 3);
|
||||
ADD_MILLISECS(1);
|
||||
/* ceil: 0.101
|
||||
* round: 0.103
|
||||
* floor: 0.003 */
|
||||
CHECK_RATE_CTRS(6, 4, 3);
|
||||
ADD_MILLISECS(46);
|
||||
/* ceil: 0.147
|
||||
* round: 0.149
|
||||
* floor: 0.049 */
|
||||
CHECK_RATE_CTRS(6, 4, 3);
|
||||
ADD_MILLISECS(1);
|
||||
/* ceil: 0.148
|
||||
* round: 0.150
|
||||
* floor: 0.050 */
|
||||
CHECK_RATE_CTRS(6, 5, 3);
|
||||
|
||||
my_obj_destruct(&my_obj);
|
||||
rate_ctr_group_reset(my_ctrg);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,328 @@
|
|||
|
||||
----------- cumulating time, without forget_sum
|
||||
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
0 ADD_MILLISECS(100) --> 23000.100
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.101
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(99) --> 23000.200
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(100) --> 23000.300
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(100) --> 23000.400
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(300) --> 23000.700
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(299) --> 23000.999
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23001.000
|
||||
1 CHECK_RATE_CTRS(1, 1, 0) ok
|
||||
1 ADD_MILLISECS(499) --> 23001.499
|
||||
1 CHECK_RATE_CTRS(1, 1, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23001.500
|
||||
1 CHECK_RATE_CTRS(1, 1, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23001.501
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(299) --> 23001.800
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
0 ADD_MILLISECS(400) --> 23002.200
|
||||
0 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(199) --> 23002.399
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(2) --> 23002.401
|
||||
1 CHECK_RATE_CTRS(2, 2, 1) ok
|
||||
1 ADD_MILLISECS(498) --> 23002.899
|
||||
1 CHECK_RATE_CTRS(2, 2, 1) ok
|
||||
1 ADD_MILLISECS(2) --> 23002.901
|
||||
1 CHECK_RATE_CTRS(3, 2, 2) ok
|
||||
1 ADD_MILLISECS(500) --> 23003.401
|
||||
1 CHECK_RATE_CTRS(3, 3, 2) ok
|
||||
1 ADD_MILLISECS(498) --> 23003.899
|
||||
1 CHECK_RATE_CTRS(3, 3, 2) ok
|
||||
1 ADD_MILLISECS(3) --> 23003.902
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
1 ADD_MILLISECS(200) --> 23004.102
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
0 ADD_MILLISECS(4321) --> 23008.423
|
||||
0 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
1 ADD_MILLISECS(5678) --> 23014.101
|
||||
1 CHECK_RATE_CTRS(9, 9, 8) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(9, 9, 8) ok
|
||||
|
||||
----------- test forget_sum_usec
|
||||
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
1 ADD_MILLISECS(100) --> 23000.100
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(1000) --> 23001.100
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(8999) --> 23010.099
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(1) --> 23010.100
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23010.101
|
||||
1 CHECK_RATE_CTRS(2, 0, 0) ok
|
||||
1 ADD_MILLISECS(399) --> 23010.500
|
||||
1 CHECK_RATE_CTRS(2, 0, 0) ok
|
||||
1 ADD_MILLISECS(99) --> 23010.599
|
||||
1 CHECK_RATE_CTRS(2, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23010.600
|
||||
1 CHECK_RATE_CTRS(2, 1, 0) ok
|
||||
1 ADD_MILLISECS(400) --> 23011.000
|
||||
1 CHECK_RATE_CTRS(2, 1, 0) ok
|
||||
1 ADD_MILLISECS(99) --> 23011.099
|
||||
1 CHECK_RATE_CTRS(2, 1, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23011.100
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(300) --> 23011.400
|
||||
1 CHECK_RATE_CTRS(3, 1, 1) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23021.399
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23021.424
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23031.423
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23031.448
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23041.447
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23041.472
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23051.471
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23051.496
|
||||
1 CHECK_RATE_CTRS(3, 1, 1) ok
|
||||
1 ADD_MILLISECS(100) --> 23051.596
|
||||
1 CHECK_RATE_CTRS(3, 2, 1) ok
|
||||
1 ADD_MILLISECS(500) --> 23052.096
|
||||
1 CHECK_RATE_CTRS(3, 2, 2) ok
|
||||
1 ADD_MILLISECS(300) --> 23052.396
|
||||
1 CHECK_RATE_CTRS(4, 2, 2) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(5000) --> 23057.396
|
||||
flag: FALSE -> FALSE
|
||||
0 ADD_MILLISECS(5000) --> 23062.396
|
||||
0 CHECK_RATE_CTRS(4, 2, 2) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(1) --> 23062.397
|
||||
1 CHECK_RATE_CTRS(5, 2, 2) ok
|
||||
1 ADD_MILLISECS(199) --> 23062.596
|
||||
1 CHECK_RATE_CTRS(5, 2, 2) ok
|
||||
1 ADD_MILLISECS(299) --> 23062.895
|
||||
1 CHECK_RATE_CTRS(5, 2, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23062.896
|
||||
1 CHECK_RATE_CTRS(5, 3, 2) ok
|
||||
1 ADD_MILLISECS(200) --> 23063.096
|
||||
1 CHECK_RATE_CTRS(5, 3, 2) ok
|
||||
1 ADD_MILLISECS(299) --> 23063.395
|
||||
1 CHECK_RATE_CTRS(5, 3, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23063.396
|
||||
1 CHECK_RATE_CTRS(5, 3, 3) ok
|
||||
|
||||
----------- cumulating time, without forget_sum, when timer cb are invoked late
|
||||
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
0 ADD_MILLISECS(100) --> 23000.100
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
1 ADD_MILLISECS(100) --> 23000.200
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(100) --> 23000.300
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(100) --> 23000.400
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(300) --> 23000.700
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(799) --> 23001.499
|
||||
1 CHECK_RATE_CTRS(1, 1, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23001.500
|
||||
1 CHECK_RATE_CTRS(1, 1, 1) ok
|
||||
1 ADD_MILLISECS(300) --> 23001.800
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
0 ADD_MILLISECS(400) --> 23002.200
|
||||
0 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(699) --> 23002.899
|
||||
1 CHECK_RATE_CTRS(2, 2, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23002.900
|
||||
1 CHECK_RATE_CTRS(2, 2, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23002.901
|
||||
1 CHECK_RATE_CTRS(3, 2, 2) ok
|
||||
1 ADD_MILLISECS(499) --> 23003.400
|
||||
1 CHECK_RATE_CTRS(3, 3, 2) ok
|
||||
1 ADD_MILLISECS(499) --> 23003.899
|
||||
1 CHECK_RATE_CTRS(3, 3, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23003.900
|
||||
1 CHECK_RATE_CTRS(3, 3, 3) ok
|
||||
1 ADD_MILLISECS(200) --> 23004.100
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
0 ADD_MILLISECS(4321) --> 23008.421
|
||||
0 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
1 ADD_MILLISECS(5678) --> 23014.099
|
||||
1 CHECK_RATE_CTRS(9, 9, 8) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(9, 9, 8) ok
|
||||
|
||||
----------- test forget_sum, when timer cb are invoked late
|
||||
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
1 ADD_MILLISECS(100) --> 23000.100
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(1000) --> 23001.100
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(8999) --> 23010.099
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
0 ADD_MILLISECS(1) --> 23010.100
|
||||
0 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23010.101
|
||||
1 CHECK_RATE_CTRS(2, 0, 0) ok
|
||||
1 ADD_MILLISECS(399) --> 23010.500
|
||||
1 CHECK_RATE_CTRS(2, 0, 0) ok
|
||||
1 ADD_MILLISECS(99) --> 23010.599
|
||||
1 CHECK_RATE_CTRS(2, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23010.600
|
||||
1 CHECK_RATE_CTRS(2, 1, 0) ok
|
||||
1 ADD_MILLISECS(400) --> 23011.000
|
||||
1 CHECK_RATE_CTRS(2, 1, 0) ok
|
||||
1 ADD_MILLISECS(99) --> 23011.099
|
||||
1 CHECK_RATE_CTRS(2, 1, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23011.100
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(300) --> 23011.400
|
||||
1 CHECK_RATE_CTRS(3, 1, 1) ok
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23021.399
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23021.424
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23031.423
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23031.448
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23041.447
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23041.472
|
||||
flag: TRUE -> FALSE
|
||||
0 ADD_MILLISECS(9999) --> 23051.471
|
||||
flag: FALSE -> TRUE
|
||||
1 ADD_MILLISECS(25) --> 23051.496
|
||||
1 CHECK_RATE_CTRS(3, 1, 1) ok
|
||||
1 ADD_MILLISECS(100) --> 23051.596
|
||||
1 CHECK_RATE_CTRS(3, 2, 1) ok
|
||||
1 ADD_MILLISECS(500) --> 23052.096
|
||||
1 CHECK_RATE_CTRS(3, 2, 2) ok
|
||||
|
||||
----------- test T_defs
|
||||
|
||||
T_defs: T_gran=100000usec T_round_threshold=10000usec T_forget_sum=0usec
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
0 ADD_MILLISECS(100) --> 23000.100
|
||||
0 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
flag: FALSE -> TRUE
|
||||
1 CHECK_RATE_CTRS(0, 0, 0) ok
|
||||
1 ADD_MILLISECS(9) --> 23000.109
|
||||
1 CHECK_RATE_CTRS(1, 0, 0) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.110
|
||||
1 CHECK_RATE_CTRS(1, 1, 0) ok
|
||||
1 ADD_MILLISECS(90) --> 23000.200
|
||||
1 CHECK_RATE_CTRS(1, 1, 1) ok
|
||||
T_defs: T_gran=200000usec T_round_threshold=190000usec T_forget_sum=1000000usec
|
||||
1 CHECK_RATE_CTRS(1, 1, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.201
|
||||
1 CHECK_RATE_CTRS(1, 1, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.202
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(8) --> 23000.210
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(90) --> 23000.300
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(99) --> 23000.399
|
||||
1 CHECK_RATE_CTRS(2, 1, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.400
|
||||
1 CHECK_RATE_CTRS(2, 2, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.401
|
||||
1 CHECK_RATE_CTRS(2, 2, 1) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.402
|
||||
1 CHECK_RATE_CTRS(3, 2, 1) ok
|
||||
1 ADD_MILLISECS(98) --> 23000.500
|
||||
1 CHECK_RATE_CTRS(3, 2, 2) ok
|
||||
1 ADD_MILLISECS(99) --> 23000.599
|
||||
1 CHECK_RATE_CTRS(3, 2, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.600
|
||||
1 CHECK_RATE_CTRS(3, 3, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.601
|
||||
1 CHECK_RATE_CTRS(3, 3, 2) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.602
|
||||
1 CHECK_RATE_CTRS(4, 3, 2) ok
|
||||
1 ADD_MILLISECS(98) --> 23000.700
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
T_defs: T_gran=100000usec T_round_threshold=0usec T_forget_sum=0usec
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
1 ADD_MILLISECS(100) --> 23000.800
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
1 ADD_MILLISECS(2) --> 23000.802
|
||||
1 CHECK_RATE_CTRS(4, 3, 3) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.803
|
||||
1 CHECK_RATE_CTRS(5, 3, 3) ok
|
||||
1 ADD_MILLISECS(46) --> 23000.849
|
||||
1 CHECK_RATE_CTRS(5, 3, 3) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.850
|
||||
1 CHECK_RATE_CTRS(5, 4, 3) ok
|
||||
1 ADD_MILLISECS(50) --> 23000.900
|
||||
1 ADD_MILLISECS(2) --> 23000.902
|
||||
1 CHECK_RATE_CTRS(5, 4, 3) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.903
|
||||
1 CHECK_RATE_CTRS(6, 4, 3) ok
|
||||
1 ADD_MILLISECS(46) --> 23000.949
|
||||
1 CHECK_RATE_CTRS(6, 4, 3) ok
|
||||
1 ADD_MILLISECS(1) --> 23000.950
|
||||
1 CHECK_RATE_CTRS(6, 5, 3) ok
|
Loading…
Reference in New Issue