summaryrefslogtreecommitdiff
path: root/components/lwp/syscall/syscall_rt_ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'components/lwp/syscall/syscall_rt_ipc.c')
-rw-r--r--components/lwp/syscall/syscall_rt_ipc.c1415
1 files changed, 1415 insertions, 0 deletions
diff --git a/components/lwp/syscall/syscall_rt_ipc.c b/components/lwp/syscall/syscall_rt_ipc.c
new file mode 100644
index 0000000000..d103cb22cd
--- /dev/null
+++ b/components/lwp/syscall/syscall_rt_ipc.c
@@ -0,0 +1,1415 @@
+/*
+ * Copyright (c) 2006-2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "syscall_internal.h"
+
+/**
+ * @brief Creates a semaphore.
+ *
+ * This system call creates a new semaphore with the specified `name` and initializes
+ * its value. The semaphore is used for synchronizing access to shared resources in
+ * concurrent programming. The semaphore's behavior is defined by the value (`value`)
+ * and any flags (`flag`) that specify additional properties or settings.
+ *
+ * @param name The name of the semaphore. This is a string used to identify the semaphore
+ * in the system. The name must be unique if the system requires it for reference.
+ * @param value The initial value of the semaphore. The value typically represents the
+ * number of available resources or tokens. The semaphore will be initialized
+ * with this value.
+ * @param flag The flag that specifies the attributes or properties of the semaphore.
+ * Flags can be used to define various characteristics of the semaphore,
+ * such as whether it is binary or counting, whether it is shared, etc.
+ *
+ * @return On success, returns a handle or reference to the created semaphore. On failure,
+ * returns `NULL`.
+ *
+ * @note Semaphores are commonly used in multithreading and multiprocessing environments
+ * to synchronize access to shared resources and ensure proper order of execution.
+ * The behavior of the semaphore depends on its type and the system's implementation.
+ *
+ * @warning Ensure that the `name` is unique and appropriate for your system's naming
+ * conventions. Invalid values for `value` or `flag` may lead to errors in semaphore
+ * creation.
+ *
+ * @see sem_wait(), sem_post(), sem_destroy()
+ */
+rt_sem_t sys_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)
+{
+ int len = 0;
+ char *kname = RT_NULL;
+
+ len = lwp_user_strlen(name);
+ if (len <= 0)
+ {
+ return RT_NULL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_get_from_user(kname, (void *)name, len + 1) != (len + 1))
+ {
+ kmem_put(kname);
+ return RT_NULL;
+ }
+
+ rt_sem_t sem = rt_sem_create(kname, value, flag);
+ if (lwp_user_object_add(lwp_self(), (rt_object_t)sem) != 0)
+ {
+ rt_sem_delete(sem);
+ sem = NULL;
+ }
+
+ kmem_put(kname);
+
+ return sem;
+}
+
+/**
+ * @brief Deletes a semaphore and releases associated resources.
+ *
+ * This system call deletes an existing semaphore identified by the given handle `sem`.
+ * It releases any resources associated with the semaphore and ensures that it is no longer
+ * available for further synchronization operations. After deletion, the semaphore handle
+ * is invalid and should not be used.
+ *
+ * @param sem The semaphore handle to be deleted. This handle is obtained when the semaphore
+ * is created using `sys_sem_create()` or similar functions.
+ *
+ * @return On success, returns `0`. On failure, returns error code.
+ *
+ * @note Deleting a semaphore is a critical operation that should be performed only when
+ * the semaphore is no longer needed and no tasks are currently waiting or posting
+ * to it. Deleting a semaphore while it is still in use may lead to undefined behavior.
+ *
+ * @warning Ensure that no tasks are using or blocking on the semaphore before deleting it.
+ * Using a deleted semaphore will result in undefined behavior and potential system errors.
+ *
+ * @see sys_sem_create(), sem_wait(), sem_post()
+ */
+sysret_t sys_sem_delete(rt_sem_t sem)
+{
+ return lwp_user_object_delete(lwp_self(), (rt_object_t)sem);
+}
+
+/**
+ * @brief Attempts to take (acquire) a semaphore.
+ *
+ * This system call attempts to acquire a semaphore, blocking the calling task until the
+ * semaphore becomes available or the specified timeout expires. If the semaphore is already
+ * available, the calling task will immediately take it and proceed. If the semaphore is not
+ * available, the task will block until the semaphore becomes available or the timeout period
+ * has elapsed. The `time` parameter specifies the maximum amount of time the task will block
+ * waiting for the semaphore.
+ *
+ * @param sem The semaphore handle to be taken. This handle is obtained when the semaphore
+ * is created using `sys_sem_create()` or similar functions.
+ * @param time The maximum time to wait for the semaphore to become available. If the semaphore
+ * is not acquired within this time period, the function will return with an error.
+ * A value of `0` means no waiting (non-blocking), while a negative value may indicate
+ * an infinite wait, depending on the system's implementation.
+ *
+ * @return On success, returns `0` if the semaphore was successfully taken. On failure, returns error code.
+ *
+ * @warning Ensure that the semaphore handle is valid and has been properly created before
+ * calling this function. If the semaphore is deleted or invalid, the behavior of
+ * this function is undefined.
+ *
+ * @see sys_sem_create(), sys_sem_delete(), sem_post()
+ */
+sysret_t sys_sem_take(rt_sem_t sem, rt_int32_t time)
+{
+ return rt_sem_take_interruptible(sem, time);
+}
+
+/**
+ * @brief Releases a semaphore and wakes up any waiting tasks.
+ *
+ * This system call releases a semaphore, incrementing its value and allowing any tasks
+ * that are blocked (waiting) on the semaphore to proceed. If there are tasks waiting for
+ * the semaphore, one of them will be unblocked and allowed to take the semaphore.
+ * The release operation does not block the calling task, and it will return immediately.
+ *
+ * @param sem The semaphore handle to be released. This handle is obtained when the semaphore
+ * is created using `sys_sem_create()` or similar functions.
+ *
+ * @return On success, returns `0`. On failure, returns error code.
+ *
+ * @warning Ensure that the semaphore handle is valid before calling this function. If the semaphore
+ * is deleted or invalid, the behavior of this function is undefined.
+ *
+ * @see sys_sem_create(), sys_sem_delete(), sys_sem_take()
+ */
+sysret_t sys_sem_release(rt_sem_t sem)
+{
+ return rt_sem_release(sem);
+}
+
+/**
+ * @brief Creates a mutex.
+ *
+ * This system call creates a new mutex with the specified `name` and initializes it
+ * with the given `flag`. The mutex is used for synchronizing access to shared resources
+ * between tasks. Mutexes are typically used to ensure that only one task can access
+ * a critical section of code or a resource at a time. The `flag` parameter allows
+ * for setting certain properties of the mutex, such as whether it is recursive or whether
+ * it can be used by multiple tasks.
+ *
+ * @param name The name of the mutex. This is a string used to uniquely identify the mutex
+ * within the system. The name must be unique if the system requires it.
+ * @param flag The flag that specifies the attributes or properties of the mutex. Flags can
+ * define various mutex behaviors, such as whether the mutex is recursive (allows
+ * the same task to lock it multiple times) or whether it can be shared across
+ * different parts of the system.
+ *
+ * @return On success, returns a handle to the created mutex. On failure, returns `-RT_NULL`.
+ *
+ * @note Mutexes are typically used to prevent race conditions and ensure mutual exclusion
+ * when multiple tasks or threads are accessing shared resources.
+ *
+ * @warning Ensure that the `name` is unique and appropriate according to the system's
+ * naming conventions. Invalid values for `flag` or `name` may result in errors.
+ *
+ * @see sys_mutex_delete(), sys_mutex_lock(), sys_mutex_unlock()
+ */
+rt_mutex_t sys_mutex_create(const char *name, rt_uint8_t flag)
+{
+ int len = 0;
+ char *kname = RT_NULL;
+ rt_mutex_t mutex = RT_NULL;
+
+ len = lwp_user_strlen(name);
+ if (len <= 0)
+ {
+ return RT_NULL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_get_from_user(kname, (void *)name, len + 1) != (len + 1))
+ {
+ kmem_put(kname);
+ return RT_NULL;
+ }
+
+ mutex = rt_mutex_create(kname, flag);
+ if (mutex == RT_NULL)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_user_object_add(lwp_self(), (rt_object_t)mutex) != 0)
+ {
+ rt_mutex_delete(mutex);
+ mutex = RT_NULL;
+ }
+
+ kmem_put(kname);
+
+ return mutex;
+}
+
+/**
+ * @brief Deletes a mutex and releases associated resources.
+ *
+ * This system call deletes an existing mutex identified by the given handle `mutex`.
+ * It releases any resources associated with the mutex and ensures that it is no longer
+ * available for further synchronization operations. After deletion, the mutex handle
+ * becomes invalid and should not be used. This operation also ensures that no tasks
+ * can block or attempt to lock the mutex after it has been deleted.
+ *
+ * @param mutex The mutex handle to be deleted. This handle is obtained when the mutex
+ * is created using `sys_mutex_create()` or similar functions.
+ *
+ * @return On success, returns `0`. On failure, returns error code.
+ *
+ * @warning Ensure that the mutex handle is valid before calling this function. Deleting
+ * an already deleted or invalid mutex will result in undefined behavior.
+ *
+ * @see sys_mutex_create(), sys_mutex_lock(), sys_mutex_unlock()
+ */
+sysret_t sys_mutex_delete(rt_mutex_t mutex)
+{
+ return lwp_user_object_delete(lwp_self(), (rt_object_t)mutex);
+}
+
+/**
+ * @brief Attempts to acquire (lock) a mutex.
+ *
+ * This system call attempts to acquire a mutex, blocking the calling task until the
+ * mutex becomes available or the specified timeout expires. If the mutex is available,
+ * the calling task will immediately acquire it and proceed. If the mutex is already locked
+ * by another task, the calling task will block until the mutex is released or the timeout
+ * period elapses. The `time` parameter specifies the maximum amount of time the task will
+ * block while waiting for the mutex.
+ *
+ * @param mutex The mutex handle to be locked. This handle is obtained when the mutex is
+ * created using `sys_mutex_create()` or similar functions.
+ * @param time The maximum time to wait for the mutex to become available. If the mutex
+ * is not acquired within this time period, the function will return an error.
+ * A value of `0` means no waiting (non-blocking), while a negative value may
+ * indicate an infinite wait.
+ *
+ * @return On success, returns `0` if the mutex was successfully acquired. On failure, returns error code.
+ *
+ * @warning Ensure that the mutex handle is valid and has been properly created before
+ * calling this function. If the mutex is deleted or invalid, the behavior of
+ * this function is undefined.
+ *
+ * @see sys_mutex_create(), sys_mutex_delete(), sys_mutex_unlock()
+ */
+sysret_t sys_mutex_take(rt_mutex_t mutex, rt_int32_t time)
+{
+ return rt_mutex_take_interruptible(mutex, time);
+}
+
+/**
+ * @brief Releases (unlocks) a mutex.
+ *
+ * This system call releases a mutex that was previously acquired (locked) by the calling task.
+ * If any other task is waiting for the mutex, one of them will be unblocked and allowed to
+ * acquire the mutex. The release operation does not block the calling task, and it will return
+ * immediately after unlocking the mutex.
+ *
+ * @param mutex The mutex handle to be released. This handle is obtained when the mutex is
+ * created using `sys_mutex_create()` or similar functions.
+ *
+ * @return On success, returns `0`. On failure, returns error code.
+ *
+ * @warning Ensure that the mutex handle is valid before calling this function. Attempting
+ * to release a mutex that has not been locked or is already released can result
+ * in undefined behavior.
+ *
+ * @see sys_mutex_create(), sys_mutex_delete(), sys_mutex_take()
+ */
+sysret_t sys_mutex_release(rt_mutex_t mutex)
+{
+ return rt_mutex_release(mutex);
+}
+
+/**
+ * @brief Creates an event object for inter-thread or inter-process communication.
+ *
+ * @param name A string representing the name of the event. If `NULL`, the event will
+ * be created without a name. Named events can be identified and accessed
+ * globally if supported by the system.
+ * @param flag Specifies the behavior of the event. Possible values include:
+ * - `RT_IPC_FLAG_FIFO`: Events are handled in a first-in, first-out order.
+ * - `RT_IPC_FLAG_PRIO`: Events are handled in priority order.
+ *
+ * @return On success, returns a handle (`rt_event_t`) to the created event. On failure,
+ * returns `-RT_NULL` to indicate that the event could not be created.
+ *
+ * @note
+ * - The event object must be explicitly deleted using `sys_event_delete` when it is
+ * no longer needed to free system resources.
+ *
+ * @warning
+ * - Ensure that sufficient system resources (e.g., memory) are available to create
+ * the event. If resources are insufficient, the function will fail.
+ * - Named events can potentially lead to naming conflicts if multiple events with
+ * the same name are created. Use unique names to avoid such issues.
+ *
+ * @see sys_event_delete(), sys_event_send(), sys_event_recv()
+ */
+rt_event_t sys_event_create(const char *name, rt_uint8_t flag)
+{
+ int len = 0;
+ rt_event_t event = RT_NULL;
+ char *kname = RT_NULL;
+
+ len = lwp_user_strlen(name);
+ if (len <= 0)
+ {
+ return RT_NULL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_get_from_user(kname, (void *)name, len + 1) != (len + 1))
+ {
+ kmem_put(kname);
+ return RT_NULL;
+ }
+
+ event = rt_event_create(kname, flag);
+ if (lwp_user_object_add(lwp_self(), (rt_object_t)event) != 0)
+ {
+ rt_event_delete(event);
+ event = NULL;
+ }
+
+ kmem_put(kname);
+
+ return event;
+}
+
+/**
+ * @brief Deletes a system event object.
+ *
+ * This system call removes the specified system event object, releasing
+ * any resources associated with it. After deletion, the event object
+ * should not be used.
+ *
+ * @param[in] event The handle to the event object to be deleted.
+ * Must be a valid `rt_event_t` object.
+ *
+ * @return sysret_t Returns a status code indicating the result of the
+ * operation:
+ * - `0` if the operation was successful.
+ * - An appropriate error code otherwise.
+ *
+ * @note Ensure that the event is no longer being accessed by any
+ * threads or tasks before calling this function.
+ *
+ * @warning Deleting an event that is in use or invalid may lead to
+ * undefined behavior.
+ * @see sys_event_create(), sys_event_send(), sys_event_recv()
+ */
+sysret_t sys_event_delete(rt_event_t event)
+{
+ return lwp_user_object_delete(lwp_self(), (rt_object_t)event);
+}
+
+/**
+ * @brief Sends an event to the specified event object.
+ *
+ * This system call sends an event to the specified event object, setting
+ * the specified bits in the event object's set. The event can be used
+ * to signal other threads or tasks that a particular condition has
+ * occurred.
+ *
+ * @param[in] event The handle to the event object to which the event
+ * will be sent. Must be a valid `rt_event_t` object.
+ * @param[in] set The bits to set in the event object's set. The bits
+ * are specified as a bitmask, where each bit represents
+ * a different event condition.
+ *
+ * @return sysret_t Returns a status code indicating the result of the
+ * operation:
+ * - `0` if the operation was successful.
+ * - An appropriate error code otherwise.
+ *
+ * @note The event object must be created before sending events to it.
+ *
+ * @warning Ensure that the event object is valid and has been created
+ * before calling this function.
+ * @see sys_event_create(), sys_event_recv()
+ */
+sysret_t sys_event_send(rt_event_t event, rt_uint32_t set)
+{
+ return rt_event_send(event, set);
+}
+
+/**
+ * @brief Receives an event from the specified event object.
+ *
+ * This system call waits for an event to be received from the specified
+ * event object. The function blocks until the specified event bits are
+ * set in the event object's set or the specified timeout period has
+ * elapsed. If the event is received, the function returns the set of
+ * bits that were set in the event object.
+ *
+ * @param[in] event The handle to the event object from which the event
+ * will be received. Must be a valid `rt_event_t` object.
+ * @param[in] set The bits to wait for in the event object's set. The
+ * bits are specified as a bitmask, where each bit
+ * represents a different event condition.
+ * @param[in] opt The options for receiving the event. Possible values
+ * include:
+ * - `EV_EVENT_ANY`: Wait for any of the specified bits
+ * to be set.
+ * - `EV_EVENT_ALL`: Wait for all of the specified bits
+ * to be set.
+ * @param[in] timeout The maximum time to wait for the event to be
+ * received, in milliseconds. A value of `0` means
+ * no waiting (non-blocking), while a negative value
+ * may indicate an infinite wait.
+ * @param[out] recved A pointer to a variable that will receive the set
+ * of bits that were set in the event object. If the
+ * event is received, this variable will be updated
+ * with the set of bits.
+ *
+ * @return sysret_t Returns a status code indicating the result of the
+ * operation:
+ * - `0` if the operation was successful.
+ * - An appropriate error code otherwise.
+ *
+ * @note The event object must be created before receiving events from it.
+ *
+ * @warning Ensure that the event object is valid and has been created
+ * before calling this function.
+ * @see sys_event_create(), sys_event_send()
+ */
+sysret_t sys_event_recv(rt_event_t event,
+ rt_uint32_t set,
+ rt_uint8_t opt,
+ rt_int32_t timeout,
+ rt_uint32_t *recved)
+{
+ int ret = 0;
+ rt_uint32_t krecved;
+
+ if ((recved != NULL) && !lwp_user_accessable((void *)recved, sizeof(rt_uint32_t *)))
+ {
+ return -EFAULT;
+ }
+
+ ret = rt_event_recv(event, set, opt, timeout, &krecved);
+ if ((ret == RT_EOK) && recved)
+ {
+ lwp_put_to_user((void *)recved, &krecved, sizeof(rt_uint32_t *));
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Creates a mailbox for inter-thread or inter-process communication.
+ *
+ * This system call creates a mailbox object with the specified name and size.
+ * The mailbox is used to exchange messages between threads or tasks in a
+ * synchronized manner. The mailbox can be used to send and receive messages
+ * of a specified size.
+ *
+ * @param[in] name A string representing the name of the mailbox. If `NULL`,
+ * the mailbox will be created without a name. Named mailboxes
+ * can be identified and accessed globally if supported by the system.
+ * @param[in] size The size of the mailbox, which determines the maximum number
+ * of messages that can be stored in the mailbox at any given time.
+ * @param[in] flag The behavior of the mailbox. Possible values include:
+ * - `RT_IPC_FLAG_FIFO`: Messages are handled in a first-in, first-out order.
+ * - `RT_IPC_FLAG_PRIO`: Messages are handled in priority order.
+ *
+ * @return rt_mailbox_t Returns a handle to the created mailbox object.
+ * On failure, returns `-RT_NULL`.
+ *
+ * @note
+ * - The mailbox object must be explicitly deleted using `sys_mb_delete` when it is
+ * no longer needed to free system resources.
+ *
+ * @warning
+ * - Ensure that sufficient system resources (e.g., memory) are available to create
+ * the mailbox. If resources are insufficient, the function will fail.
+ * - Named mailboxes can potentially lead to naming conflicts if multiple mailboxes
+ * with the same name are created. Use unique names to avoid such issues.
+ *
+ * @see sys_mb_delete(), sys_mb_send(), sys_mb_recv()
+ */
+rt_mailbox_t sys_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
+{
+ int len = 0;
+ rt_mailbox_t mb = RT_NULL;
+ char *kname = RT_NULL;
+
+ len = lwp_user_strlen(name);
+ if (len <= 0)
+ {
+ return RT_NULL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_get_from_user(kname, (void *)name, len + 1) != (len + 1))
+ {
+ kmem_put(kname);
+ return RT_NULL;
+ }
+
+ mb = rt_mb_create(kname, size, flag);
+ if (lwp_user_object_add(lwp_self(), (rt_object_t)mb) != 0)
+ {
+ rt_mb_delete(mb);
+ mb = NULL;
+ }
+
+ kmem_put(kname);
+
+ return mb;
+}
+
+/**
+ * @brief Deletes a mailbox object.
+ *
+ * This system call deletes the specified mailbox object, releasing any resources
+ * associated with it. After deletion, the mailbox object should not be used.
+ *
+ * @param[in] mb The handle to the mailbox object to be deleted.
+ * Must be a valid `rt_mailbox_t` object.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0` if the operation was successful.
+ * - An appropriate error code otherwise.
+ *
+ * @note Ensure that the mailbox is no longer being accessed by any threads or tasks
+ * before calling this function.
+ *
+ * @warning Deleting a mailbox that is in use or invalid may lead to undefined behavior.
+ *
+ * @see sys_mb_create(), sys_mb_send(), sys_mb_recv()
+ */
+sysret_t sys_mb_delete(rt_mailbox_t mb)
+{
+ return lwp_user_object_delete(lwp_self(), (rt_object_t)mb);
+}
+
+/**
+ * @brief Sends a message to a mailbox object.
+ *
+ * This system call posts a message (a single value) to the specified mailbox.
+ * If the mailbox is full, the function will return an error code immediately without waiting time.
+ *
+ * @param[in] mb The handle to the mailbox object where the message
+ * will be sent. Must be a valid `rt_mailbox_t` object.
+ * @param[in] value The value to be sent to the mailbox. Typically, this
+ * is a pointer or an integral value that represents
+ * the message content.
+ *
+ * @return sysret_t Returns a status code indicating the result of the
+ * operation:
+ * - `0` if the message was successfully sent.
+ * - `-RT_EFULL` if the mailbox is full.
+ * - An appropriate error code for other failures.
+ *
+ * @note Ensure the mailbox has been properly initialized before calling
+ * this function. Sending messages to an uninitialized or invalid
+ * mailbox may result in undefined behavior.
+ *
+ * @warning If the mailbox is full and the function blocks, ensure
+ * proper handling to avoid potential deadlocks.
+ *
+ * @see sys_mb_create(), sys_mb_recv(), sys_mb_send_wait()
+ */
+sysret_t sys_mb_send(rt_mailbox_t mb, rt_ubase_t value)
+{
+ return rt_mb_send(mb, value);
+}
+
+/**
+ * @brief Sends a message to a mailbox object with a timeout.
+ *
+ * This system call attempts to post a message (a single value) to the specified mailbox.
+ * If the mailbox is full, the function will wait for a specified timeout period
+ * for space to become available. If the timeout expires before the message is sent,
+ * the function returns an error.
+ *
+ * @param[in] mb The handle to the mailbox object where the message
+ * will be sent. Must be a valid `rt_mailbox_t` object.
+ * @param[in] value The value to be sent to the mailbox. Typically, this
+ * is a pointer or an integral value representing the
+ * message content.
+ * @param[in] timeout The maximum time to wait for space to become available
+ * in the mailbox, in milliseconds.
+ * - a negative value can be used to wait indefinitely.
+ * - `0` can be used for non-blocking behavior.
+ *
+ * @return sysret_t Returns a status code indicating the result of the
+ * operation:
+ * - `0` if the message was successfully sent.
+ * - `-RT_ETIMEOUT` if the operation timed out.
+ * - `-RT_EFULL` if the mailbox is full and `timeout` is `0`.
+ * - An appropriate error code for other failures.
+ *
+ * @note Ensure the mailbox has been properly initialized before calling this function.
+ * Passing an uninitialized or invalid mailbox handle may result in undefined behavior.
+ *
+ * @warning Using a negative value without appropriate logic may lead to indefinite blocking,
+ * potentially causing deadlocks.
+ * @see sys_mb_send()
+ */
+sysret_t sys_mb_send_wait(rt_mailbox_t mb,
+ rt_ubase_t value,
+ rt_int32_t timeout)
+{
+ return rt_mb_send_wait(mb, value, timeout);
+}
+
+/**
+ * @brief Receives a message from a mailbox with a timeout.
+ *
+ * This system call attempts to receive a message from the specified mailbox.
+ * If the mailbox is empty, the function will wait for a specified timeout
+ * period for a message to arrive. If no message is received within the timeout,
+ * an error is returned.
+ *
+ * @param[in] mb The handle to the mailbox object from which the message
+ * is to be received. Must be a valid `rt_mailbox_t` object.
+ * @param[out] value Pointer to a variable where the received message will
+ * be stored. Must not be NULL.
+ * @param[in] timeout The maximum time to wait for a message, in milliseconds.
+ * - a negative value: Wait indefinitely until a message is available.
+ * - `0`: Non-blocking mode. If no message is available, return immediately.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The message was successfully received.
+ * - `-RT_ETIMEOUT`: The operation timed out before a message was received.
+ * - Other error codes may indicate failures.
+ *
+ * @note Ensure the mailbox is properly initialized and the `value` pointer
+ * is valid before calling this function. Passing an invalid mailbox
+ * or NULL `value` pointer may lead to undefined behavior.
+ *
+ * @warning Using a negative value without proper safeguards may cause
+ * indefinite blocking, potentially resulting in deadlocks.
+ */
+sysret_t sys_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
+{
+ int ret = 0;
+ rt_ubase_t *kvalue;
+
+ if (!lwp_user_accessable((void *)value, sizeof(rt_ubase_t *)))
+ {
+ return -EFAULT;
+ }
+
+ kvalue = kmem_get(sizeof(rt_ubase_t *));
+ if (kvalue == RT_NULL)
+ {
+ return -ENOMEM;
+ }
+
+ ret = rt_mb_recv(mb, (rt_ubase_t *)kvalue, timeout);
+ if (ret == RT_EOK)
+ {
+ lwp_put_to_user(value, kvalue, sizeof(rt_ubase_t *));
+ }
+
+ kmem_put(kvalue);
+
+ return ret;
+}
+
+rt_weak int syslog_ctrl(int type, char *buf, int len)
+{
+ return -EINVAL;
+}
+
+/**
+ * @brief Sends a log message to the system log.
+ *
+ * This system call sends a message to the system log for recording or debugging purposes.
+ *
+ * @param[in] type The type of the log message, typically representing the severity
+ * or category (e.g., debug, info, warning, error). This should be
+ * a valid predefined log type.
+ * @param[in] buf A pointer to a buffer containing the log message. Must be a
+ * null-terminated string and a valid pointer.
+ * @param[in] len The length of the log message to be sent, excluding the null
+ * terminator. If the length exceeds the system log's limit,
+ * the message may be truncated.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The log message was successfully recorded.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note Ensure the log type is a valid predefined value supported by the system.
+ * The buffer must remain valid and accessible during the execution of this function.
+ *
+ * @warning Sending excessively large or frequent log messages may impact system performance.
+ */
+sysret_t sys_syslog(int type, char *buf, int len)
+{
+ char *tmp;
+ int ret = -1;
+
+ if (!lwp_user_accessable((void *)buf, len))
+ {
+ return -EFAULT;
+ }
+
+ tmp = (char *)rt_malloc(len);
+ if (!tmp)
+ {
+ return -ENOMEM;
+ }
+
+ ret = syslog_ctrl(type, tmp, len);
+ lwp_put_to_user(buf, tmp, len);
+ rt_free(tmp);
+
+ return ret;
+}
+
+/**
+ * @brief Creates a message queue.
+ *
+ * This system call creates a new message queue with a specified name, message size,
+ * maximum number of messages, and associated flags. The message queue allows
+ * messages of a given size to be sent and received between tasks or threads.
+ *
+ * @param[in] name The name of the message queue. It should be a unique
+ * identifier and a null-terminated string.
+ * @param[in] msg_size The size of each message in the queue. This defines
+ * the maximum size for individual messages that can
+ * be sent or received.
+ * @param[in] max_msgs The maximum number of messages the queue can hold.
+ * If the queue is full, further send operations may
+ * block or return an error depending on the flags.
+ * @param[in] flag Flags that control the behavior of the message queue.
+ * This can specify whether the queue is blocking,
+ * non-blocking, or has other specific attributes.
+ *
+ * @return rt_mq_t Returns the handle to the created message queue, or `NULL`
+ * if the creation failed (e.g., due to invalid parameters
+ * or insufficient resources).
+ *
+ * @note Ensure that the message queue name is unique. The size of the messages
+ * and the number of messages should be chosen based on the application
+ * requirements.
+ *
+ * @warning Creating too many message queues or setting an overly large
+ * `max_msgs` may lead to resource exhaustion.
+ */
+rt_mq_t sys_mq_create(const char *name,
+ rt_size_t msg_size,
+ rt_size_t max_msgs,
+ rt_uint8_t flag)
+{
+ rt_mq_t mq = RT_NULL;
+
+ int len = 0;
+ char *kname = RT_NULL;
+
+ len = lwp_user_strlen(name);
+ if (len <= 0)
+ {
+ return RT_NULL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_get_from_user(kname, (void *)name, len + 1) != (len + 1))
+ {
+ kmem_put(kname);
+ return RT_NULL;
+ }
+
+ mq = rt_mq_create(kname, msg_size, max_msgs, flag);
+ if (lwp_user_object_add(lwp_self(), (rt_object_t)mq) != 0)
+ {
+ rt_mq_delete(mq);
+ mq = NULL;
+ }
+
+ kmem_put(kname);
+
+ return mq;
+}
+
+/**
+ * @brief Deletes a message queue.
+ *
+ * This system call deletes the specified message queue and releases any resources
+ * associated with it. After calling this function, the message queue handle
+ * becomes invalid and should not be used.
+ *
+ * @param[in] mq The handle to the message queue to be deleted.
+ * Must be a valid `rt_mq_t` object.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The message queue was successfully deleted.
+ * - An appropriate error code for other failures.
+ *
+ * @note Ensure that no tasks or threads are using the message queue before
+ * deleting it to avoid undefined behavior or data loss.
+ *
+ * @warning Deleting an active message queue that is being used by tasks or
+ * threads may lead to resource leaks or corruption. Ensure proper
+ * synchronization before deletion.
+ */
+sysret_t sys_mq_delete(rt_mq_t mq)
+{
+ return lwp_user_object_delete(lwp_self(), (rt_object_t)mq);
+}
+
+/**
+ * @brief Sends a message to a message queue.
+ *
+ * This system call sends a message to the specified message queue. The message
+ * is copied into the queue's buffer. If the queue is full, the behavior will
+ * depend on the flags set during queue creation (e.g., whether it is blocking
+ * or non-blocking).
+ *
+ * @param[in] mq The handle to the message queue where the message will be sent.
+ * Must be a valid `rt_mq_t` object.
+ * @param[in] buffer A pointer to the message data to be sent. This must not be NULL.
+ * @param[in] size The size of the message to be sent, in bytes. This should be
+ * less than or equal to the maximum message size defined when
+ * the queue was created.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The message was successfully sent to the queue.
+ * - An appropriate error code for other failures.
+ *
+ * @note Ensure that the message size does not exceed the maximum allowed message
+ * size when the queue was created. Passing an invalid queue handle or buffer
+ * may result in undefined behavior.
+ *
+ * @warning Sending messages to a full queue in blocking mode may cause the calling
+ * task or thread to block indefinitely if not properly handled.
+ */
+sysret_t sys_mq_send(rt_mq_t mq, void *buffer, rt_size_t size)
+{
+ int ret = 0;
+ void *kbuffer = RT_NULL;
+
+ if (!lwp_user_accessable((void *)buffer, size))
+ {
+ return -EFAULT;
+ }
+
+ kbuffer = kmem_get(size);
+ if (kbuffer == RT_NULL)
+ {
+ return -ENOMEM;
+ }
+
+ if (lwp_get_from_user(kbuffer, buffer, size) != size)
+ {
+ kmem_put(kbuffer);
+ return -EINVAL;
+ }
+
+ ret = rt_mq_send(mq, kbuffer, size);
+
+ kmem_put(kbuffer);
+
+ return ret;
+}
+
+/**
+ * @brief Sends an urgent message to a message queue.
+ *
+ * This system call sends a message to the specified message queue with higher priority,
+ * meaning it will be placed at the front of the queue, bypassing normal message
+ * order. The message is copied into the queue's buffer. If the queue is full,
+ * the behavior will depend on the flags set during queue creation (e.g., whether
+ * it is blocking or non-blocking).
+ *
+ * @param[in] mq The handle to the message queue where the message will be sent.
+ * Must be a valid `rt_mq_t` object.
+ * @param[in] buffer A pointer to the message data to be sent. This must not be NULL.
+ * @param[in] size The size of the message to be sent, in bytes. This should be
+ * less than or equal to the maximum message size defined when
+ * the queue was created.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The urgent message was successfully sent to the queue.
+ * - `-RT_EFULL`: The queue is full and the message could not be sent.
+ * - An appropriate error code for other failures.
+ *
+ * @note Ensure that the message size does not exceed the maximum allowed message
+ * size when the queue was created. The urgent message will be processed before
+ * other normal messages in the queue.
+ *
+ * @warning Sending urgent messages to a full queue in blocking mode may cause the
+ * calling task or thread to block indefinitely if not properly handled.
+ */
+sysret_t sys_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size)
+{
+ int ret = 0;
+ void *kbuffer = RT_NULL;
+
+ if (!lwp_user_accessable((void *)buffer, size))
+ {
+ return -EFAULT;
+ }
+
+ kbuffer = kmem_get(size);
+ if (kbuffer == RT_NULL)
+ {
+ return -ENOMEM;
+ }
+
+ if (lwp_get_from_user(kbuffer, buffer, size) != size)
+ {
+ kmem_put(kbuffer);
+ return -EINVAL;
+ }
+
+ ret = rt_mq_urgent(mq, kbuffer, size);
+
+ kmem_put(kbuffer);
+
+ return ret;
+}
+
+/**
+ * @brief Receives a message from a message queue.
+ *
+ * This system call attempts to receive a message from the specified message queue.
+ * The message is copied into the provided buffer. If no message is available
+ * in the queue, the function will block for a specified timeout period before
+ * returning. If the timeout expires without receiving a message, an error is returned.
+ *
+ * @param[in] mq The handle to the message queue from which the message
+ * will be received. Must be a valid `rt_mq_t` object.
+ * @param[out] buffer A pointer to the buffer where the received message will
+ * be stored. Must not be NULL and large enough to hold the
+ * message.
+ * @param[in] size The size of the buffer, in bytes. This should be at least
+ * the size of a message in the queue.
+ * @param[in] timeout The maximum time to wait for a message, in milliseconds.
+ * - a negative value: Wait indefinitely until a message is available.
+ * - `0`: Non-blocking mode. If no message is available, return immediately.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The message was successfully received.
+ * - `-RT_ETIMEOUT`: The operation timed out before a message was received.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note Ensure the buffer is large enough to store the message received from the queue.
+ * If the buffer is too small, the function may fail or behave unexpectedly.
+ *
+ * @warning Using a negative value without proper safeguards may cause indefinite
+ * blocking, potentially resulting in deadlocks if no message is received.
+ */
+sysret_t sys_mq_recv(rt_mq_t mq,
+ void *buffer,
+ rt_size_t size,
+ rt_int32_t timeout)
+{
+ int ret = 0;
+ void *kbuffer = RT_NULL;
+
+ if (!lwp_user_accessable((void *)buffer, size))
+ {
+ return -EFAULT;
+ }
+
+ kbuffer = kmem_get(size);
+ if (kbuffer == RT_NULL)
+ {
+ return -ENOMEM;
+ }
+
+ ret = rt_mq_recv(mq, kbuffer, size, timeout);
+ if (ret > 0)
+ {
+ lwp_put_to_user((void *)buffer, (void *)kbuffer, ret);
+ }
+
+ kmem_put(kbuffer);
+
+ return ret;
+}
+
+static void timer_timeout_callback(void *parameter)
+{
+ rt_sem_t sem = (rt_sem_t)parameter;
+ rt_sem_release(sem);
+}
+
+/**
+ * @brief Creates a timer.
+ *
+ * This system call creates a timer that can be used to trigger events or
+ * actions after a specified timeout or interval. The timer will operate in a
+ * real-time manner and can be configured to trigger once or repeatedly. The
+ * created timer can be started, stopped, or deleted as required.
+ *
+ * @param[in] name The name of the timer. It should be a unique string identifier.
+ * The name is used for debugging and logging purposes.
+ * @param[in] data A pointer to user-defined data that will be passed to the timer's
+ * callback function when it is triggered. This may be used to carry
+ * context or other necessary information for the callback.
+ * @param[in] period The timer period in milliseconds. The timer will trigger every
+ * `period` milliseconds, or after the specified timeout.
+ * @param[in] flag Flags that control the behavior of the timer. These can specify
+ * whether the timer is one-shot (triggers once) or periodic
+ * (triggers repeatedly).
+ *
+ * @return rt_timer_t Returns the handle to the created timer, or `NULL` if the creation failed.
+ *
+ * @note The timer callback function must be implemented to handle the event triggered
+ * by the timer. Ensure that the `data` parameter, if used, is properly handled
+ * in the callback.
+ *
+ * @warning Ensure the timer's period and flags are configured correctly to avoid
+ * undesired behavior, especially if the timer is periodic.
+ */
+rt_timer_t sys_rt_timer_create(const char *name,
+ void *data,
+ rt_tick_t time,
+ rt_uint8_t flag)
+{
+ int len = 0;
+ char *kname = RT_NULL;
+ rt_timer_t timer = RT_NULL;
+
+ len = lwp_user_strlen(name);
+ if (len <= 0)
+ {
+ return RT_NULL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return RT_NULL;
+ }
+
+ if (lwp_get_from_user(kname, (void *)name, len + 1) != (len + 1))
+ {
+ kmem_put(kname);
+ return RT_NULL;
+ }
+
+ timer = rt_timer_create(kname, timer_timeout_callback, (void *)data, time, flag);
+ if (lwp_user_object_add(lwp_self(), (rt_object_t)timer) != 0)
+ {
+ rt_timer_delete(timer);
+ timer = NULL;
+ }
+
+ kmem_put(kname);
+
+ return timer;
+}
+
+/**
+ * @brief Deletes a timer.
+ *
+ * This system call deletes the specified timer and releases any resources
+ * associated with it. Once the timer is deleted, its handle becomes invalid,
+ * and any further operations on the timer should be avoided.
+ *
+ * @param[in] timer The handle to the timer to be deleted. Must be a valid `rt_timer_t` object.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer was successfully deleted.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note Ensure that the timer is not active or being used before deleting it to avoid
+ * any unexpected behavior or resource leaks.
+ *
+ * @warning Deleting an active timer may lead to undefined behavior, especially
+ * if the timer is in the middle of triggering or executing its callback.
+ */
+sysret_t sys_rt_timer_delete(rt_timer_t timer)
+{
+ return lwp_user_object_delete(lwp_self(), (rt_object_t)timer);
+}
+
+/**
+ * @brief Starts a timer.
+ *
+ * This system call starts the specified timer, causing it to begin counting down
+ * based on its configured period. Once the timer reaches the set period, it triggers the
+ * associated callback function. The behavior depends on whether the timer is configured
+ * as one-shot or periodic.
+ *
+ * @param[in] timer The handle to the timer to be started. Must be a valid `rt_timer_t` object.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer was successfully started.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note Ensure that the timer has been created and is in a valid state before attempting to start it.
+ *
+ * @warning Starting a timer that is already running may lead to undefined behavior. Ensure that the
+ * timer is stopped or not in use before starting it.
+ */
+sysret_t sys_rt_timer_start(rt_timer_t timer)
+{
+ return rt_timer_start(timer);
+}
+
+/**
+ * @brief Stops a timer.
+ *
+ * This system call stops the specified timer, halting its countdown and
+ * preventing it from triggering further callbacks. If the timer is periodic,
+ * stopping it will prevent further periodic triggers until it is started again.
+ *
+ * @param[in] timer The handle to the timer to be stopped. Must be a valid `rt_timer_t` object.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer was successfully stopped.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note Ensure that the timer is in a valid state before attempting to stop it.
+ * Stopping an inactive or already stopped timer may not have any effect.
+ *
+ * @warning Stopping a timer that is actively triggering or in use may disrupt its expected
+ * behavior. Ensure proper synchronization or state management when stopping
+ * the timer during active use.
+ */
+sysret_t sys_rt_timer_stop(rt_timer_t timer)
+{
+ return rt_timer_stop(timer);
+}
+
+/**
+ * @brief Controls various properties of a timer.
+ *
+ * This system call provides control over various aspects of a timer, such as
+ * modifying its configuration, querying its status, or changing its behavior.
+ * The specific behavior is determined by the command (`cmd`) and any associated arguments (`arg`).
+ *
+ * @param[in] timer The handle to the timer to be controlled. Must be a valid `rt_timer_t` object.
+ * @param[in] cmd The command to execute. The meaning of this parameter depends on the command value.
+ * Common commands might include modifying the timer period, changing its callback,
+ * or querying its current state.
+ * @param[in] arg A pointer to any additional arguments needed for the command. The type and content
+ * of this argument depend on the specific command being executed.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer control operation was successful.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note Ensure that the provided command (`cmd`) is valid for the specific timer implementation.
+ * Incorrect commands or arguments may lead to unexpected behavior or errors.
+ *
+ * @warning Using invalid or unsupported commands may cause undefined behavior or crashes.
+ */
+sysret_t sys_rt_timer_control(rt_timer_t timer, int cmd, void *arg)
+{
+ return rt_timer_control(timer, cmd, arg);
+}
+
+/* MUSL compatible */
+struct ksigevent
+{
+ union sigval sigev_value;
+ int sigev_signo;
+ int sigev_notify;
+ int sigev_tid;
+};
+
+/* to protect unsafe implementation in current rt-smart toolchain */
+RT_STATIC_ASSERT(sigevent_compatible, offsetof(struct ksigevent, sigev_tid) == offsetof(struct sigevent, sigev_notify_function));
+
+/**
+ * @brief Creates a per-process timer.
+ *
+ * This system call creates a new timer associated with the specified clock, and
+ * initializes the timer with the provided event notification attributes.
+ * Once created, the timer can be started, stopped, or controlled as needed.
+ * The timer will trigger when the specified expiration time or interval is reached.
+ *
+ * @param[in] clockid The clock to be used for the timer. Common clock values include:
+ * - `CLOCK_REALTIME`: System real-time clock.
+ * - `CLOCK_MONOTONIC`: Monotonic clock that cannot be set and is not affected by system time changes.
+ * - Other clock IDs can be used depending on the platform and requirements.
+ * @param[in] sevp A pointer to a `sigevent` structure that specifies how the process
+ * should be notified when the timer expires. This can include notification
+ * types such as signal delivery, thread notification, or posting to a queue.
+ * @param[out] timerid A pointer to a `timer_t` variable where the created timer's ID will be stored.
+ * The timer ID will be used for subsequent timer operations (e.g., starting, stopping).
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer was successfully created.
+ * - Other error codes may indicate additional failures.
+ *
+ * @warning Ensure that the provided `sigevent` structure is properly configured, as invalid or
+ * unsupported notification types may result in unexpected behavior.
+ */
+sysret_t sys_timer_create(clockid_t clockid, struct sigevent * restrict sevp, timer_t * restrict timerid)
+{
+ int ret = 0;
+#ifdef ARCH_MM_MMU
+ struct sigevent sevp_k;
+ timer_t timerid_k;
+ int utimer;
+
+ if (sevp == NULL)
+ {
+ sevp_k.sigev_notify = SIGEV_SIGNAL;
+ sevp_k.sigev_signo = SIGALRM;
+ sevp = &sevp_k;
+ }
+ else
+ {
+ /* clear extra bytes if any */
+ if (sizeof(struct ksigevent) < sizeof(struct sigevent))
+ {
+ memset(&sevp_k, 0, sizeof(sevp_k));
+ }
+
+ /* musl passes `struct ksigevent` to kernel, we shoule only get size of that bytes */
+ if (!lwp_get_from_user(&sevp_k, (void *)sevp, sizeof(struct ksigevent)))
+ {
+ return -EINVAL;
+ }
+ }
+
+ ret = _SYS_WRAP(timer_create(clockid, &sevp_k, &timerid_k));
+
+ if (ret != -RT_ERROR)
+ {
+ utimer = (rt_ubase_t)timerid_k;
+ if (!lwp_put_to_user(sevp, (void *)&sevp_k, sizeof(struct ksigevent)) ||
+ !lwp_put_to_user(timerid, (void *)&utimer, sizeof(utimer)))
+ {
+ ret = -EINVAL;
+ }
+ }
+#else
+ ret = _SYS_WRAP(timer_create(clockid, sevp, timerid));
+#endif
+ return ret;
+}
+
+/**
+ * @brief Deletes a timer.
+ *
+ * This system call deletes the specified timer and releases any resources associated
+ * with it. Once the timer is deleted, it can no longer be used, and any further
+ * operations on the timer (such as starting or stopping) will result in an error.
+ *
+ * @param[in] timerid The ID of the timer to be deleted. This is the timer handle
+ * returned by `sys_timer_create`.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer was successfully deleted.
+ * - Other error codes may indicate additional failures.
+ *
+ * @note After calling this function, the timer ID becomes invalid, and it should
+ * not be used in any further operations.
+ *
+ * @warning Make sure the timer is not active or in use when attempting to delete it,
+ * as deleting an active timer may cause unexpected behavior or resource leaks.
+ */
+sysret_t sys_timer_delete(timer_t timerid)
+{
+ int ret = timer_delete(timerid);
+ return (ret < 0 ? GET_ERRNO() : ret);
+}
+
+/**
+ * @brief Changes the time or interval of an existing timer.
+ *
+ * This system call modifies the expiration time or interval of a previously created
+ * timer. It can either set a new expiration time for the timer or update the
+ * interval for periodic timers. The timer can be started or modified based on
+ * the flags provided. The current (old) timer settings can be retrieved if
+ * requested.
+ *
+ * @param[in] timerid The ID of the timer to modify. This is the timer handle
+ * returned by `sys_timer_create`.
+ * @param[in] flags Flags that control the behavior of the operation. Common
+ * values include:
+ * - `TIMER_ABSTIME`: Specifies that `new_value` contains
+ * an absolute time. Otherwise, it is treated as relative.
+ * @param[in] new_value A pointer to the `itimerspec` structure specifying
+ * the new time settings for the timer. The structure includes:
+ * - `it_value`: The initial expiration time (relative or absolute).
+ * - `it_interval`: The period for periodic timers.
+ * @param[out] old_value A pointer to an `itimerspec` structure where the previous
+ * timer settings will be stored. If NULL, the old value is ignored.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The timer time/interval was successfully updated.
+ * - Other error codes may indicate additional failures.
+ *
+ * @warning Modifying a timer that is currently active can cause timing-related issues
+ * if not handled correctly. Make sure the timer is in an appropriate state
+ * before making changes.
+ */
+sysret_t sys_timer_settime(timer_t timerid, int flags,
+ const struct itimerspec * restrict new_value,
+ struct itimerspec * restrict old_value)
+{
+ int ret = 0;
+#ifdef ARCH_MM_MMU
+ struct itimerspec new_value_k;
+ struct itimerspec old_value_k;
+
+ if (!lwp_get_from_user(&new_value_k, (void *)new_value, sizeof(*new_value)) ||
+ (old_value && !lwp_get_from_user(&old_value_k, (void *)old_value, sizeof(*old_value))))
+ {
+ return -EFAULT;
+ }
+
+ ret = timer_settime(timerid, flags, &new_value_k, &old_value_k);
+ lwp_put_to_user(old_value, (void *)&old_value_k, sizeof old_value_k);
+
+#else
+ ret = timer_settime(timerid, flags, new_value, old_value);
+#endif
+ return (ret < 0 ? GET_ERRNO() : ret);
+}
+
+/**
+ * @brief Retrieves the current time and interval of a timer.
+ *
+ * This system call fetches the current expiration time (`it_value`) and interval (`it_interval`)
+ * of a previously created timer. It allows the caller to determine the current state of the timer,
+ * whether it is one-shot or periodic, and the remaining time before expiration.
+ *
+ * @param[in] timerid The ID of the timer to query. This is the timer handle
+ * returned by `sys_timer_create`.
+ * @param[out] curr_value A pointer to an `itimerspec` structure where the current timer values
+ * will be stored. This structure includes:
+ * - `it_value`: The remaining time until the timer expires.
+ * - `it_interval`: The interval between subsequent expirations (for periodic timers).
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The current time/interval was successfully retrieved.
+ * - Other error codes may indicate additional failures.
+ *
+ * @warning Ensure that the timer ID is valid before calling this function, as invalid timer IDs
+ * will result in errors.
+ */
+sysret_t sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
+{
+ int ret = 0;
+#ifdef ARCH_MM_MMU
+
+ struct itimerspec curr_value_k;
+ lwp_get_from_user(&curr_value_k, (void *)curr_value, sizeof curr_value_k);
+ ret = timer_gettime(timerid, &curr_value_k);
+ lwp_put_to_user(curr_value, (void *)&curr_value_k, sizeof curr_value_k);
+#else
+ ret = timer_gettime(timerid, curr_value);
+#endif
+ return (ret < 0 ? GET_ERRNO() : ret);
+}
+
+/**
+ * @brief Retrieves the overrun count for a periodic timer.
+ *
+ * This system call retrieves the number of times a periodic timer has "overrun." An overrun occurs
+ * when a timer expires before the previous expiration has been acknowledged or handled. For periodic
+ * timers, this indicates how many times the timer's expiration has been missed due to delayed processing
+ * or handling.
+ *
+ * @param[in] timerid The ID of the timer to query. This is the timer handle
+ * returned by `sys_timer_create`.
+ *
+ * @return sysret_t Returns a status code indicating the result of the operation:
+ * - `0`: The overrun count was successfully retrieved.
+ * - Other error codes may indicate additional failures.
+ *
+ * @warning Ensure that the timer ID is valid before calling this function, as invalid timer IDs
+ * will result in errors.
+ */
+sysret_t sys_timer_getoverrun(timer_t timerid)
+{
+ int ret = 0;
+ ret = timer_getoverrun(timerid);
+ return (ret < 0 ? GET_ERRNO() : ret);
+}