lib: os: mpsc_pbuf: Add usage tracking
Add API to fetch current buffer usage. Add option to track maximum buffer usage and API to fetch that value. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
87f8b090ab
commit
5c8cc1aa8f
|
@ -58,6 +58,9 @@ extern "C" {
|
|||
*/
|
||||
#define MPSC_PBUF_MODE_OVERWRITE BIT(1)
|
||||
|
||||
/** @brief Flag indicating that maximum buffer usage is tracked. */
|
||||
#define MPSC_PBUF_MAX_UTILIZATION BIT(2)
|
||||
|
||||
/**@} */
|
||||
|
||||
/* Forward declaration */
|
||||
|
@ -112,6 +115,9 @@ struct mpsc_pbuf_buffer {
|
|||
/* Buffer size in 32 bit words. */
|
||||
uint32_t size;
|
||||
|
||||
/* Store max buffer usage. */
|
||||
uint32_t max_usage;
|
||||
|
||||
struct k_sem sem;
|
||||
};
|
||||
|
||||
|
@ -237,6 +243,24 @@ void mpsc_pbuf_free(struct mpsc_pbuf_buffer *buffer,
|
|||
*/
|
||||
bool mpsc_pbuf_is_pending(struct mpsc_pbuf_buffer *buffer);
|
||||
|
||||
/** @brief Get current memory utilization.
|
||||
*
|
||||
* @param[in, out] buffer Buffer.
|
||||
* @param[out] size Buffer size in bytes.
|
||||
* @param[out] now Current buffer usage in bytes.
|
||||
*/
|
||||
void mpsc_pbuf_get_utilization(struct mpsc_pbuf_buffer *buffer,
|
||||
uint32_t *size, uint32_t *now);
|
||||
|
||||
/** @brief Get maximum memory utilization.
|
||||
*
|
||||
* @param[in, out] buffer Buffer.
|
||||
* @param[out] max Maximum buffer usage in bytes.
|
||||
*
|
||||
* retval 0 if utilization data collected successfully.
|
||||
* retval -ENOTSUP if Collecting utilization data is not supported.
|
||||
*/
|
||||
int mpsc_pbuf_get_max_utilization(struct mpsc_pbuf_buffer *buffer, uint32_t *max);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -35,6 +35,7 @@ void mpsc_pbuf_init(struct mpsc_pbuf_buffer *buffer,
|
|||
buffer->notify_drop = cfg->notify_drop;
|
||||
buffer->buf = cfg->buf;
|
||||
buffer->size = cfg->size;
|
||||
buffer->max_usage = 0;
|
||||
buffer->flags = cfg->flags;
|
||||
|
||||
if (is_power_of_two(buffer->size)) {
|
||||
|
@ -74,6 +75,26 @@ static inline bool available(struct mpsc_pbuf_buffer *buffer, uint32_t *res)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline uint32_t get_usage(struct mpsc_pbuf_buffer *buffer)
|
||||
{
|
||||
uint32_t f;
|
||||
|
||||
if (free_space(buffer, &f)) {
|
||||
f += (buffer->rd_idx - 1);
|
||||
}
|
||||
|
||||
return buffer->size - 1 - f;
|
||||
}
|
||||
|
||||
static inline void max_utilization_update(struct mpsc_pbuf_buffer *buffer)
|
||||
{
|
||||
if (!(buffer->flags & MPSC_PBUF_MAX_UTILIZATION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->max_usage = MAX(buffer->max_usage, get_usage(buffer));
|
||||
}
|
||||
|
||||
static inline bool is_valid(union mpsc_pbuf_generic *item)
|
||||
{
|
||||
return item->hdr.valid;
|
||||
|
@ -190,6 +211,7 @@ void mpsc_pbuf_put_word(struct mpsc_pbuf_buffer *buffer,
|
|||
buffer->tmp_wr_idx = idx_inc(buffer,
|
||||
buffer->tmp_wr_idx, 1);
|
||||
buffer->wr_idx = idx_inc(buffer, buffer->wr_idx, 1);
|
||||
max_utilization_update(buffer);
|
||||
} else {
|
||||
bool user_drop = buffer->flags & MPSC_PBUF_MODE_OVERWRITE;
|
||||
|
||||
|
@ -288,6 +310,7 @@ void mpsc_pbuf_commit(struct mpsc_pbuf_buffer *buffer,
|
|||
|
||||
item->hdr.valid = 1;
|
||||
buffer->wr_idx = idx_inc(buffer, buffer->wr_idx, wlen);
|
||||
max_utilization_update(buffer);
|
||||
k_spin_unlock(&buffer->lock, key);
|
||||
MPSC_PBUF_DBG(buffer, "committed %p ", item);
|
||||
}
|
||||
|
@ -320,6 +343,7 @@ void mpsc_pbuf_put_word_ext(struct mpsc_pbuf_buffer *buffer,
|
|||
buffer->tmp_wr_idx =
|
||||
idx_inc(buffer, buffer->tmp_wr_idx, l);
|
||||
buffer->wr_idx = idx_inc(buffer, buffer->wr_idx, l);
|
||||
max_utilization_update(buffer);
|
||||
} else if (wrap) {
|
||||
add_skip_item(buffer, free_wlen);
|
||||
cont = true;
|
||||
|
@ -363,6 +387,7 @@ void mpsc_pbuf_put_data(struct mpsc_pbuf_buffer *buffer, const uint32_t *data,
|
|||
buffer->tmp_wr_idx =
|
||||
idx_inc(buffer, buffer->tmp_wr_idx, wlen);
|
||||
buffer->wr_idx = idx_inc(buffer, buffer->wr_idx, wlen);
|
||||
max_utilization_update(buffer);
|
||||
} else if (wrap) {
|
||||
add_skip_item(buffer, free_wlen);
|
||||
cont = true;
|
||||
|
@ -460,3 +485,22 @@ bool mpsc_pbuf_is_pending(struct mpsc_pbuf_buffer *buffer)
|
|||
|
||||
return a ? true : false;
|
||||
}
|
||||
|
||||
void mpsc_pbuf_get_utilization(struct mpsc_pbuf_buffer *buffer,
|
||||
uint32_t *size, uint32_t *now)
|
||||
{
|
||||
/* One byte is left for full/empty distinction. */
|
||||
*size = (buffer->size - 1) * sizeof(int);
|
||||
*now = get_usage(buffer) * sizeof(int);
|
||||
}
|
||||
|
||||
int mpsc_pbuf_get_max_utilization(struct mpsc_pbuf_buffer *buffer, uint32_t *max)
|
||||
{
|
||||
|
||||
if (!(buffer->flags & MPSC_PBUF_MAX_UTILIZATION)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
*max = buffer->max_usage * sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue