@@ -124,8 +124,7 @@ int k_msgq_cleanup(struct k_msgq *msgq)
124
124
return 0 ;
125
125
}
126
126
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 , k_timeout_t timeout , bool put_at_back )
129
128
{
130
129
__ASSERT (!arch_is_in_isr () || K_TIMEOUT_EQ (timeout , K_NO_WAIT ), "" );
131
130
@@ -150,13 +149,50 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
150
149
arch_thread_return_value_set (pending_thread , 0 );
151
150
z_ready_thread (pending_thread );
152
151
} else {
153
- /* put message in queue */
154
152
__ASSERT_NO_MSG (msgq -> write_ptr >= msgq -> buffer_start &&
155
153
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 ;
154
+ if (put_at_back ) {
155
+ /*
156
+ * writing a message to the back of the queue is
157
+ * simple and effective: copy the message, then
158
+ * 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
+ * writing a message to the head of the queue is
168
+ * less obvious, but it can be achieved by simply
169
+ * following these steps:
170
+ *
171
+ * 1. decrementing the read pointer. This effectively
172
+ * opens space for the incoming message in the head of
173
+ * the queue.
174
+ *
175
+ * 2. temporarily matching the write pointer with the
176
+ * read pointer. This way the message will be written
177
+ * in the recently opened space.
178
+ *
179
+ * 3. reverting the write pointer after the write to its
180
+ * original value. The read pointer, by its turn, should
181
+ * be always at the head, so it doesn't need reverting
182
+ * because we just wrote to the head.
183
+ *
184
+ * ...but this is inefficient because we need to go back
185
+ * and forth with the value of write_ptr; note that it
186
+ * becomes equal to read_ptr just to be restored afterwards.
187
+ * A much more efficient solution is to simply write the
188
+ * message directly to read_ptr's address after step 1,
189
+ * which avoids needing to perform steps 2 and 3 altogether.
190
+ */
191
+ if (msgq -> read_ptr == msgq -> buffer_start ) {
192
+ msgq -> read_ptr = msgq -> buffer_end ;
193
+ }
194
+ msgq -> read_ptr -= msgq -> msg_size ;
195
+ (void )memcpy (msgq -> read_ptr , (char * )data , msgq -> msg_size );
160
196
}
161
197
msgq -> used_msgs ++ ;
162
198
resched = handle_poll_events (msgq );
@@ -187,6 +223,17 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
187
223
return result ;
188
224
}
189
225
226
+
227
+ int z_impl_k_msgq_put (struct k_msgq * msgq , const void * data , k_timeout_t timeout )
228
+ {
229
+ return put_msg_in_queue (msgq , data , timeout , true);
230
+ }
231
+
232
+ int z_impl_k_msgq_put_front (struct k_msgq * msgq , const void * data , k_timeout_t timeout )
233
+ {
234
+ return put_msg_in_queue (msgq , data , timeout , false);
235
+ }
236
+
190
237
#ifdef CONFIG_USERSPACE
191
238
static inline int z_vrfy_k_msgq_put (struct k_msgq * msgq , const void * data ,
192
239
k_timeout_t timeout )
@@ -196,6 +243,15 @@ static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
196
243
197
244
return z_impl_k_msgq_put (msgq , data , timeout );
198
245
}
246
+
247
+ static inline int z_vrfy_k_msgq_put_front (struct k_msgq * msgq , const void * data ,
248
+ k_timeout_t timeout )
249
+ {
250
+ K_OOPS (K_SYSCALL_OBJ (msgq , K_OBJ_MSGQ ));
251
+ K_OOPS (K_SYSCALL_MEMORY_READ (data , msgq -> msg_size ));
252
+
253
+ return z_impl_k_msgq_put_front (msgq , data , timeout );
254
+ }
199
255
#include <zephyr/syscalls/k_msgq_put_mrsh.c>
200
256
#endif /* CONFIG_USERSPACE */
201
257
0 commit comments