From 3315f8fecfbba8bf3f15be3874ffdaee486d2601 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Wed, 6 May 2020 18:43:58 -0400 Subject: [PATCH] kernel: pipe: read_avail / write_avail syscalls These helper functions may clarify how much data is available to read from or write to the circular buffer of a k_pipe. Fixes #25036 Signed-off-by: Christopher Friedt --- include/kernel.h | 20 +++++++++++++ kernel/pipes.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/include/kernel.h b/include/kernel.h index 9137666ff4b..e2de042322f 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -4430,6 +4430,26 @@ __syscall int k_pipe_get(struct k_pipe *pipe, void *data, extern void k_pipe_block_put(struct k_pipe *pipe, struct k_mem_block *block, size_t size, struct k_sem *sem); +/** + * @brief Query the number of bytes that may be read from @a pipe. + * + * @param pipe Address of the pipe. + * + * @retval a number n such that 0 <= n <= @ref k_pipe.size; the + * result is zero for unbuffered pipes. + */ +__syscall size_t k_pipe_read_avail(struct k_pipe *pipe); + +/** + * @brief Query the number of bytes that may be written to @a pipe + * + * @param pipe Address of the pipe. + * + * @retval a number n such that 0 <= n <= @ref k_pipe.size; the + * result is zero for unbuffered pipes. + */ +__syscall size_t k_pipe_write_avail(struct k_pipe *pipe); + /** @} */ /** diff --git a/kernel/pipes.c b/kernel/pipes.c index 8b83c41ca32..d28d7a33cf6 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -805,3 +805,77 @@ void k_pipe_block_put(struct k_pipe *pipe, struct k_mem_block *block, bytes_to_write, K_FOREVER); } #endif + +size_t z_impl_k_pipe_read_avail(struct k_pipe *pipe) +{ + size_t res; + k_spinlock_key_t key; + + /* Buffer and size are fixed. No need to spin. */ + if (pipe->buffer == NULL || pipe->size == 0) { + res = 0; + goto out; + } + + key = k_spin_lock(&pipe->lock); + + if (pipe->read_index == pipe->write_index) { + res = pipe->bytes_used; + } else if (pipe->read_index < pipe->write_index) { + res = pipe->write_index - pipe->read_index; + } else { + res = pipe->size - (pipe->read_index - pipe->write_index); + } + + k_spin_unlock(&pipe->lock, key); + +out: + return res; +} + +#ifdef CONFIG_USERSPACE +size_t z_vrfy_k_pipe_read_avail(struct k_pipe *pipe) +{ + Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + + return z_impl_k_pipe_read_avail(pipe); +} +#include +#endif + +size_t z_impl_k_pipe_write_avail(struct k_pipe *pipe) +{ + size_t res; + k_spinlock_key_t key; + + /* Buffer and size are fixed. No need to spin. */ + if (pipe->buffer == NULL || pipe->size == 0) { + res = 0; + goto out; + } + + key = k_spin_lock(&pipe->lock); + + if (pipe->write_index == pipe->read_index) { + res = pipe->size - pipe->bytes_used; + } else if (pipe->write_index < pipe->read_index) { + res = pipe->read_index - pipe->write_index; + } else { + res = pipe->size - (pipe->write_index - pipe->read_index); + } + + k_spin_unlock(&pipe->lock, key); + +out: + return res; +} + +#ifdef CONFIG_USERSPACE +size_t z_vrfy_k_pipe_write_avail(struct k_pipe *pipe) +{ + Z_OOPS(Z_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); + + return z_impl_k_pipe_write_avail(pipe); +} +#include +#endif