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 <chrisfriedt@gmail.com>
This commit is contained in:
Christopher Friedt 2020-05-06 18:43:58 -04:00 committed by Carles Cufí
commit 3315f8fecf
2 changed files with 94 additions and 0 deletions

View file

@ -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);
/** @} */
/**

View file

@ -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 <syscalls/k_pipe_read_avail_mrsh.c>
#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 <syscalls/k_pipe_write_avail_mrsh.c>
#endif