@@ -187,6 +187,100 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
187
187
return result ;
188
188
}
189
189
190
+ int z_impl_k_msgq_put_urgent (struct k_msgq * msgq , const void * data , k_timeout_t timeout )
191
+ {
192
+ __ASSERT (!arch_is_in_isr () || K_TIMEOUT_EQ (timeout , K_NO_WAIT ), "" );
193
+
194
+ struct k_thread * pending_thread ;
195
+ k_spinlock_key_t key ;
196
+ int result ;
197
+ bool resched = false;
198
+
199
+ key = k_spin_lock (& msgq -> lock );
200
+
201
+ SYS_PORT_TRACING_OBJ_FUNC_ENTER (k_msgq , put , msgq , timeout );
202
+
203
+ if (msgq -> used_msgs < msgq -> max_msgs ) {
204
+ /* message queue isn't full */
205
+ pending_thread = z_unpend_first_thread (& msgq -> wait_q );
206
+ if (unlikely (pending_thread != NULL )) {
207
+ resched = true;
208
+
209
+ /* give message to waiting thread */
210
+ (void )memcpy (pending_thread -> base .swap_data , data , msgq -> msg_size );
211
+ /* wake up waiting thread */
212
+ arch_thread_return_value_set (pending_thread , 0 );
213
+ z_ready_thread (pending_thread );
214
+ } else {
215
+ /*
216
+ * urgent put = write message to the head of the queue.
217
+ * this is achieved in practice by simply:
218
+ *
219
+ * 1. decrementing the read pointer. This effectively
220
+ * opens space for the incoming message in the head of
221
+ * the queue.
222
+ *
223
+ * 2. temporarily matching the read pointer with the
224
+ * write pointer. This way the message will be written
225
+ * in the recently opened space.
226
+ *
227
+ * 3. reverting the write pointer after the write to its
228
+ * original value. The read pointer, by its turn, should
229
+ * be always at the head, so it doesn't need reverting
230
+ * because we just wrote to the head.
231
+ */
232
+ char * original_write_ptr = msgq -> write_ptr ;
233
+
234
+ /* decrement the read pointer */
235
+ msgq -> read_ptr -= msgq -> msg_size ;
236
+ if (msgq -> read_ptr < msgq -> buffer_start ) {
237
+ msgq -> read_ptr = msgq -> buffer_end - msgq -> msg_size ;
238
+ }
239
+
240
+ /* match read and write pointers */
241
+ msgq -> write_ptr = msgq -> read_ptr ;
242
+
243
+ /* put message in queue */
244
+ __ASSERT_NO_MSG (msgq -> write_ptr >= msgq -> buffer_start &&
245
+ msgq -> write_ptr < msgq -> buffer_end );
246
+ (void )memcpy (msgq -> write_ptr , (char * )data , msgq -> msg_size );
247
+ msgq -> write_ptr += msgq -> msg_size ;
248
+ if (msgq -> write_ptr == msgq -> buffer_end ) {
249
+ msgq -> write_ptr = msgq -> buffer_start ;
250
+ }
251
+ msgq -> used_msgs ++ ;
252
+
253
+ /* revert write pointer to the original value */
254
+ msgq -> write_ptr = original_write_ptr ;
255
+
256
+ resched = handle_poll_events (msgq );
257
+ }
258
+ result = 0 ;
259
+ } else if (K_TIMEOUT_EQ (timeout , K_NO_WAIT )) {
260
+ /* don't wait for message space to become available */
261
+ result = - ENOMSG ;
262
+ } else {
263
+ SYS_PORT_TRACING_OBJ_FUNC_BLOCKING (k_msgq , put , msgq , timeout );
264
+
265
+ /* wait for put message success, failure, or timeout */
266
+ _current -> base .swap_data = (void * ) data ;
267
+
268
+ result = z_pend_curr (& msgq -> lock , key , & msgq -> wait_q , timeout );
269
+ SYS_PORT_TRACING_OBJ_FUNC_EXIT (k_msgq , put , msgq , timeout , result );
270
+ return result ;
271
+ }
272
+
273
+ SYS_PORT_TRACING_OBJ_FUNC_EXIT (k_msgq , put , msgq , timeout , result );
274
+
275
+ if (resched ) {
276
+ z_reschedule (& msgq -> lock , key );
277
+ } else {
278
+ k_spin_unlock (& msgq -> lock , key );
279
+ }
280
+
281
+ return result ;
282
+ }
283
+
190
284
#ifdef CONFIG_USERSPACE
191
285
static inline int z_vrfy_k_msgq_put (struct k_msgq * msgq , const void * data ,
192
286
k_timeout_t timeout )
@@ -196,6 +290,15 @@ static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
196
290
197
291
return z_impl_k_msgq_put (msgq , data , timeout );
198
292
}
293
+
294
+ static inline int z_vrfy_k_msgq_put_urgent (struct k_msgq * msgq , const void * data ,
295
+ k_timeout_t timeout )
296
+ {
297
+ K_OOPS (K_SYSCALL_OBJ (msgq , K_OBJ_MSGQ ));
298
+ K_OOPS (K_SYSCALL_MEMORY_READ (data , msgq -> msg_size ));
299
+
300
+ return z_impl_k_msgq_put_urgent (msgq , data , timeout );
301
+ }
199
302
#include <zephyr/syscalls/k_msgq_put_mrsh.c>
200
303
#endif /* CONFIG_USERSPACE */
201
304
0 commit comments