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

4.115
Last change on this file since d349e8a4 was d349e8a4, checked in by Sebastian Huber <sebastian.huber@…>, on 04/21/15 at 07:21:29

score: Fix priority message queue insert

Move the linear search into a critical section to avoid corruption due
to higher priority interrupts. The interrupt disable time depends now
on the count of pending messages.

Close #2328.

  • Property mode set to 100644
File size: 18.1 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/**
183 *  @brief Flush all outstanding messages.
184 *
185 *  This routine flushes all outstanding messages and returns
186 *  them to the inactive message chain.
187 *
188 *  @param[in] the_message_queue points to the message queue to flush
189 *
190 *  @retval This method returns the number of pending messages flushed.
191 *
192 *  - INTERRUPT LATENCY:
193 *    + single case
194 */
195uint32_t   _CORE_message_queue_Flush_support(
196  CORE_message_queue_Control *the_message_queue
197);
198
199#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
200/**
201 *  @brief Flush waiting threads.
202 *
203 *  This function flushes the threads which are blocked on
204 *  @a the_message_queue's pending message queue.  They are
205 *  unblocked whether blocked sending or receiving. It returns
206 *  the number of messages flushed from the queue.
207 *
208 *  @param[in] the_message_queue points to the message queue to flush
209 *  @retval number of messages flushed from the queue
210 */
211  void _CORE_message_queue_Flush_waiting_threads(
212    CORE_message_queue_Control *the_message_queue
213  );
214#endif
215
216/**
217 *  @brief Broadcast a message to the message queue.
218 *
219 *  This package is the implementation of the CORE Message Queue Handler.
220 *  This core object provides task synchronization and communication functions
221 *  via messages passed to queue objects.
222 *
223 *  This function sends a message for every thread waiting on the queue and
224 *  returns the number of threads made ready by the message.
225 *
226 *  @param[in] the_message_queue points to the message queue
227 *  @param[in] buffer is the starting address of the message to broadcast
228 *  @param[in] size is the size of the message being broadcast
229 *  @param[in] id is the RTEMS object Id associated with this message queue.
230 *         It is used when unblocking a remote thread.
231 *  @param[in] api_message_queue_mp_support is the routine to invoke if
232 *         a thread that is unblocked is actually a remote thread.
233 *  @param[out] count points to the variable that will contain the
234 *         number of tasks that are sent this message
235 *  @retval @a *count will contain the number of messages sent
236 *  @retval indication of the successful completion or reason for failure
237 */
238CORE_message_queue_Status _CORE_message_queue_Broadcast(
239  CORE_message_queue_Control                *the_message_queue,
240  const void                                *buffer,
241  size_t                                     size,
242  Objects_Id                                 id,
243  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
244  uint32_t                                  *count
245);
246
247/**
248 *  @brief Submit a message to the message queue.
249 *
250 *  This routine implements the send and urgent message functions. It
251 *  processes a message that is to be submitted to the designated
252 *  message queue.  The message will either be processed as a
253 *  send message which it will be inserted at the rear of the queue
254 *  or it will be processed as an urgent message which will be inserted
255 *  at the front of the queue.
256 *
257 *  @param[in] the_message_queue points to the message queue
258 *  @param[in] buffer is the starting address of the message to send
259 *  @param[in] size is the size of the message being send
260 *  @param[in] id is the RTEMS object Id associated with this message queue.
261 *         It is used when unblocking a remote thread.
262 *  @param[in] api_message_queue_mp_support is the routine to invoke if
263 *         a thread that is unblocked is actually a remote thread.
264 *  @param[in] submit_type determines whether the message is prepended,
265 *         appended, or enqueued in priority order.
266 *  @param[in] wait indicates whether the calling thread is willing to block
267 *         if the message queue is full.
268 *  @param[in] timeout is the maximum number of clock ticks that the calling
269 *         thread is willing to block if the message queue is full.
270 *  @retval indication of the successful completion or reason for failure
271 */
272CORE_message_queue_Status _CORE_message_queue_Submit(
273  CORE_message_queue_Control                *the_message_queue,
274  Thread_Control                            *executing,
275  const void                                *buffer,
276  size_t                                     size,
277  Objects_Id                                 id,
278  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
279  CORE_message_queue_Submit_types            submit_type,
280  bool                                       wait,
281  Watchdog_Interval                          timeout
282);
283
284/**
285 *  @brief Size a message from the message queue.
286 *
287 *  This package is the implementation of the CORE Message Queue Handler.
288 *  This core object provides task synchronization and communication functions
289 *  via messages passed to queue objects.
290 *
291 *  This kernel routine dequeues a message, copies the message buffer to
292 *  a given destination buffer, and frees the message buffer to the
293 *  inactive message pool.  The thread will be blocked if wait is true,
294 *  otherwise an error will be given to the thread if no messages are available.
295 *
296 *  @param[in] the_message_queue points to the message queue
297 *  @param[in] id is the RTEMS object Id associated with this message queue.
298 *         It is used when unblocking a remote thread.
299 *  @param[in] buffer is the starting address of the message buffer to
300 *         to be filled in with a message
301 *  @param[in] size_p is a pointer to the size of the @a buffer and
302 *         indicates the maximum size message that the caller can receive.
303 *  @param[in] wait indicates whether the calling thread is willing to block
304 *         if the message queue is empty.
305 *  @param[in] timeout is the maximum number of clock ticks that the calling
306 *         thread is willing to block if the message queue is empty.
307 *
308 *  @retval indication of the successful completion or reason for failure.
309 *          On success, the location pointed to @a size_p will contain the
310 *          size of the received message.
311 *
312 *  @note Returns message priority via return area in TCB.
313 *
314 *  - INTERRUPT LATENCY:
315 *    + available
316 *    + wait
317 */
318void _CORE_message_queue_Seize(
319  CORE_message_queue_Control      *the_message_queue,
320  Thread_Control                  *executing,
321  Objects_Id                       id,
322  void                            *buffer,
323  size_t                          *size_p,
324  bool                             wait,
325  Watchdog_Interval                timeout
326);
327
328/**
329 *  @brief Insert a message into the message queue.
330 *
331 *  This kernel routine inserts the specified message into the
332 *  message queue.  It is assumed that the message has been filled
333 *  in before this routine is called.
334 *
335 *  @param[in] the_message_queue points to the message queue
336 *  @param[in] the_message is the message to enqueue
337 *  @param[in] submit_type determines whether the message is prepended,
338 *         appended, or enqueued in priority order.
339 *
340 *  - INTERRUPT LATENCY:
341 *    + insert
342 */
343void _CORE_message_queue_Insert_message(
344  CORE_message_queue_Control        *the_message_queue,
345  CORE_message_queue_Buffer_control *the_message,
346  CORE_message_queue_Submit_types    submit_type
347);
348
349/**
350 * This routine sends a message to the end of the specified message queue.
351 */
352RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Send(
353  CORE_message_queue_Control                *the_message_queue,
354  const void                                *buffer,
355  size_t                                     size,
356  Objects_Id                                 id,
357  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
358  bool                                    wait,
359  Watchdog_Interval                          timeout
360)
361{
362  return _CORE_message_queue_Submit(
363    the_message_queue,
364    _Thread_Executing,
365    buffer,
366    size,
367    id,
368    api_message_queue_mp_support,
369    CORE_MESSAGE_QUEUE_SEND_REQUEST,
370    wait,     /* sender may block */
371    timeout   /* timeout interval */
372  );
373}
374
375/**
376 * This routine sends a message to the front of the specified message queue.
377 */
378RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Urgent(
379  CORE_message_queue_Control                *the_message_queue,
380  const void                                *buffer,
381  size_t                                     size,
382  Objects_Id                                 id,
383  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
384  bool                                    wait,
385  Watchdog_Interval                          timeout
386)
387{
388  return _CORE_message_queue_Submit(
389    the_message_queue,
390    _Thread_Executing,
391    buffer,
392    size,
393    id,
394    api_message_queue_mp_support,
395    CORE_MESSAGE_QUEUE_URGENT_REQUEST,
396    wait,     /* sender may block */
397    timeout   /* timeout interval */
398 );
399}
400
401/**
402 * This routine copies the contents of the source message buffer
403 * to the destination message buffer.
404 */
405RTEMS_INLINE_ROUTINE void _CORE_message_queue_Copy_buffer (
406  const void *source,
407  void       *destination,
408  size_t      size
409)
410{
411  memcpy(destination, source, size);
412}
413
414/**
415 * This function allocates a message buffer from the inactive
416 * message buffer chain.
417 */
418RTEMS_INLINE_ROUTINE CORE_message_queue_Buffer_control *
419_CORE_message_queue_Allocate_message_buffer (
420    CORE_message_queue_Control *the_message_queue
421)
422{
423   return (CORE_message_queue_Buffer_control *)
424     _Chain_Get( &the_message_queue->Inactive_messages );
425}
426
427/**
428 * This routine frees a message buffer to the inactive
429 * message buffer chain.
430 */
431RTEMS_INLINE_ROUTINE void _CORE_message_queue_Free_message_buffer (
432  CORE_message_queue_Control        *the_message_queue,
433  CORE_message_queue_Buffer_control *the_message
434)
435{
436  _Chain_Append( &the_message_queue->Inactive_messages, &the_message->Node );
437}
438
439/**
440 * This function returns 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 int _CORE_message_queue_Get_message_priority (
446  const CORE_message_queue_Buffer_control *the_message
447)
448{
449  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
450    return the_message->priority;
451  #else
452    return 0;
453  #endif
454}
455
456/**
457 * This function sets the priority of @a the_message.
458 *
459 * @note It encapsulates the optional behavior that message priority is
460 *       disabled if no API requires it.
461 */
462RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_message_priority (
463  CORE_message_queue_Buffer_control *the_message,
464  int                                priority
465)
466{
467  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
468    the_message->priority = priority;
469  #endif
470}
471
472/**
473 * This function removes the first message from the_message_queue
474 * and returns a pointer to it.
475 */
476RTEMS_INLINE_ROUTINE
477  CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message (
478  CORE_message_queue_Control *the_message_queue
479)
480{
481  return (CORE_message_queue_Buffer_control *)
482    _Chain_Get_unprotected( &the_message_queue->Pending_messages );
483}
484
485/**
486 * This function returns true if the priority attribute is
487 * enabled in the attribute_set and false otherwise.
488 */
489RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_priority(
490  CORE_message_queue_Attributes *the_attribute
491)
492{
493  return
494    (the_attribute->discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY);
495}
496
497#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
498  /**
499   * This function returns true if notification is enabled on this message
500   * queue and false otherwise.
501   */
502  RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_notify_enabled (
503    CORE_message_queue_Control *the_message_queue
504  )
505  {
506    return (the_message_queue->notify_handler != NULL);
507  }
508#endif
509
510/**
511 * This routine initializes the notification information for
512 * @a the_message_queue.
513 */
514#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
515  RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
516    CORE_message_queue_Control        *the_message_queue,
517    CORE_message_queue_Notify_Handler  the_handler,
518    void                              *the_argument
519  )
520  {
521    the_message_queue->notify_handler  = the_handler;
522    the_message_queue->notify_argument = the_argument;
523  }
524#else
525  /* turn it into nothing if not enabled */
526  #define _CORE_message_queue_Set_notify( \
527           the_message_queue, the_handler, the_argument )
528#endif
529
530/** @} */
531
532#ifdef __cplusplus
533}
534#endif
535
536#endif
537/* end of include file */
Note: See TracBrowser for help on using the repository browser.