Skip to content

Commit 1698684

Browse files
alexpaschoalettocfriedt
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 <[email protected]>
1 parent 5673189 commit 1698684

File tree

2 files changed

+73
-8
lines changed

2 files changed

+73
-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: 45 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,30 @@ 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+
* to write a message to the back of the queue,
158+
* copy the message and increment write_ptr
159+
*/
160+
(void)memcpy(msgq->write_ptr, (char *)data, msgq->msg_size);
161+
msgq->write_ptr += msgq->msg_size;
162+
if (msgq->write_ptr == msgq->buffer_end) {
163+
msgq->write_ptr = msgq->buffer_start;
164+
}
165+
} else {
166+
/*
167+
* to write a message to the head of the queue,
168+
* first decrement the read pointer (to open
169+
* space at the front of the queue) then copy
170+
* the message to the newly created space.
171+
*/
172+
if (msgq->read_ptr == msgq->buffer_start) {
173+
msgq->read_ptr = msgq->buffer_end;
174+
}
175+
msgq->read_ptr -= msgq->msg_size;
176+
(void)memcpy(msgq->read_ptr, (char *)data, msgq->msg_size);
160177
}
161178
msgq->used_msgs++;
162179
resched = handle_poll_events(msgq);
@@ -187,6 +204,17 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
187204
return result;
188205
}
189206

207+
208+
int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout)
209+
{
210+
return put_msg_in_queue(msgq, data, timeout, true);
211+
}
212+
213+
int z_impl_k_msgq_put_front(struct k_msgq *msgq, const void *data, k_timeout_t timeout)
214+
{
215+
return put_msg_in_queue(msgq, data, timeout, false);
216+
}
217+
190218
#ifdef CONFIG_USERSPACE
191219
static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
192220
k_timeout_t timeout)
@@ -197,6 +225,16 @@ static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
197225
return z_impl_k_msgq_put(msgq, data, timeout);
198226
}
199227
#include <zephyr/syscalls/k_msgq_put_mrsh.c>
228+
229+
static inline int z_vrfy_k_msgq_put_front(struct k_msgq *msgq, const void *data,
230+
k_timeout_t timeout)
231+
{
232+
K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
233+
K_OOPS(K_SYSCALL_MEMORY_READ(data, msgq->msg_size));
234+
235+
return z_impl_k_msgq_put_front(msgq, data, timeout);
236+
}
237+
#include <zephyr/syscalls/k_msgq_put_front_mrsh.c>
200238
#endif /* CONFIG_USERSPACE */
201239

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

0 commit comments

Comments
 (0)