source: rtems/cpukit/include/rtems/score/coremsgimpl.h @ 4c20da4

Last change on this file since 4c20da4 was 4c20da4, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 4, 2019 at 7:18:11 AM

doxygen: Rename Score* groups in RTEMSScore*

Update #3706

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