From: Gerhard Sittig Date: Tue, 12 Oct 2021 14:34:32 +0000 (+0200) Subject: sw_limits: extend API to "get remaining counts" before the limit is reached X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=5aba93c3bd06502c3bd732d478f3b93023fcc1df;p=libsigrok.git sw_limits: extend API to "get remaining counts" before the limit is reached The current sw_limits API provides routines which interface nicely with config get/set and Glib data types, and which check whether a limit was exceeded after previous submission of samples (summary result). Device drivers may want to check _before_ a limit was reached, some may want to cap to-get-submitted sample data such that a limit gets reached but is not exceeded. This need becomes more obvious when devices with efficient hardware compression "severely overshoot" the user specified limits when the check is only done late after submission of another chunk of data which results from uncompression. Introduce an API routine which gets the remaining count until the limit is reached. Phrase the implementation for cheapest cost of execution. These routines may execute in tight loops in acquisition code paths. --- diff --git a/src/libsigrok-internal.h b/src/libsigrok-internal.h index 1960264c..7a5b717d 100644 --- a/src/libsigrok-internal.h +++ b/src/libsigrok-internal.h @@ -2671,6 +2671,9 @@ SR_PRIV int sr_sw_limits_config_set(struct sr_sw_limits *limits, uint32_t key, GVariant *data); SR_PRIV void sr_sw_limits_acquisition_start(struct sr_sw_limits *limits); SR_PRIV gboolean sr_sw_limits_check(struct sr_sw_limits *limits); +SR_PRIV int sr_sw_limits_get_remain(const struct sr_sw_limits *limits, + uint64_t *samples, uint64_t *frames, uint64_t *msecs, + gboolean *exceeded); SR_PRIV void sr_sw_limits_update_samples_read(struct sr_sw_limits *limits, uint64_t samples_read); SR_PRIV void sr_sw_limits_update_frames_read(struct sr_sw_limits *limits, diff --git a/src/sw_limits.c b/src/sw_limits.c index 55ca79da..1a9c4c58 100644 --- a/src/sw_limits.c +++ b/src/sw_limits.c @@ -165,6 +165,87 @@ SR_PRIV gboolean sr_sw_limits_check(struct sr_sw_limits *limits) return FALSE; } +/** + * Get remaining counts until software limits are reached. + * + * This routine fills in those C language variables which callers + * requested, and provides the remaining value until a specified limit + * would be reached. + * + * The @ref sr_sw_limits_config_get() routine is suitable for rare + * configuration calls and interfaces nicely with Glib data types. The + * @ref sr_sw_limits_check() routine only provides a weak "exceeded" + * result. This @ref sr_sw_limits_get_remain() routine is suitable for + * additional checks and more eager limits enforcement in (potentially + * tight) acquisition code paths. Hardware compression may result in + * rather large "overshoots" when checks are done only late. + * + * @param[in] limits software limit instance + * @param[out] samples remaining samples count until the limit is reached + * @param[out] frames remaining frames count until the limit is reached + * @param[out] msecs remaining milliseconds until the limit is reached + * + * @return SR_ERR_* upon error, SR_OK otherwise + */ +SR_PRIV int sr_sw_limits_get_remain(const struct sr_sw_limits *limits, + uint64_t *samples, uint64_t *frames, uint64_t *msecs, + gboolean *exceeded) +{ + + if (!limits) + return SR_ERR_ARG; + + if (exceeded) + *exceeded = FALSE; + + if (samples) do { + *samples = 0; + if (!limits->limit_samples) + break; + if (limits->samples_read >= limits->limit_samples) { + if (exceeded) + *exceeded = TRUE; + break; + } + *samples = limits->limit_samples - limits->samples_read; + } while (0); + + if (frames) do { + *frames = 0; + if (!limits->limit_frames) + break; + if (limits->frames_read >= limits->limit_frames) { + if (exceeded) + *exceeded = TRUE; + break; + } + *frames = limits->limit_frames - limits->frames_read; + } while (0); + + if (msecs) do { + guint64 now, elapsed, remain; + + *msecs = 0; + if (!limits->limit_msec) + break; + if (!limits->start_time) + break; + now = g_get_monotonic_time(); + if (now < limits->start_time) + break; + elapsed = now - limits->start_time; + if (elapsed >= limits->limit_msec) { + if (exceeded) + *exceeded = TRUE; + break; + } + remain = limits->limit_msec - elapsed; + *msecs = remain / 1000; + } while (0); + + return SR_OK; +} + /** * Update the amount of samples that have been read *