source: rtems/cpukit/include/rtems/score/coremsgimpl.h @ 36655b8

Last change on this file since 36655b8 was 36655b8, checked in by Sebastian Huber <sebastian.huber@…>, on 07/16/21 at 11:27:00

cpukit: occured -> occurred

  • Property mode set to 100644
File size: 22.2 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreMessageQueue
5 *
6 * @brief This header file provides interfaces of the
7 *   @ref RTEMSScoreMessageQueue which are used by the implementation and the
8 *   @ref RTEMSImplApplConfig.
9 */
10
11/*
12 *  COPYRIGHT (c) 1989-2009.
13 *  On-Line Applications Research Corporation (OAR).
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.org/license/LICENSE.
18 */
19
20#ifndef _RTEMS_SCORE_COREMSGIMPL_H
21#define _RTEMS_SCORE_COREMSGIMPL_H
22
23#include <rtems/score/coremsg.h>
24#include <rtems/score/status.h>
25#include <rtems/score/chainimpl.h>
26#include <rtems/score/threaddispatch.h>
27#include <rtems/score/threadqimpl.h>
28
29#include <limits.h>
30#include <string.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36/**
37 * @addtogroup RTEMSScoreMessageQueue
38 *
39 * @{
40 */
41
42/**
43 *  @brief Used when appending messages onto a message queue.
44 *
45 *  This is the priority constant used when appending messages onto
46 *  a message queue.
47 */
48#define  CORE_MESSAGE_QUEUE_SEND_REQUEST   INT_MAX
49
50/**
51 *  @brief Used when prepending messages onto a message queue.
52 *
53 *  This is the priority constant used when prepending messages onto
54 *  a message queue.
55 */
56#define  CORE_MESSAGE_QUEUE_URGENT_REQUEST INT_MIN
57
58/**
59 *  @brief The modes in which a message may be submitted to a message queue.
60 *
61 *  The following type details the modes in which a message
62 *  may be submitted to a message queue.  The message may be posted
63 *  in a send or urgent fashion.
64 *
65 *  @note  All other values are message priorities.  Numerically smaller
66 *         priorities indicate higher priority messages.
67 */
68typedef int CORE_message_queue_Submit_types;
69
70/**
71 * @brief This handler shall allocate the message buffer storage area for a
72 *   message queue.
73 *
74 * The handler shall set the CORE_message_queue_Control::free_message_buffers
75 * member.
76 *
77 * @param[out] the_message_queue is the message queue control.
78 *
79 * @param size is the message buffer storage area size to allocate.
80 *
81 * @param arg is the handler argument.
82 *
83 * @retval NULL The allocation failed.
84 *
85 * @return Otherwise the pointer to the allocated message buffer storage area
86 *   begin shall be returned.
87 */
88typedef void *( *CORE_message_queue_Allocate_buffers )(
89  CORE_message_queue_Control *the_message_queue,
90  size_t                      size,
91  const void                 *arg
92);
93
94/**
95 * @brief This handler allocates the message buffer storage area for a message
96 *   queue from the RTEMS Workspace.
97 *
98 * The handler sets the CORE_message_queue_Control::free_message_buffers
99 * to _Workspace_Free().
100 *
101 * @param[out] the_message_queue is the message queue control.
102 *
103 * @param size is the message buffer storage area size to allocate.
104 *
105 * @param arg is the unused handler argument.
106 *
107 * @retval NULL The allocation failed.
108 *
109 * @return Otherwise the pointer to the allocated message buffer storage area
110 *   begin is returned.
111 */
112void *_CORE_message_queue_Workspace_allocate(
113  CORE_message_queue_Control *the_message_queue,
114  size_t                      size,
115  const void                 *arg
116);
117
118/**
119 * @brief Initializes a message queue.
120 *
121 * @param[out] the_message_queue is the message queue to initialize.
122 *
123 * @param discipline is the blocking discipline for the message queue.
124 *
125 * @param maximum_pending_messages is the maximum number of messages that will
126 *   be allowed to be pending at any given time.
127 *
128 * @param maximum_message_size is the size of the largest message that may be
129 *   sent to this message queue instance.
130 *
131 * @param allocate_buffers is the message buffer storage area allocation
132 *   handler.
133 *
134 * @param arg is the message buffer storage area allocation handler argument.
135 *
136 * @retval STATUS_SUCCESSFUL The message queue was initialized.
137 *
138 * @retval STATUS_MESSAGE_QUEUE_INVALID_SIZE Calculations with the maximum
139 *   pending messages or maximum message size produced an integer overflow.
140 *
141 * @retval STATUS_MESSAGE_QUEUE_NO_MEMORY The message buffer storage area
142 *   allocation failed.
143 */
144Status_Control _CORE_message_queue_Initialize(
145  CORE_message_queue_Control          *the_message_queue,
146  CORE_message_queue_Disciplines       discipline,
147  uint32_t                             maximum_pending_messages,
148  size_t                               maximum_message_size,
149  CORE_message_queue_Allocate_buffers  allocate_buffers,
150  const void                          *arg
151);
152
153/**
154 * @brief Closes a message queue.
155 *
156 * This package is the implementation of the CORE Message Queue Handler.
157 * This core object provides task synchronization and communication functions
158 * via messages passed to queue objects.
159 *
160 * This function closes a message by returning all allocated space and
161 * flushing @a the_message_queue's task wait queue.
162 *
163 * @param[in, out] the_message_queue The message queue to close.
164 * @param[in, out] queue_context The thread queue context used for
165 *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
166 */
167void _CORE_message_queue_Close(
168  CORE_message_queue_Control *the_message_queue,
169  Thread_queue_Context       *queue_context
170);
171
172/**
173 * @brief Flushes pending messages.
174 *
175 * This package is the implementation of the CORE Message Queue Handler.
176 * This core object provides task synchronization and communication functions
177 * via messages passed to queue objects.
178 *
179 * This function flushes @a the_message_queue's pending message queue.  The
180 * number of messages flushed from the queue is returned.
181 *
182 * @param[in, out] the_message_queue The message queue to flush.
183 * @param queue_context The thread queue context with interrupts disabled.
184 *
185 * @return This method returns the number of message pending messages flushed.
186 */
187uint32_t   _CORE_message_queue_Flush(
188  CORE_message_queue_Control *the_message_queue,
189  Thread_queue_Context       *queue_context
190);
191
192#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
193/**
194 * @brief Flushes waiting threads.
195 *
196 * This function flushes the threads which are blocked on
197 * @a the_message_queue's pending message queue.  They are
198 * unblocked whether blocked sending or receiving. It returns
199 * the number of messages flushed from the queue.
200 *
201 * @param[in, out] the_message_queue The message queue to flush.
202 *
203 * @return This method returns the number of messages flushed from the queue.
204 */
205  void _CORE_message_queue_Flush_waiting_threads(
206    CORE_message_queue_Control *the_message_queue
207  );
208#endif
209
210/**
211 * @brief Broadcasts a message to the message queue.
212 *
213 * This package is the implementation of the CORE Message Queue Handler.
214 * This core object provides task synchronization and communication functions
215 * via messages passed to queue objects.
216 *
217 * This function sends a message for every thread waiting on the queue and
218 * returns the number of threads made ready by the message.
219 *
220 * @param[in, out] the_message_queue The message queue to operate upon.
221 * @param buffer The starting address of the message to broadcast.
222 * @param size The size of the message being broadcast.
223 * @param[out] count The variable that will contain the
224 *        number of tasks that are sent this message.
225 * @param queue_context The thread queue context used for
226 *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
227 *
228 * @retval STATUS_SUCCESSFUL The message was successfully broadcast.
229 * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
230 */
231Status_Control _CORE_message_queue_Broadcast(
232  CORE_message_queue_Control *the_message_queue,
233  const void                 *buffer,
234  size_t                      size,
235  uint32_t                   *count,
236  Thread_queue_Context       *queue_context
237);
238
239/**
240 * @brief Submits a message to the message queue.
241 *
242 * This routine implements the send and urgent message functions. It
243 * processes a message that is to be submitted to the designated
244 * message queue.  The message will either be processed as a
245 * send message which it will be inserted at the rear of the queue
246 * or it will be processed as an urgent message which will be inserted
247 * at the front of the queue.
248 *
249 * @param[in, out] the_message_queue The message queue to operate upon.
250 * @param executing The executing thread.
251 * @param buffer The starting address of the message to send.
252 * @param size The size of the message being send.
253 * @param submit_type Determines whether the message is prepended,
254 *        appended, or enqueued in priority order.
255 * @param wait Indicates whether the calling thread is willing to block
256 *        if the message queue is full.
257 * @param queue_context The thread queue context used for
258 *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
259 *
260 * @retval STATUS_SUCCESSFUL The message was successfully submitted to the message queue.
261 * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
262 * @retval STATUS_TOO_MANY No message buffers were available.
263 * @retval STATUS_MESSAGE_QUEUE_WAIT_IN_ISR The caller is in an ISR, do not block!
264 * @retval STATUS_TIMEOUT A timeout occurred.
265 */
266Status_Control _CORE_message_queue_Submit(
267  CORE_message_queue_Control       *the_message_queue,
268  Thread_Control                   *executing,
269  const void                       *buffer,
270  size_t                            size,
271  CORE_message_queue_Submit_types   submit_type,
272  bool                              wait,
273  Thread_queue_Context             *queue_context
274);
275
276/**
277 * @brief Seizes a message from the message queue.
278 *
279 * This package is the implementation of the CORE Message Queue Handler.
280 * This core object provides task synchronization and communication functions
281 * via messages passed to queue objects.
282 *
283 * This kernel routine dequeues a message, copies the message buffer to
284 * a given destination buffer, and frees the message buffer to the
285 * inactive message pool.  The thread will be blocked if wait is true,
286 * otherwise an error will be given to the thread if no messages are available.
287 *
288 * @param[in, out] the_message_queue The message queue to seize a message from.
289 * @param executing The executing thread.
290 * @param[out] buffer The starting address of the message buffer to
291 *        to be filled in with a message.
292 * @param[out] size_p The size of the @a buffer,
293 *        indicates the maximum size message that the caller can receive.
294 * @param wait Indicates whether the calling thread is willing to block
295 *        if the message queue is empty.
296 * @param queue_context The thread queue context used for
297 *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
298 *
299 * @retval STATUS_SUCCESSFUL The message was successfully seized from the message queue.
300 * @retval STATUS_UNSATISFIED Wait was set to false and there is currently no pending message.
301 * @retval STATUS_TIMEOUT A timeout occurred.
302 *
303 * @note Returns message priority via return area in TCB.
304 *
305 * - INTERRUPT LATENCY:
306 *   + available
307 *   + wait
308 */
309Status_Control _CORE_message_queue_Seize(
310  CORE_message_queue_Control *the_message_queue,
311  Thread_Control             *executing,
312  void                       *buffer,
313  size_t                     *size_p,
314  bool                        wait,
315  Thread_queue_Context       *queue_context
316);
317
318/**
319 * @brief Inserts a message into the message queue.
320 *
321 * Copies the specified content into the message storage space and then
322 * inserts the message into the message queue according to the submit type.
323 *
324 * @param[in, out] the_message_queue The message queue to insert a message in.
325 * @param[in, out] the_message The message to insert in the message queue.
326 * @param content_source The message content source.
327 * @param content_size The message content size in bytes.
328 * @param submit_type Determines whether the message is prepended,
329 *        appended, or enqueued in priority order.
330 */
331void _CORE_message_queue_Insert_message(
332  CORE_message_queue_Control        *the_message_queue,
333  CORE_message_queue_Buffer         *the_message,
334  const void                        *content_source,
335  size_t                             content_size,
336  CORE_message_queue_Submit_types    submit_type
337);
338
339/**
340 * @brief Sends a message to the message queue.
341 *
342 * @param[in, out] the_message_queue The message queue to send a message to.
343 * @param buffer The starting address of the message to send.
344 * @param sizeis The size of the message being send.
345 * @param wait Indicates whether the calling thread is willing to block
346 *        if the message queue is full.
347 * @param queue_context The thread queue context used for
348 *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
349 *
350 * @retval STATUS_SUCCESSFUL The message was successfully submitted to the message queue.
351 * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
352 * @retval STATUS_TOO_MANY No message buffers were available.
353 * @retval STATUS_MESSAGE_QUEUE_WAIT_IN_ISR The caller is in an ISR, do not block!
354 * @retval STATUS_TIMEOUT A timeout occurred.
355 */
356RTEMS_INLINE_ROUTINE Status_Control _CORE_message_queue_Send(
357  CORE_message_queue_Control       *the_message_queue,
358  const void                       *buffer,
359  size_t                            size,
360  bool                              wait,
361  Thread_queue_Context             *queue_context
362)
363{
364  return _CORE_message_queue_Submit(
365    the_message_queue,
366    _Thread_Executing,
367    buffer,
368    size,
369    CORE_MESSAGE_QUEUE_SEND_REQUEST,
370    wait,
371    queue_context
372  );
373}
374
375/**
376 * @brief Sends an urgent message to the message queue.
377 *
378 * @param[in, out] the_message_queue The message queue to send an urgent message to.
379 * @param buffer The starting address of the message to send.
380 * @param sizeis The size of the message being send.
381 * @param wait Indicates whether the calling thread is willing to block
382 *        if the message queue is full.
383 * @param queue_context The thread queue context used for
384 *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
385 *
386 * @retval STATUS_SUCCESSFUL The message was successfully submitted to the message queue.
387 * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
388 * @retval STATUS_TOO_MANY No message buffers were available.
389 * @retval STATUS_MESSAGE_QUEUE_WAIT_IN_ISR The caller is in an ISR, do not block!
390 * @retval STATUS_TIMEOUT A timeout occurred.
391 */
392RTEMS_INLINE_ROUTINE Status_Control _CORE_message_queue_Urgent(
393  CORE_message_queue_Control       *the_message_queue,
394  const void                       *buffer,
395  size_t                            size,
396  bool                              wait,
397  Thread_queue_Context             *queue_context
398)
399{
400  return _CORE_message_queue_Submit(
401    the_message_queue,
402    _Thread_Executing,
403    buffer,
404    size,
405    CORE_MESSAGE_QUEUE_URGENT_REQUEST,
406    wait,
407    queue_context
408  );
409}
410
411/**
412 * @brief Acquires the message queue.
413 *
414 * @param[in, out] the_message_queue Rhe message queue to acquire.
415 * @param queue_context The thread queue context.
416 */
417RTEMS_INLINE_ROUTINE void _CORE_message_queue_Acquire(
418  CORE_message_queue_Control *the_message_queue,
419  Thread_queue_Context       *queue_context
420)
421{
422  _Thread_queue_Acquire( &the_message_queue->Wait_queue, queue_context );
423}
424
425/**
426 * @brief Acquires the message queue critical.
427 *
428 * @param[in, out] the_message_queue The message queue to acquire critical.
429 * @param queue_context The thread queue context.
430 */
431RTEMS_INLINE_ROUTINE void _CORE_message_queue_Acquire_critical(
432  CORE_message_queue_Control *the_message_queue,
433  Thread_queue_Context       *queue_context
434)
435{
436  _Thread_queue_Acquire_critical( &the_message_queue->Wait_queue, queue_context );
437}
438
439/**
440 * @brief Releases the message queue.
441 *
442 * @param[in, out] the_message_queue The message queue to release.
443 * @param queue_context The thread queue context.
444 */
445RTEMS_INLINE_ROUTINE void _CORE_message_queue_Release(
446  CORE_message_queue_Control *the_message_queue,
447  Thread_queue_Context       *queue_context
448)
449{
450  _Thread_queue_Release( &the_message_queue->Wait_queue, queue_context );
451}
452
453/**
454 * @brief Copies the source message buffer to the destination message buffer.
455 *
456 * This routine copies the contents of the source message buffer
457 * to the destination message buffer.
458 *
459 * @param source The source message buffer to be copied.
460 * @param[out] destination The destination messag buffer to copy the source to.
461 * @param size The size of the source buffer.
462 */
463RTEMS_INLINE_ROUTINE void _CORE_message_queue_Copy_buffer (
464  const void *source,
465  void       *destination,
466  size_t      size
467)
468{
469  memcpy(destination, source, size);
470}
471
472/**
473 * @brief Allocates a message buffer from the inactive message buffer chain.
474 *
475 * This function allocates a message buffer from the inactive
476 * message buffer chain.
477 *
478 * @param the_message_queue The message queue to operate upon.
479 *
480 * @retval pointer The allocated message buffer.
481 * @retval NULL The inactive message buffer chain is empty.
482 */
483RTEMS_INLINE_ROUTINE CORE_message_queue_Buffer *
484_CORE_message_queue_Allocate_message_buffer (
485    CORE_message_queue_Control *the_message_queue
486)
487{
488   return (CORE_message_queue_Buffer *)
489     _Chain_Get_unprotected( &the_message_queue->Inactive_messages );
490}
491
492/**
493 * @brief Frees a message buffer to inactive message buffer chain.
494 *
495 * This routine frees a message buffer to the inactive
496 * message buffer chain.
497 *
498 * @param[in, out] the_message_queue The message queue to free the message buffer to.
499 * @param[out] the_message The message to be freed.
500 */
501RTEMS_INLINE_ROUTINE void _CORE_message_queue_Free_message_buffer (
502  CORE_message_queue_Control *the_message_queue,
503  CORE_message_queue_Buffer  *the_message
504)
505{
506  _Chain_Append_unprotected( &the_message_queue->Inactive_messages, &the_message->Node );
507}
508
509/**
510 * @brief Gets message priority.
511 *
512 * This function returns the priority of @a the_message.
513 *
514 * @param the_message The message to obtain the priority from.
515 *
516 * @retval priority The priority of this message.
517 * @retval 0 Message priority is disabled.
518 *
519 * @note It encapsulates the optional behavior that message priority is
520 *       disabled if no API requires it.
521 */
522RTEMS_INLINE_ROUTINE int _CORE_message_queue_Get_message_priority (
523  const CORE_message_queue_Buffer *the_message
524)
525{
526  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
527    return the_message->priority;
528  #else
529    return 0;
530  #endif
531}
532
533/**
534 * @brief Gets first message of message queue and removes it.
535 *
536 * This function removes the first message from the_message_queue
537 * and returns a pointer to it.
538 *
539 * @param[in, out] the_message_queue The message queue to get the first message from.
540 *
541 * @retval pointer The first message if the message queue is not empty.
542 * @retval NULL The message queue is empty.
543 */
544RTEMS_INLINE_ROUTINE
545  CORE_message_queue_Buffer *_CORE_message_queue_Get_pending_message (
546  CORE_message_queue_Control *the_message_queue
547)
548{
549  return (CORE_message_queue_Buffer *)
550    _Chain_Get_unprotected( &the_message_queue->Pending_messages );
551}
552
553#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
554  /**
555   * @brief Checks if notification is enabled.
556   *
557   * This function returns true if notification is enabled on this message
558   * queue and false otherwise.
559   *
560   * @param the_message_queue The message queue to check if the notification is enabled.
561   *
562   * @retval true Notification is enabled on this message queue.
563   * @retval false Notification is not enabled on this message queue.
564   */
565  RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_notify_enabled (
566    CORE_message_queue_Control *the_message_queue
567  )
568  {
569    return (the_message_queue->notify_handler != NULL);
570  }
571#endif
572
573/**
574 * @brief Initializes notification information.
575 *
576 * This routine initializes the notification information for
577 * @a the_message_queue.
578 *
579 * @param[out] the_message_queue The message queue to initialize the notification information.
580 * @param[out] the_handler The notification information for the message queue.
581 */
582#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
583  RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
584    CORE_message_queue_Control        *the_message_queue,
585    CORE_message_queue_Notify_Handler  the_handler
586  )
587  {
588    the_message_queue->notify_handler = the_handler;
589  }
590#else
591  /* turn it into nothing if not enabled */
592  #define _CORE_message_queue_Set_notify( the_message_queue, the_handler ) \
593    do { } while ( 0 )
594#endif
595
596/**
597 * @brief Gets the first locked thread waiting to receive and dequeues it.
598 *
599 * This method dequeues the first locked thread waiting to receive a message,
600 *      dequeues it and returns the corresponding Thread_Control.
601 *
602 * @param[in, out] the_message_queue The message queue to operate upon.
603 * @param buffer The buffer that is copied to the threads mutable_object.
604 * @param size The size of the buffer.
605 * @param submit_type Indicates whether the thread should be willing to block in the future.
606 * @param queue_context The thread queue context.
607 *
608 * @retval thread The Thread_Control for the first locked thread, if there is a locked thread.
609 * @retval NULL There are pending messages or no thread waiting to receive.
610 */
611RTEMS_INLINE_ROUTINE Thread_Control *_CORE_message_queue_Dequeue_receiver(
612  CORE_message_queue_Control      *the_message_queue,
613  const void                      *buffer,
614  size_t                           size,
615  CORE_message_queue_Submit_types  submit_type,
616  Thread_queue_Context            *queue_context
617)
618{
619  Thread_Control *the_thread;
620
621  /*
622   *  If there are pending messages, then there can't be threads
623   *  waiting for us to send them a message.
624   *
625   *  NOTE: This check is critical because threads can block on
626   *        send and receive and this ensures that we are broadcasting
627   *        the message to threads waiting to receive -- not to send.
628   */
629  if ( the_message_queue->number_of_pending_messages != 0 ) {
630    return NULL;
631  }
632
633  /*
634   *  There must be no pending messages if there is a thread waiting to
635   *  receive a message.
636   */
637  the_thread = _Thread_queue_First_locked(
638    &the_message_queue->Wait_queue,
639    the_message_queue->operations
640  );
641  if ( the_thread == NULL ) {
642    return NULL;
643  }
644
645   *(size_t *) the_thread->Wait.return_argument = size;
646   the_thread->Wait.count = (uint32_t) submit_type;
647
648  _CORE_message_queue_Copy_buffer(
649    buffer,
650    the_thread->Wait.return_argument_second.mutable_object,
651    size
652  );
653
654  _Thread_queue_Extract_critical(
655    &the_message_queue->Wait_queue.Queue,
656    the_message_queue->operations,
657    the_thread,
658    queue_context
659  );
660
661  return the_thread;
662}
663
664/** @} */
665
666#ifdef __cplusplus
667}
668#endif
669
670#endif
671/* end of include file */
Note: See TracBrowser for help on using the repository browser.