source: rtems/cpukit/include/rtems/score/coremsgimpl.h @ 0865cd2

Last change on this file since 0865cd2 was 0865cd2, checked in by Andreas Dachsberger <andreas.dachsberger@…>, on Apr 5, 2019 at 10:39:51 AM

doxygen: score: adjust doc in coremsgimpl.h to doxygen guidelines

Update #3706.

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