Browse Source

kernel: Rewrite k_pipe_* API

The `k_pipe_*` API has been reworked to provide a more consistent and
intuitive interface. The new API aims to provide a simple to use byte
stream interface that is more in line with the POSIX pipe API.
The previous API has been deprecated and will be removed in a future
release.

Signed-off-by: Måns Ansgariusson <Mansgariusson@gmail.com>
pull/84177/head
Måns Ansgariusson 7 months ago committed by Benjamin Cabé
parent
commit
c8a2a080ac
  1. 159
      include/zephyr/kernel.h
  2. 11
      include/zephyr/sys/ring_buffer.h
  3. 4
      kernel/CMakeLists.txt
  4. 5
      kernel/Kconfig
  5. 2
      kernel/Kconfig.obj_core
  6. 251
      kernel/pipe.c
  7. 11
      kernel/pipes.c

159
include/zephyr/kernel.h

@ -22,6 +22,7 @@
#include <zephyr/tracing/tracing_macros.h> #include <zephyr/tracing/tracing_macros.h>
#include <zephyr/sys/mem_stats.h> #include <zephyr/sys/mem_stats.h>
#include <zephyr/sys/iterable_sections.h> #include <zephyr/sys/iterable_sections.h>
#include <zephyr/sys/ring_buffer.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -4991,6 +4992,18 @@ void k_mbox_data_get(struct k_mbox_msg *rx_msg, void *buffer);
* @{ * @{
*/ */
/**
* @brief initialize a pipe
*
* This routine initializes a pipe object, prior to its first use.
*
* @param pipe Address of the pipe.
* @param buffer Address of the pipe's buffer.
* @param buffer_size Size of the pipe's buffer.
*/
__syscall void k_pipe_init(struct k_pipe *pipe, uint8_t *buffer, size_t buffer_size);
#ifdef CONFIG_PIPES
/** Pipe Structure */ /** Pipe Structure */
struct k_pipe { struct k_pipe {
unsigned char *buffer; /**< Pipe buffer: may be NULL */ unsigned char *buffer; /**< Pipe buffer: may be NULL */
@ -5061,19 +5074,7 @@ struct k_pipe {
Z_PIPE_INITIALIZER(name, _k_pipe_buf_##name, pipe_buffer_size) Z_PIPE_INITIALIZER(name, _k_pipe_buf_##name, pipe_buffer_size)
/** /**
* @brief Initialize a pipe. * @deprecated Dynamic allocation of pipe buffers will be removed in the new k_pipe API.
*
* This routine initializes a pipe object, prior to its first use.
*
* @param pipe Address of the pipe.
* @param buffer Address of the pipe's ring buffer, or NULL if no ring buffer
* is used.
* @param size Size of the pipe's ring buffer (in bytes), or zero if no ring
* buffer is used.
*/
void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size);
/**
* @brief Release a pipe's allocated buffer * @brief Release a pipe's allocated buffer
* *
* If a pipe object was given a dynamically allocated buffer via * If a pipe object was given a dynamically allocated buffer via
@ -5084,9 +5085,10 @@ void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size);
* @retval 0 on success * @retval 0 on success
* @retval -EAGAIN nothing to cleanup * @retval -EAGAIN nothing to cleanup
*/ */
int k_pipe_cleanup(struct k_pipe *pipe); __deprecated int k_pipe_cleanup(struct k_pipe *pipe);
/** /**
* @deprecated Dynamic allocation of pipe buffers will be removed in the new k_pipe API.
* @brief Initialize a pipe and allocate a buffer for it * @brief Initialize a pipe and allocate a buffer for it
* *
* Storage for the buffer region will be allocated from the calling thread's * Storage for the buffer region will be allocated from the calling thread's
@ -5101,9 +5103,10 @@ int k_pipe_cleanup(struct k_pipe *pipe);
* @retval 0 on success * @retval 0 on success
* @retval -ENOMEM if memory couldn't be allocated * @retval -ENOMEM if memory couldn't be allocated
*/ */
__syscall int k_pipe_alloc_init(struct k_pipe *pipe, size_t size); __deprecated __syscall int k_pipe_alloc_init(struct k_pipe *pipe, size_t size);
/** /**
* @deprecated k_pipe_put() is replaced by k_pipe_write(...) in the new k_pipe API.
* @brief Write data to a pipe. * @brief Write data to a pipe.
* *
* This routine writes up to @a bytes_to_write bytes of data to @a pipe. * This routine writes up to @a bytes_to_write bytes of data to @a pipe.
@ -5121,11 +5124,12 @@ __syscall int k_pipe_alloc_init(struct k_pipe *pipe, size_t size);
* @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer * @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer
* minus one data bytes were written. * minus one data bytes were written.
*/ */
__syscall int k_pipe_put(struct k_pipe *pipe, const void *data, __deprecated __syscall int k_pipe_put(struct k_pipe *pipe, const void *data,
size_t bytes_to_write, size_t *bytes_written, size_t bytes_to_write, size_t *bytes_written,
size_t min_xfer, k_timeout_t timeout); size_t min_xfer, k_timeout_t timeout);
/** /**
* @deprecated k_pipe_get() is replaced by k_pipe_read(...) in the new k_pipe API.
* @brief Read data from a pipe. * @brief Read data from a pipe.
* *
* This routine reads up to @a bytes_to_read bytes of data from @a pipe. * This routine reads up to @a bytes_to_read bytes of data from @a pipe.
@ -5144,11 +5148,12 @@ __syscall int k_pipe_put(struct k_pipe *pipe, const void *data,
* @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer * @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer
* minus one data bytes were read. * minus one data bytes were read.
*/ */
__syscall int k_pipe_get(struct k_pipe *pipe, void *data, __deprecated __syscall int k_pipe_get(struct k_pipe *pipe, void *data,
size_t bytes_to_read, size_t *bytes_read, size_t bytes_to_read, size_t *bytes_read,
size_t min_xfer, k_timeout_t timeout); size_t min_xfer, k_timeout_t timeout);
/** /**
* @deprecated k_pipe_read_avail() will be removed in the new k_pipe API.
* @brief Query the number of bytes that may be read from @a pipe. * @brief Query the number of bytes that may be read from @a pipe.
* *
* @param pipe Address of the pipe. * @param pipe Address of the pipe.
@ -5156,9 +5161,10 @@ __syscall int k_pipe_get(struct k_pipe *pipe, void *data,
* @retval a number n such that 0 <= n <= @ref k_pipe.size; the * @retval a number n such that 0 <= n <= @ref k_pipe.size; the
* result is zero for unbuffered pipes. * result is zero for unbuffered pipes.
*/ */
__syscall size_t k_pipe_read_avail(struct k_pipe *pipe); __deprecated __syscall size_t k_pipe_read_avail(struct k_pipe *pipe);
/** /**
* @deprecated k_pipe_write_avail() will be removed in the new k_pipe API.
* @brief Query the number of bytes that may be written to @a pipe * @brief Query the number of bytes that may be written to @a pipe
* *
* @param pipe Address of the pipe. * @param pipe Address of the pipe.
@ -5166,9 +5172,10 @@ __syscall size_t k_pipe_read_avail(struct k_pipe *pipe);
* @retval a number n such that 0 <= n <= @ref k_pipe.size; the * @retval a number n such that 0 <= n <= @ref k_pipe.size; the
* result is zero for unbuffered pipes. * result is zero for unbuffered pipes.
*/ */
__syscall size_t k_pipe_write_avail(struct k_pipe *pipe); __deprecated __syscall size_t k_pipe_write_avail(struct k_pipe *pipe);
/** /**
* @deprecated k_pipe_flush() will be removed in the new k_pipe API.
* @brief Flush the pipe of write data * @brief Flush the pipe of write data
* *
* This routine flushes the pipe. Flushing the pipe is equivalent to reading * This routine flushes the pipe. Flushing the pipe is equivalent to reading
@ -5178,9 +5185,10 @@ __syscall size_t k_pipe_write_avail(struct k_pipe *pipe);
* *
* @param pipe Address of the pipe. * @param pipe Address of the pipe.
*/ */
__syscall void k_pipe_flush(struct k_pipe *pipe); __deprecated __syscall void k_pipe_flush(struct k_pipe *pipe);
/** /**
* @deprecated k_pipe_buffer_flush will be removed in the new k_pipe API.
* @brief Flush the pipe's internal buffer * @brief Flush the pipe's internal buffer
* *
* This routine flushes the pipe's internal buffer. This is equivalent to * This routine flushes the pipe's internal buffer. This is equivalent to
@ -5191,14 +5199,121 @@ __syscall void k_pipe_flush(struct k_pipe *pipe);
* *
* @param pipe Address of the pipe. * @param pipe Address of the pipe.
*/ */
__syscall void k_pipe_buffer_flush(struct k_pipe *pipe); __deprecated __syscall void k_pipe_buffer_flush(struct k_pipe *pipe);
/** @} */ #else /* CONFIG_PIPES */
enum pipe_flags {
PIPE_FLAG_OPEN = BIT(0),
PIPE_FLAG_RESET = BIT(1),
};
struct k_pipe {
size_t waiting;
struct ring_buf buf;
struct k_spinlock lock;
_wait_q_t data;
_wait_q_t space;
uint8_t flags;
};
/** /**
* @cond INTERNAL_HIDDEN * @cond INTERNAL_HIDDEN
*/ */
#define Z_PIPE_INITIALIZER(obj, pipe_buffer, pipe_buffer_size) \
{ \
.buf = RING_BUF_INIT(pipe_buffer, pipe_buffer_size), \
.data = Z_WAIT_Q_INIT(&obj.data), \
.space = Z_WAIT_Q_INIT(&obj.space), \
.flags = PIPE_FLAG_OPEN, \
.waiting = 0, \
}
/**
* INTERNAL_HIDDEN @endcond
*/
/**
* @brief Statically define and initialize a pipe.
*
* The pipe can be accessed outside the module where it is defined using:
*
* @code extern struct k_pipe <name>; @endcode
*
* @param name Name of the pipe.
* @param pipe_buffer_size Size of the pipe's ring buffer (in bytes).
* @param pipe_align Alignment of the pipe's ring buffer (power of 2).
*
*/
#define K_PIPE_DEFINE(name, pipe_buffer_size, pipe_align) \
static unsigned char __noinit __aligned(pipe_align) \
_k_pipe_buf_##name[pipe_buffer_size]; \
STRUCT_SECTION_ITERABLE(k_pipe, name) = \
Z_PIPE_INITIALIZER(name, _k_pipe_buf_##name, pipe_buffer_size)
/**
* @brief Write data to a pipe
*
* This routine writes up to @a len bytes of data to @a pipe.
* If the pipe is full, the routine will block until the data can be written or the timeout expires.
*
* @param pipe Address of the pipe.
* @param data Address of data to write.
* @param len Size of data (in bytes).
* @param timeout Waiting period to wait for the data to be written.
*
* @retval number of bytes written on success
* @retval -EAGAIN if no data could be written before the timeout expired
* @retval -ECANCELED if the write was interrupted by k_pipe_reset(..)
* @retval -EPIPE if the pipe was closed
*/
__syscall int k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len,
k_timeout_t timeout);
/**
* @brief Read data from a pipe
* This routine reads up to @a len bytes of data from @a pipe.
* If the pipe is empty, the routine will block until the data can be read or the timeout expires.
*
* @param pipe Address of the pipe.
* @param data Address to place the data read from pipe.
* @param len Requested number of bytes to read.
* @param timeout Waiting period to wait for the data to be read.
*
* @retval number of bytes read on success
* @retval -EAGAIN if no data could be read before the timeout expired
* @retval -ECANCELED if the read was interrupted by k_pipe_reset(..)
* @retval -EPIPE if the pipe was closed
*/
__syscall int k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len,
k_timeout_t timeout);
/**
* @brief Reset a pipe
* This routine resets the pipe, discarding any unread data and unblocking any threads waiting to
* write or read, causing the waiting threads to return with -ECANCELED. Calling k_pipe_read(..) or
* k_pipe_write(..) when the pipe is resetting but not yet reset will return -ECANCELED.
* The pipe is left open after a reset and can be used as normal.
*
* @param pipe Address of the pipe.
*/
__syscall void k_pipe_reset(struct k_pipe *pipe);
/**
* @brief Close a pipe
*
* This routine closes a pipe. Any threads that were blocked on the pipe
* will be unblocked and receive an error code.
*
* @param pipe Address of the pipe.
*/
__syscall void k_pipe_close(struct k_pipe *pipe);
#endif /* CONFIG_PIPES */
/** @} */
/**
* @cond INTERNAL_HIDDEN
*/
struct k_mem_slab_info { struct k_mem_slab_info {
uint32_t num_blocks; uint32_t num_blocks;
size_t block_size; size_t block_size;

11
include/zephyr/sys/ring_buffer.h

@ -7,7 +7,6 @@
#ifndef ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_ #ifndef ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_
#define ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_ #define ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h> #include <zephyr/sys/util.h>
#include <errno.h> #include <errno.h>
@ -62,6 +61,11 @@ static inline void ring_buf_internal_reset(struct ring_buf *buf, int32_t value)
buf->get_head = buf->get_tail = buf->get_base = value; buf->get_head = buf->get_tail = buf->get_base = value;
} }
#define RING_BUF_INIT(buf, size8) \
{ \
.buffer = buf, \
.size = size8, \
}
/** /**
* @brief Define and initialize a ring buffer for byte data. * @brief Define and initialize a ring buffer for byte data.
* *
@ -80,10 +84,7 @@ static inline void ring_buf_internal_reset(struct ring_buf *buf, int32_t value)
BUILD_ASSERT(size8 < RING_BUFFER_MAX_SIZE,\ BUILD_ASSERT(size8 < RING_BUFFER_MAX_SIZE,\
RING_BUFFER_SIZE_ASSERT_MSG); \ RING_BUFFER_SIZE_ASSERT_MSG); \
static uint8_t __noinit _ring_buffer_data_##name[size8]; \ static uint8_t __noinit _ring_buffer_data_##name[size8]; \
struct ring_buf name = { \ struct ring_buf name = RING_BUF_INIT(_ring_buffer_data_##name, size8)
.buffer = _ring_buffer_data_##name, \
.size = size8 \
}
/** /**
* @brief Define and initialize an "item based" ring buffer. * @brief Define and initialize an "item based" ring buffer.

4
kernel/CMakeLists.txt

@ -84,6 +84,10 @@ list(APPEND kernel_files
thread.c thread.c
sched.c sched.c
) )
# FIXME: Once the prior pipe implementation is removed, this should be included in the above list
if(NOT CONFIG_PIPES)
list(APPEND kernel_files pipe.c)
endif() # NOT CONFIG_PIPES
if(CONFIG_SMP) if(CONFIG_SMP)
list(APPEND kernel_files list(APPEND kernel_files
smp.c smp.c

5
kernel/Kconfig

@ -12,6 +12,7 @@ source "subsys/logging/Kconfig.template.log_config"
config MULTITHREADING config MULTITHREADING
bool "Multi-threading" if ARCH_HAS_SINGLE_THREAD_SUPPORT bool "Multi-threading" if ARCH_HAS_SINGLE_THREAD_SUPPORT
default y default y
select RING_BUFFER
help help
If disabled, only the main thread is available, so a main() function If disabled, only the main thread is available, so a main() function
must be provided. Interrupts are available. Kernel objects will most must be provided. Interrupts are available. Kernel objects will most
@ -713,6 +714,7 @@ config EVENTS
config PIPES config PIPES
bool "Pipe objects" bool "Pipe objects"
select DEPRECATED
help help
This option enables kernel pipes. A pipe is a kernel object that This option enables kernel pipes. A pipe is a kernel object that
allows a thread to send a byte stream to another thread. Pipes can allows a thread to send a byte stream to another thread. Pipes can
@ -720,6 +722,9 @@ config PIPES
Note that setting this option slightly increases the size of the Note that setting this option slightly increases the size of the
thread structure. thread structure.
This Kconfig is deprecated and will be removed, by disabling this
kconfig another implementation of k_pipe will be available when
CONFIG_MULTITHREADING is enabled.
config KERNEL_MEM_POOL config KERNEL_MEM_POOL
bool "Use Kernel Memory Pool" bool "Use Kernel Memory Pool"

2
kernel/Kconfig.obj_core

@ -77,7 +77,7 @@ config OBJ_CORE_SEM
config OBJ_CORE_PIPE config OBJ_CORE_PIPE
bool "Integrate pipe into object core framework" bool "Integrate pipe into object core framework"
default y if PIPES default y
help help
When enabled, this option integrates pipes into the object core When enabled, this option integrates pipes into the object core
framework. framework.

251
kernel/pipe.c

@ -0,0 +1,251 @@
/*
* Copyright (c) 2024 Måns Ansgariusson <mansgariusson@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/internal/syscall_handler.h>
#include <ksched.h>
#include <kthread.h>
#include <wait_q.h>
static inline bool pipe_closed(struct k_pipe *pipe)
{
return (pipe->flags & PIPE_FLAG_OPEN) == 0;
}
static inline bool pipe_resetting(struct k_pipe *pipe)
{
return (pipe->flags & PIPE_FLAG_RESET) != 0;
}
static inline bool pipe_full(struct k_pipe *pipe)
{
return ring_buf_space_get(&pipe->buf) == 0;
}
static inline bool pipe_empty(struct k_pipe *pipe)
{
return ring_buf_is_empty(&pipe->buf);
}
static inline int wait_for(_wait_q_t *waitq, struct k_pipe *pipe, k_spinlock_key_t *key,
k_timepoint_t time_limit)
{
k_timeout_t timeout = sys_timepoint_timeout(time_limit);
if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
return -EAGAIN;
}
pipe->waiting++;
z_pend_curr(&pipe->lock, *key, waitq, timeout);
*key = k_spin_lock(&pipe->lock);
pipe->waiting--;
if (unlikely(pipe_closed(pipe))) {
return -EPIPE;
} else if (unlikely(pipe_resetting(pipe))) {
if (pipe->waiting == 0) {
pipe->flags &= ~PIPE_FLAG_RESET;
}
return -ECANCELED;
} else if (sys_timepoint_expired(time_limit)) {
return -EAGAIN;
}
return 0;
}
static void notify_waiter(_wait_q_t *waitq)
{
struct k_thread *thread_to_unblock = z_unpend_first_thread(waitq);
if (likely(thread_to_unblock != NULL)) {
z_ready_thread(thread_to_unblock);
}
}
void z_impl_k_pipe_init(struct k_pipe *pipe, uint8_t *buffer, size_t buffer_size)
{
ring_buf_init(&pipe->buf, buffer_size, buffer);
pipe->flags = PIPE_FLAG_OPEN;
pipe->waiting = 0;
pipe->lock = (struct k_spinlock){};
z_waitq_init(&pipe->data);
z_waitq_init(&pipe->space);
k_object_init(pipe);
}
int z_impl_k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len, k_timeout_t timeout)
{
int rc;
size_t written = 0;
k_spinlock_key_t key;
k_timepoint_t end = sys_timepoint_calc(timeout);
while (written < len) {
key = k_spin_lock(&pipe->lock);
if (unlikely(pipe_closed(pipe))) {
k_spin_unlock(&pipe->lock, key);
rc = -EPIPE;
goto exit;
} else if (unlikely(pipe_resetting(pipe))) {
k_spin_unlock(&pipe->lock, key);
rc = -ECANCELED;
goto exit;
} else if (pipe_full(pipe)) {
rc = wait_for(&pipe->space, pipe, &key, end);
if (rc == -EAGAIN) {
/* the timeout expired */
k_spin_unlock(&pipe->lock, key);
rc = written ? written : -EAGAIN;
goto exit;
} else if (unlikely(rc != 0)) {
/* The pipe was closed or reseted while waiting for space */
k_spin_unlock(&pipe->lock, key);
goto exit;
} else if (unlikely(pipe_full(pipe))) {
/* Timeout has not elapsed, the pipe is open and not resetting,
* we've been notified of available space, but the notified space
* was consumed by another thread before the calling thread.
*/
k_spin_unlock(&pipe->lock, key);
continue;
}
/* The timeout has not elapsed, we've been notified of
* available space, and the pipe is not full. Continue writing.
*/
}
rc = ring_buf_put(&pipe->buf, &data[written], len - written);
if (likely(rc != 0)) {
notify_waiter(&pipe->data);
}
k_spin_unlock(&pipe->lock, key);
written += rc;
}
rc = written;
exit:
return rc;
}
int z_impl_k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len, k_timeout_t timeout)
{
int rc;
size_t read = 0;
k_spinlock_key_t key;
k_timepoint_t end = sys_timepoint_calc(timeout);
while (read < len) {
key = k_spin_lock(&pipe->lock);
if (unlikely(pipe_resetting(pipe))) {
k_spin_unlock(&pipe->lock, key);
rc = -ECANCELED;
goto exit;
} else if (pipe_empty(pipe) && !pipe_closed(pipe)) {
rc = wait_for(&pipe->data, pipe, &key, end);
if (rc == -EAGAIN) {
/* The timeout elapsed */
k_spin_unlock(&pipe->lock, key);
rc = read ? read : -EAGAIN;
goto exit;
} else if (unlikely(rc == -ECANCELED)) {
/* The pipe is being rested. */
k_spin_unlock(&pipe->lock, key);
goto exit;
} else if (unlikely(rc == 0 && pipe_empty(pipe))) {
/* Timeout has not elapsed, we've been notified of available bytes
* but they have been consumed by another thread before the calling
* thread.
*/
k_spin_unlock(&pipe->lock, key);
continue;
}
/* The timeout has not elapsed, we've been notified of
* available bytes, and the pipe is not empty. Continue reading.
*/
}
if (unlikely(pipe_closed(pipe) && pipe_empty(pipe))) {
k_spin_unlock(&pipe->lock, key);
rc = read ? read : -EPIPE;
goto exit;
}
rc = ring_buf_get(&pipe->buf, &data[read], len - read);
if (likely(rc != 0)) {
notify_waiter(&pipe->space);
}
read += rc;
k_spin_unlock(&pipe->lock, key);
}
rc = read;
exit:
return rc;
}
void z_impl_k_pipe_reset(struct k_pipe *pipe)
{
K_SPINLOCK(&pipe->lock) {
ring_buf_reset(&pipe->buf);
if (likely(pipe->waiting != 0)) {
pipe->flags |= PIPE_FLAG_RESET;
z_unpend_all(&pipe->data);
z_unpend_all(&pipe->space);
}
}
}
void z_impl_k_pipe_close(struct k_pipe *pipe)
{
K_SPINLOCK(&pipe->lock) {
pipe->flags = 0;
z_unpend_all(&pipe->data);
z_unpend_all(&pipe->space);
}
}
#ifdef CONFIG_USERSPACE
void z_vrfy_k_pipe_init(struct k_pipe *pipe, uint8_t *buffer, size_t buffer_size)
{
K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, buffer_size));
z_impl_k_pipe_init(pipe, buffer, buffer_size);
}
#include <zephyr/syscalls/k_pipe_init_mrsh.c>
int z_vrfy_k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len, k_timeout_t timeout)
{
K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
K_OOPS(K_SYSCALL_MEMORY_WRITE(data, len));
return z_impl_k_pipe_read(pipe, data, len, timeout);
}
#include <zephyr/syscalls/k_pipe_read_mrsh.c>
int z_vrfy_k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len, k_timeout_t timeout)
{
K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
K_OOPS(K_SYSCALL_MEMORY_READ(data, len));
return z_impl_k_pipe_write(pipe, data, len, timeout);
}
#include <zephyr/syscalls/k_pipe_write_mrsh.c>
void z_vrfy_k_pipe_reset(struct k_pipe *pipe)
{
K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
z_impl_k_pipe_reset(pipe);
}
#include <zephyr/syscalls/k_pipe_reset_mrsh.c>
void z_vrfy_k_pipe_close(struct k_pipe *pipe)
{
K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE));
z_impl_k_pipe_close(pipe);
}
#include <zephyr/syscalls/k_pipe_close_mrsh.c>
#endif /* CONFIG_USERSPACE */

11
kernel/pipes.c

@ -36,7 +36,7 @@ static struct k_obj_type obj_type_pipe;
#endif /* CONFIG_OBJ_CORE_PIPE */ #endif /* CONFIG_OBJ_CORE_PIPE */
void k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size) void z_impl_k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size)
{ {
pipe->buffer = buffer; pipe->buffer = buffer;
pipe->size = size; pipe->size = size;
@ -87,6 +87,15 @@ int z_impl_k_pipe_alloc_init(struct k_pipe *pipe, size_t size)
} }
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
static inline void z_vrfy_k_pipe_init(struct k_pipe *pipe, unsigned char *buffer, size_t size)
{
K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(pipe, K_OBJ_PIPE));
K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, size));
z_impl_k_pipe_init(pipe, buffer, size);
}
#include <zephyr/syscalls/k_pipe_init_mrsh.c>
static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size)
{ {
K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(pipe, K_OBJ_PIPE)); K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(pipe, K_OBJ_PIPE));

Loading…
Cancel
Save