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