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