source: rtems/cpukit/score/include/rtems/score/coremsgimpl.h @ c654b525

4.11
Last change on this file since c654b525 was c654b525, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 30, 2015 at 11:18:45 AM

score: Delete _CORE_message_queue_Flush_support()

Check the number of pending messages in _CORE_message_queue_Flush() to
avoid race conditions.

  • Property mode set to 100644
File size: 17.7 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/chainimpl.h>
24#include <rtems/score/threadqimpl.h>
25
26#include <limits.h>
27#include <string.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/**
34 * @addtogroup ScoreMessageQueue
35 */
36/**@{**/
37
38/**
39 *  @brief Used when appending messages onto a message queue.
40 *
41 *  This is the priority constant used when appending messages onto
42 *  a message queue.
43 */
44#define  CORE_MESSAGE_QUEUE_SEND_REQUEST   INT_MAX
45
46/**
47 *  @brief Used when prepending messages onto a message queue.
48 *
49 *  This is the priority constant used when prepending messages onto
50 *  a message queue.
51 */
52#define  CORE_MESSAGE_QUEUE_URGENT_REQUEST INT_MIN
53
54/**
55 *  @brief The modes in which a message may be submitted to a message queue.
56 *
57 *  The following type details the modes in which a message
58 *  may be submitted to a message queue.  The message may be posted
59 *  in a send or urgent fashion.
60 *
61 *  @note  All other values are message priorities.  Numerically smaller
62 *         priorities indicate higher priority messages.
63 */
64typedef int CORE_message_queue_Submit_types;
65
66/**
67 *  @brief The possible set of Core Message Queue handler return statuses.
68 *
69 *  This enumerated type defines the possible set of Core Message
70 *  Queue handler return statuses.
71 */
72typedef enum {
73  /** This value indicates the operation completed sucessfully. */
74  CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL,
75  /** This value indicates that the message was too large for this queue. */
76  CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE,
77  /** This value indicates that there are too many messages pending. */
78  CORE_MESSAGE_QUEUE_STATUS_TOO_MANY,
79  /** This value indicates that a receive was unsuccessful. */
80  CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED,
81  /** This value indicates that a blocking send was unsuccessful. */
82  CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT,
83  /** This value indicates that the message queue being blocked upon
84   *  was deleted while the thread was waiting.
85   */
86  CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED,
87  /** This value indicates that the thread had to timeout while waiting
88   *  to receive a message because one did not become available.
89   */
90  CORE_MESSAGE_QUEUE_STATUS_TIMEOUT,
91  /** This value indicates that a blocking receive was unsuccessful. */
92  CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT
93}   CORE_message_queue_Status;
94
95/**
96 *  @brief Core message queue last status value.
97 *
98 *  This is the last status value.
99 */
100#define CORE_MESSAGE_QUEUE_STATUS_LAST CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT
101
102/**
103 *  @brief Callout provides to support global/multiprocessor operations.
104 *
105 *  The following type defines the callout which the API provides
106 *  to support global/multiprocessor operations on message_queues.
107 */
108typedef void ( *CORE_message_queue_API_mp_support_callout )(
109                 Thread_Control *,
110                 Objects_Id
111             );
112
113/**
114 *  @brief Initialize a message queue.
115 *
116 *  This package is the implementation of the CORE Message Queue Handler.
117 *  This core object provides task synchronization and communication functions
118 *  via messages passed to queue objects.
119 *
120 *  This routine initializes @a the_message_queue
121 *      based on the parameters passed.
122 *
123 *  @param[in] the_message_queue points to the message queue to initialize
124 *  @param[in] the_message_queue_attributes points to the attributes that
125 *         will be used with this message queue instance
126 *  @param[in] maximum_pending_messages is the maximum number of messages
127 *         that will be allowed to pend at any given time
128 *  @param[in] maximum_message_size is the size of largest message that
129 *         may be sent to this message queue instance
130 *
131 *  @retval true if the message queue can be initialized.  In general,
132 *         false will only be returned if memory for the pending
133 *         messages cannot be allocated.
134 */
135bool _CORE_message_queue_Initialize(
136  CORE_message_queue_Control    *the_message_queue,
137  CORE_message_queue_Attributes *the_message_queue_attributes,
138  uint32_t                       maximum_pending_messages,
139  size_t                         maximum_message_size
140);
141
142/**
143 *  @brief Close a message queue.
144 *
145 *  This package is the implementation of the CORE Message Queue Handler.
146 *  This core object provides task synchronization and communication functions
147 *  via messages passed to queue objects
148 *
149 *  This function closes a message by returning all allocated space and
150 *  flushing @a the_message_queue's task wait queue.
151 *
152 *  @param[in] the_message_queue points to the message queue to close
153 *  @param[in] remote_extract_callout is the routine to call for each thread
154 *         that is extracted from the set of waiting threads
155 *  @param[in] status is the status that each waiting thread will return
156 *         from it's blocking service
157 */
158void _CORE_message_queue_Close(
159  CORE_message_queue_Control *the_message_queue,
160  Thread_queue_Flush_callout  remote_extract_callout,
161  uint32_t                    status
162);
163
164/**
165 *  @brief Flush pending messages.
166 *
167 *  This package is the implementation of the CORE Message Queue Handler.
168 *  This core object provides task synchronization and communication functions
169 *  via messages passed to queue objects.
170 *
171 *  This function flushes @a the_message_queue's pending message queue.  The
172 *  number of messages flushed from the queue is returned.
173 *
174 *  @param[in] the_message_queue points to the message queue to flush
175 *
176 *  @retval This method returns the number of message pending messages flushed.
177 */
178uint32_t   _CORE_message_queue_Flush(
179  CORE_message_queue_Control *the_message_queue
180);
181
182#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
183/**
184 *  @brief Flush waiting threads.
185 *
186 *  This function flushes the threads which are blocked on
187 *  @a the_message_queue's pending message queue.  They are
188 *  unblocked whether blocked sending or receiving. It returns
189 *  the number of messages flushed from the queue.
190 *
191 *  @param[in] the_message_queue points to the message queue to flush
192 *  @retval number of messages flushed from the queue
193 */
194  void _CORE_message_queue_Flush_waiting_threads(
195    CORE_message_queue_Control *the_message_queue
196  );
197#endif
198
199/**
200 *  @brief Broadcast a message to the message queue.
201 *
202 *  This package is the implementation of the CORE Message Queue Handler.
203 *  This core object provides task synchronization and communication functions
204 *  via messages passed to queue objects.
205 *
206 *  This function sends a message for every thread waiting on the queue and
207 *  returns the number of threads made ready by the message.
208 *
209 *  @param[in] the_message_queue points to the message queue
210 *  @param[in] buffer is the starting address of the message to broadcast
211 *  @param[in] size is the size of the message being broadcast
212 *  @param[in] id is the RTEMS object Id associated with this message queue.
213 *         It is used when unblocking a remote thread.
214 *  @param[in] api_message_queue_mp_support is the routine to invoke if
215 *         a thread that is unblocked is actually a remote thread.
216 *  @param[out] count points to the variable that will contain the
217 *         number of tasks that are sent this message
218 *  @retval @a *count will contain the number of messages sent
219 *  @retval indication of the successful completion or reason for failure
220 */
221CORE_message_queue_Status _CORE_message_queue_Broadcast(
222  CORE_message_queue_Control                *the_message_queue,
223  const void                                *buffer,
224  size_t                                     size,
225  Objects_Id                                 id,
226  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
227  uint32_t                                  *count
228);
229
230/**
231 *  @brief Submit a message to the message queue.
232 *
233 *  This routine implements the send and urgent message functions. It
234 *  processes a message that is to be submitted to the designated
235 *  message queue.  The message will either be processed as a
236 *  send message which it will be inserted at the rear of the queue
237 *  or it will be processed as an urgent message which will be inserted
238 *  at the front of the queue.
239 *
240 *  @param[in] the_message_queue points to the message queue
241 *  @param[in] buffer is the starting address of the message to send
242 *  @param[in] size is the size of the message being send
243 *  @param[in] id is the RTEMS object Id associated with this message queue.
244 *         It is used when unblocking a remote thread.
245 *  @param[in] api_message_queue_mp_support is the routine to invoke if
246 *         a thread that is unblocked is actually a remote thread.
247 *  @param[in] submit_type determines whether the message is prepended,
248 *         appended, or enqueued in priority order.
249 *  @param[in] wait indicates whether the calling thread is willing to block
250 *         if the message queue is full.
251 *  @param[in] timeout is the maximum number of clock ticks that the calling
252 *         thread is willing to block if the message queue is full.
253 *  @retval indication of the successful completion or reason for failure
254 */
255CORE_message_queue_Status _CORE_message_queue_Submit(
256  CORE_message_queue_Control                *the_message_queue,
257  Thread_Control                            *executing,
258  const void                                *buffer,
259  size_t                                     size,
260  Objects_Id                                 id,
261  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
262  CORE_message_queue_Submit_types            submit_type,
263  bool                                       wait,
264  Watchdog_Interval                          timeout
265);
266
267/**
268 *  @brief Size a message from the message queue.
269 *
270 *  This package is the implementation of the CORE Message Queue Handler.
271 *  This core object provides task synchronization and communication functions
272 *  via messages passed to queue objects.
273 *
274 *  This kernel routine dequeues a message, copies the message buffer to
275 *  a given destination buffer, and frees the message buffer to the
276 *  inactive message pool.  The thread will be blocked if wait is true,
277 *  otherwise an error will be given to the thread if no messages are available.
278 *
279 *  @param[in] the_message_queue points to the message queue
280 *  @param[in] id is the RTEMS object Id associated with this message queue.
281 *         It is used when unblocking a remote thread.
282 *  @param[in] buffer is the starting address of the message buffer to
283 *         to be filled in with a message
284 *  @param[in] size_p is a pointer to the size of the @a buffer and
285 *         indicates the maximum size message that the caller can receive.
286 *  @param[in] wait indicates whether the calling thread is willing to block
287 *         if the message queue is empty.
288 *  @param[in] timeout is the maximum number of clock ticks that the calling
289 *         thread is willing to block if the message queue is empty.
290 *
291 *  @retval indication of the successful completion or reason for failure.
292 *          On success, the location pointed to @a size_p will contain the
293 *          size of the received message.
294 *
295 *  @note Returns message priority via return area in TCB.
296 *
297 *  - INTERRUPT LATENCY:
298 *    + available
299 *    + wait
300 */
301void _CORE_message_queue_Seize(
302  CORE_message_queue_Control      *the_message_queue,
303  Thread_Control                  *executing,
304  Objects_Id                       id,
305  void                            *buffer,
306  size_t                          *size_p,
307  bool                             wait,
308  Watchdog_Interval                timeout
309);
310
311/**
312 *  @brief Insert a message into the message queue.
313 *
314 *  This kernel routine inserts the specified message into the
315 *  message queue.  It is assumed that the message has been filled
316 *  in before this routine is called.
317 *
318 *  @param[in] the_message_queue points to the message queue
319 *  @param[in] the_message is the message to enqueue
320 *  @param[in] submit_type determines whether the message is prepended,
321 *         appended, or enqueued in priority order.
322 *
323 *  - INTERRUPT LATENCY:
324 *    + insert
325 */
326void _CORE_message_queue_Insert_message(
327  CORE_message_queue_Control        *the_message_queue,
328  CORE_message_queue_Buffer_control *the_message,
329  CORE_message_queue_Submit_types    submit_type
330);
331
332/**
333 * This routine sends a message to the end of the specified message queue.
334 */
335RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Send(
336  CORE_message_queue_Control                *the_message_queue,
337  const void                                *buffer,
338  size_t                                     size,
339  Objects_Id                                 id,
340  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
341  bool                                    wait,
342  Watchdog_Interval                          timeout
343)
344{
345  return _CORE_message_queue_Submit(
346    the_message_queue,
347    _Thread_Executing,
348    buffer,
349    size,
350    id,
351    api_message_queue_mp_support,
352    CORE_MESSAGE_QUEUE_SEND_REQUEST,
353    wait,     /* sender may block */
354    timeout   /* timeout interval */
355  );
356}
357
358/**
359 * This routine sends a message to the front of the specified message queue.
360 */
361RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Urgent(
362  CORE_message_queue_Control                *the_message_queue,
363  const void                                *buffer,
364  size_t                                     size,
365  Objects_Id                                 id,
366  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
367  bool                                    wait,
368  Watchdog_Interval                          timeout
369)
370{
371  return _CORE_message_queue_Submit(
372    the_message_queue,
373    _Thread_Executing,
374    buffer,
375    size,
376    id,
377    api_message_queue_mp_support,
378    CORE_MESSAGE_QUEUE_URGENT_REQUEST,
379    wait,     /* sender may block */
380    timeout   /* timeout interval */
381 );
382}
383
384/**
385 * This routine copies the contents of the source message buffer
386 * to the destination message buffer.
387 */
388RTEMS_INLINE_ROUTINE void _CORE_message_queue_Copy_buffer (
389  const void *source,
390  void       *destination,
391  size_t      size
392)
393{
394  memcpy(destination, source, size);
395}
396
397/**
398 * This function allocates a message buffer from the inactive
399 * message buffer chain.
400 */
401RTEMS_INLINE_ROUTINE CORE_message_queue_Buffer_control *
402_CORE_message_queue_Allocate_message_buffer (
403    CORE_message_queue_Control *the_message_queue
404)
405{
406   return (CORE_message_queue_Buffer_control *)
407     _Chain_Get( &the_message_queue->Inactive_messages );
408}
409
410/**
411 * This routine frees a message buffer to the inactive
412 * message buffer chain.
413 */
414RTEMS_INLINE_ROUTINE void _CORE_message_queue_Free_message_buffer (
415  CORE_message_queue_Control        *the_message_queue,
416  CORE_message_queue_Buffer_control *the_message
417)
418{
419  _Chain_Append( &the_message_queue->Inactive_messages, &the_message->Node );
420}
421
422/**
423 * This function returns the priority of @a the_message.
424 *
425 * @note It encapsulates the optional behavior that message priority is
426 *       disabled if no API requires it.
427 */
428RTEMS_INLINE_ROUTINE int _CORE_message_queue_Get_message_priority (
429  const CORE_message_queue_Buffer_control *the_message
430)
431{
432  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
433    return the_message->priority;
434  #else
435    return 0;
436  #endif
437}
438
439/**
440 * This function sets the priority of @a the_message.
441 *
442 * @note It encapsulates the optional behavior that message priority is
443 *       disabled if no API requires it.
444 */
445RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_message_priority (
446  CORE_message_queue_Buffer_control *the_message,
447  int                                priority
448)
449{
450  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
451    the_message->priority = priority;
452  #endif
453}
454
455/**
456 * This function removes the first message from the_message_queue
457 * and returns a pointer to it.
458 */
459RTEMS_INLINE_ROUTINE
460  CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message (
461  CORE_message_queue_Control *the_message_queue
462)
463{
464  return (CORE_message_queue_Buffer_control *)
465    _Chain_Get_unprotected( &the_message_queue->Pending_messages );
466}
467
468/**
469 * This function returns true if the priority attribute is
470 * enabled in the attribute_set and false otherwise.
471 */
472RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_priority(
473  CORE_message_queue_Attributes *the_attribute
474)
475{
476  return
477    (the_attribute->discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY);
478}
479
480#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
481  /**
482   * This function returns true if notification is enabled on this message
483   * queue and false otherwise.
484   */
485  RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_notify_enabled (
486    CORE_message_queue_Control *the_message_queue
487  )
488  {
489    return (the_message_queue->notify_handler != NULL);
490  }
491#endif
492
493/**
494 * This routine initializes the notification information for
495 * @a the_message_queue.
496 */
497#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
498  RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
499    CORE_message_queue_Control        *the_message_queue,
500    CORE_message_queue_Notify_Handler  the_handler,
501    void                              *the_argument
502  )
503  {
504    the_message_queue->notify_handler  = the_handler;
505    the_message_queue->notify_argument = the_argument;
506  }
507#else
508  /* turn it into nothing if not enabled */
509  #define _CORE_message_queue_Set_notify( \
510           the_message_queue, the_handler, the_argument )
511#endif
512
513/** @} */
514
515#ifdef __cplusplus
516}
517#endif
518
519#endif
520/* end of include file */
Note: See TracBrowser for help on using the repository browser.