kernel: k_msgq: add peek at function
Make message queue able to peek data at the specified index.
Related to issue #53360
Signed-off-by: romain pelletant <romainp@kickmaker.net>
diff --git a/kernel/msg_q.c b/kernel/msg_q.c
index 0e6488d..6b68f7a 100644
--- a/kernel/msg_q.c
+++ b/kernel/msg_q.c
@@ -315,6 +315,52 @@
#include <syscalls/k_msgq_peek_mrsh.c>
#endif
+int z_impl_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx)
+{
+ k_spinlock_key_t key;
+ int result;
+ uint32_t bytes_to_end;
+ uint32_t byte_offset;
+ char *start_addr;
+
+ key = k_spin_lock(&msgq->lock);
+
+ if (msgq->used_msgs > idx) {
+ bytes_to_end = (msgq->buffer_end - msgq->read_ptr);
+ byte_offset = idx * msgq->msg_size;
+ start_addr = msgq->read_ptr;
+ /* check item available in start/end of ring buffer */
+ if (bytes_to_end <= byte_offset) {
+ /* Tweak the values in case */
+ byte_offset -= bytes_to_end;
+ /* wrap-around is required */
+ start_addr = msgq->buffer_start;
+ }
+ (void)memcpy(data, start_addr + byte_offset, msgq->msg_size);
+ result = 0;
+ } else {
+ /* don't wait for a message to become available */
+ result = -ENOMSG;
+ }
+
+ SYS_PORT_TRACING_OBJ_FUNC(k_msgq, peek, msgq, result);
+
+ k_spin_unlock(&msgq->lock, key);
+
+ return result;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx)
+{
+ Z_OOPS(Z_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
+ Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, msgq->msg_size));
+
+ return z_impl_k_msgq_peek_at(msgq, data, idx);
+}
+#include <syscalls/k_msgq_peek_at_mrsh.c>
+#endif
+
void z_impl_k_msgq_purge(struct k_msgq *msgq)
{
k_spinlock_key_t key;