Skip to content

Commit 6b361b2

Browse files
alexpaschoalettoAlexander pinheiro paschoaletto
authored andcommitted
kernel: msgq: adding support to k_msgq_put_front
This commit introduces the k_msgq_put_front API for sending messages to a queue in a LIFO scheme. Signed-off-by: Alexander Paschoaletto <axelpinheiro@gmail.com>
1 parent 808ee17 commit 6b361b2

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

include/zephyr/kernel.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4785,7 +4785,7 @@ __syscall int k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size,
47854785
int k_msgq_cleanup(struct k_msgq *msgq);
47864786

47874787
/**
4788-
* @brief Send a message to a message queue.
4788+
* @brief Send a message to the end of a message queue.
47894789
*
47904790
* This routine sends a message to message queue @a q.
47914791
*
@@ -4806,6 +4806,33 @@ int k_msgq_cleanup(struct k_msgq *msgq);
48064806
*/
48074807
__syscall int k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout);
48084808

4809+
/**
4810+
* @brief Send a message to the front of a message queue.
4811+
*
4812+
* This routine sends a message to the beginning (head) of message queue @a q.
4813+
* Messages sent with this method will be retrieved before any pre-existing
4814+
* messages in the queue.
4815+
*
4816+
* @note if there is no space in the message queue, this function will
4817+
* behave the same as k_msgq_put.
4818+
*
4819+
* @note The message content is copied from @a data into @a msgq and the @a data
4820+
* pointer is not retained, so the message content will not be modified
4821+
* by this function.
4822+
*
4823+
* @funcprops \isr_ok
4824+
*
4825+
* @param msgq Address of the message queue.
4826+
* @param data Pointer to the message.
4827+
* @param timeout Waiting period to add the message, or one of the special
4828+
* values K_NO_WAIT and K_FOREVER.
4829+
*
4830+
* @retval 0 Message sent.
4831+
* @retval -ENOMSG Returned without waiting or queue purged.
4832+
* @retval -EAGAIN Waiting period timed out.
4833+
*/
4834+
__syscall int k_msgq_put_front(struct k_msgq *msgq, const void *data, k_timeout_t timeout);
4835+
48094836
/**
48104837
* @brief Receive a message from a message queue.
48114838
*

kernel/msg_q.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ int k_msgq_cleanup(struct k_msgq *msgq)
124124
return 0;
125125
}
126126

127-
128-
int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout)
127+
static inline int put_msg_in_queue(struct k_msgq *msgq, const void *data,
128+
k_timeout_t timeout, bool put_at_back)
129129
{
130130
__ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), "");
131131

@@ -150,13 +150,31 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
150150
arch_thread_return_value_set(pending_thread, 0);
151151
z_ready_thread(pending_thread);
152152
} else {
153-
/* put message in queue */
154153
__ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start &&
155154
msgq->write_ptr < msgq->buffer_end);
156-
(void)memcpy(msgq->write_ptr, (char *)data, msgq->msg_size);
157-
msgq->write_ptr += msgq->msg_size;
158-
if (msgq->write_ptr == msgq->buffer_end) {
159-
msgq->write_ptr = msgq->buffer_start;
155+
if (put_at_back) {
156+
/*
157+
* writing a message to the back of the queue is
158+
* simple and effective: copy the message, then
159+
* increment write_ptr.
160+
*/
161+
(void)memcpy(msgq->write_ptr, (char *)data, msgq->msg_size);
162+
msgq->write_ptr += msgq->msg_size;
163+
if (msgq->write_ptr == msgq->buffer_end) {
164+
msgq->write_ptr = msgq->buffer_start;
165+
}
166+
} else {
167+
/*
168+
* writing a message to the head of the queue can
169+
* be achieved by simply decrementing the read pointer
170+
* to open space at the front of the queue, then
171+
* copying the message to the newly created space.
172+
*/
173+
if (msgq->read_ptr == msgq->buffer_start) {
174+
msgq->read_ptr = msgq->buffer_end;
175+
}
176+
msgq->read_ptr -= msgq->msg_size;
177+
(void)memcpy(msgq->read_ptr, (char *)data, msgq->msg_size);
160178
}
161179
msgq->used_msgs++;
162180
resched = handle_poll_events(msgq);
@@ -187,6 +205,17 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
187205
return result;
188206
}
189207

208+
209+
int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout)
210+
{
211+
return put_msg_in_queue(msgq, data, timeout, true);
212+
}
213+
214+
int z_impl_k_msgq_put_front(struct k_msgq *msgq, const void *data, k_timeout_t timeout)
215+
{
216+
return put_msg_in_queue(msgq, data, timeout, false);
217+
}
218+
190219
#ifdef CONFIG_USERSPACE
191220
static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
192221
k_timeout_t timeout)
@@ -197,6 +226,16 @@ static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
197226
return z_impl_k_msgq_put(msgq, data, timeout);
198227
}
199228
#include <zephyr/syscalls/k_msgq_put_mrsh.c>
229+
230+
static inline int z_vrfy_k_msgq_put_front(struct k_msgq *msgq, const void *data,
231+
k_timeout_t timeout)
232+
{
233+
K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
234+
K_OOPS(K_SYSCALL_MEMORY_READ(data, msgq->msg_size));
235+
236+
return z_impl_k_msgq_put_front(msgq, data, timeout);
237+
}
238+
#include <zephyr/syscalls/k_msgq_put_front_mrsh.c>
200239
#endif /* CONFIG_USERSPACE */
201240

202241
void z_impl_k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs)

0 commit comments

Comments
 (0)