source: rtems/cpukit/score/include/rtems/score/coremsgimpl.h @ 1e1a91ed

5
Last change on this file since 1e1a91ed was 1e1a91ed, checked in by Sebastian Huber <sebastian.huber@…>, on 03/23/16 at 09:01:31

score: Remove Thread_queue_Queue::operations field

Remove the Thread_queue_Queue::operations field to reduce the size of
this structure. Add a thread queue operations parameter to the
_Thread_queue_First(), _Thread_queue_First_locked(),
_Thread_queue_Enqueue(), _Thread_queue_Dequeue() and
_Thread_queue_Flush() functions. This is a preparation patch to reduce
the size of several synchronization objects.

  • Property mode set to 100644
File size: 20.4 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/threaddispatch.h>
25#include <rtems/score/threadqimpl.h>
26
27#include <limits.h>
28#include <string.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34/**
35 * @addtogroup ScoreMessageQueue
36 */
37/**@{**/
38
39/**
40 *  @brief Used when appending messages onto a message queue.
41 *
42 *  This is the priority constant used when appending messages onto
43 *  a message queue.
44 */
45#define  CORE_MESSAGE_QUEUE_SEND_REQUEST   INT_MAX
46
47/**
48 *  @brief Used when prepending messages onto a message queue.
49 *
50 *  This is the priority constant used when prepending messages onto
51 *  a message queue.
52 */
53#define  CORE_MESSAGE_QUEUE_URGENT_REQUEST INT_MIN
54
55/**
56 *  @brief The modes in which a message may be submitted to a message queue.
57 *
58 *  The following type details the modes in which a message
59 *  may be submitted to a message queue.  The message may be posted
60 *  in a send or urgent fashion.
61 *
62 *  @note  All other values are message priorities.  Numerically smaller
63 *         priorities indicate higher priority messages.
64 */
65typedef int CORE_message_queue_Submit_types;
66
67/**
68 *  @brief The possible set of Core Message Queue handler return statuses.
69 *
70 *  This enumerated type defines the possible set of Core Message
71 *  Queue handler return statuses.
72 */
73typedef enum {
74  /** This value indicates the operation completed sucessfully. */
75  CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL,
76  /** This value indicates that the message was too large for this queue. */
77  CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE,
78  /** This value indicates that there are too many messages pending. */
79  CORE_MESSAGE_QUEUE_STATUS_TOO_MANY,
80  /** This value indicates that a receive was unsuccessful. */
81  CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED,
82  /** This value indicates that a blocking send was unsuccessful. */
83  CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT,
84  /** This value indicates that the message queue being blocked upon
85   *  was deleted while the thread was waiting.
86   */
87  CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED,
88  /** This value indicates that the thread had to timeout while waiting
89   *  to receive a message because one did not become available.
90   */
91  CORE_MESSAGE_QUEUE_STATUS_TIMEOUT,
92  /** This value indicates that a blocking receive was unsuccessful. */
93  CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT
94}   CORE_message_queue_Status;
95
96/**
97 *  @brief Core message queue last status value.
98 *
99 *  This is the last status value.
100 */
101#define CORE_MESSAGE_QUEUE_STATUS_LAST CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT
102
103/**
104 *  @brief Callout provides to support global/multiprocessor operations.
105 *
106 *  The following type defines the callout which the API provides
107 *  to support global/multiprocessor operations on message_queues.
108 */
109typedef void ( *CORE_message_queue_API_mp_support_callout )(
110                 Thread_Control *,
111                 Objects_Id
112             );
113
114/**
115 *  @brief Initialize a message queue.
116 *
117 *  This package is the implementation of the CORE Message Queue Handler.
118 *  This core object provides task synchronization and communication functions
119 *  via messages passed to queue objects.
120 *
121 *  This routine initializes @a the_message_queue
122 *      based on the parameters passed.
123 *
124 *  @param[in] the_message_queue points to the message queue to initialize
125 *  @param[in] discipline the blocking discipline
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_Disciplines  discipline,
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 *  @param[in] lock_context The lock context of the interrupt disable.
176 *
177 *  @retval This method returns the number of message pending messages flushed.
178 */
179uint32_t   _CORE_message_queue_Flush(
180  CORE_message_queue_Control *the_message_queue,
181  ISR_lock_Context           *lock_context
182);
183
184#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
185/**
186 *  @brief Flush waiting threads.
187 *
188 *  This function flushes the threads which are blocked on
189 *  @a the_message_queue's pending message queue.  They are
190 *  unblocked whether blocked sending or receiving. It returns
191 *  the number of messages flushed from the queue.
192 *
193 *  @param[in] the_message_queue points to the message queue to flush
194 *  @retval number of messages flushed from the queue
195 */
196  void _CORE_message_queue_Flush_waiting_threads(
197    CORE_message_queue_Control *the_message_queue
198  );
199#endif
200
201/**
202 *  @brief Broadcast a message to the message queue.
203 *
204 *  This package is the implementation of the CORE Message Queue Handler.
205 *  This core object provides task synchronization and communication functions
206 *  via messages passed to queue objects.
207 *
208 *  This function sends a message for every thread waiting on the queue and
209 *  returns the number of threads made ready by the message.
210 *
211 *  @param[in] the_message_queue points to the message queue
212 *  @param[in] buffer is the starting address of the message to broadcast
213 *  @param[in] size is the size of the message being broadcast
214 *  @param[in] id is the RTEMS object Id associated with this message queue.
215 *         It is used when unblocking a remote thread.
216 *  @param[in] api_message_queue_mp_support is the routine to invoke if
217 *         a thread that is unblocked is actually a remote thread.
218 *  @param[out] count points to the variable that will contain the
219 *         number of tasks that are sent this message
220 *  @param[in] lock_context The lock context of the interrupt disable.
221 *  @retval @a *count will contain the number of messages sent
222 *  @retval indication of the successful completion or reason for failure
223 */
224CORE_message_queue_Status _CORE_message_queue_Broadcast(
225  CORE_message_queue_Control                *the_message_queue,
226  const void                                *buffer,
227  size_t                                     size,
228  Objects_Id                                 id,
229  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
230  uint32_t                                  *count,
231  ISR_lock_Context                          *lock_context
232);
233
234/**
235 *  @brief Submit a message to the message queue.
236 *
237 *  This routine implements the send and urgent message functions. It
238 *  processes a message that is to be submitted to the designated
239 *  message queue.  The message will either be processed as a
240 *  send message which it will be inserted at the rear of the queue
241 *  or it will be processed as an urgent message which will be inserted
242 *  at the front of the queue.
243 *
244 *  @param[in] the_message_queue points to the message queue
245 *  @param[in] buffer is the starting address of the message to send
246 *  @param[in] size is the size of the message being send
247 *  @param[in] id is the RTEMS object Id associated with this message queue.
248 *         It is used when unblocking a remote thread.
249 *  @param[in] api_message_queue_mp_support is the routine to invoke if
250 *         a thread that is unblocked is actually a remote thread.
251 *  @param[in] submit_type determines whether the message is prepended,
252 *         appended, or enqueued in priority order.
253 *  @param[in] wait indicates whether the calling thread is willing to block
254 *         if the message queue is full.
255 *  @param[in] timeout is the maximum number of clock ticks that the calling
256 *         thread is willing to block if the message queue is full.
257 *  @param[in] lock_context The lock context of the interrupt disable.
258 *  @retval indication of the successful completion or reason for failure
259 */
260CORE_message_queue_Status _CORE_message_queue_Submit(
261  CORE_message_queue_Control                *the_message_queue,
262  Thread_Control                            *executing,
263  const void                                *buffer,
264  size_t                                     size,
265  Objects_Id                                 id,
266  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
267  CORE_message_queue_Submit_types            submit_type,
268  bool                                       wait,
269  Watchdog_Interval                          timeout,
270  ISR_lock_Context                          *lock_context
271);
272
273/**
274 *  @brief Size a message from the message queue.
275 *
276 *  This package is the implementation of the CORE Message Queue Handler.
277 *  This core object provides task synchronization and communication functions
278 *  via messages passed to queue objects.
279 *
280 *  This kernel routine dequeues a message, copies the message buffer to
281 *  a given destination buffer, and frees the message buffer to the
282 *  inactive message pool.  The thread will be blocked if wait is true,
283 *  otherwise an error will be given to the thread if no messages are available.
284 *
285 *  @param[in] the_message_queue points to the message queue
286 *  @param[in] id is the RTEMS object Id associated with this message queue.
287 *         It is used when unblocking a remote thread.
288 *  @param[in] buffer is the starting address of the message buffer to
289 *         to be filled in with a message
290 *  @param[in] size_p is a pointer to the size of the @a buffer and
291 *         indicates the maximum size message that the caller can receive.
292 *  @param[in] wait indicates whether the calling thread is willing to block
293 *         if the message queue is empty.
294 *  @param[in] timeout is the maximum number of clock ticks that the calling
295 *         thread is willing to block if the message queue is empty.
296 *  @param[in] lock_context The lock context of the interrupt disable.
297 *
298 *  @retval indication of the successful completion or reason for failure.
299 *          On success, the location pointed to @a size_p will contain the
300 *          size of the received message.
301 *
302 *  @note Returns message priority via return area in TCB.
303 *
304 *  - INTERRUPT LATENCY:
305 *    + available
306 *    + wait
307 */
308void _CORE_message_queue_Seize(
309  CORE_message_queue_Control      *the_message_queue,
310  Thread_Control                  *executing,
311  Objects_Id                       id,
312  void                            *buffer,
313  size_t                          *size_p,
314  bool                             wait,
315  Watchdog_Interval                timeout,
316  ISR_lock_Context                *lock_context
317);
318
319/**
320 *  @brief Insert a message into the message queue.
321 *
322 *  This kernel routine inserts the specified message into the
323 *  message queue.  It is assumed that the message has been filled
324 *  in before this routine is called.
325 *
326 *  @param[in] the_message_queue points to the message queue
327 *  @param[in] the_message is the message to enqueue
328 *  @param[in] submit_type determines whether the message is prepended,
329 *         appended, or enqueued in priority order.
330 *
331 *  - INTERRUPT LATENCY:
332 *    + insert
333 */
334void _CORE_message_queue_Insert_message(
335  CORE_message_queue_Control        *the_message_queue,
336  CORE_message_queue_Buffer_control *the_message,
337  CORE_message_queue_Submit_types    submit_type
338);
339
340/**
341 * This routine sends a message to the end of the specified message queue.
342 */
343RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Send(
344  CORE_message_queue_Control                *the_message_queue,
345  const void                                *buffer,
346  size_t                                     size,
347  Objects_Id                                 id,
348  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
349  bool                                       wait,
350  Watchdog_Interval                          timeout,
351  ISR_lock_Context                          *lock_context
352)
353{
354  return _CORE_message_queue_Submit(
355    the_message_queue,
356    _Thread_Executing,
357    buffer,
358    size,
359    id,
360    api_message_queue_mp_support,
361    CORE_MESSAGE_QUEUE_SEND_REQUEST,
362    wait,     /* sender may block */
363    timeout,  /* timeout interval */
364    lock_context
365  );
366}
367
368/**
369 * This routine sends a message to the front of the specified message queue.
370 */
371RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Urgent(
372  CORE_message_queue_Control                *the_message_queue,
373  const void                                *buffer,
374  size_t                                     size,
375  Objects_Id                                 id,
376  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
377  bool                                       wait,
378  Watchdog_Interval                          timeout,
379  ISR_lock_Context                          *lock_context
380)
381{
382  return _CORE_message_queue_Submit(
383    the_message_queue,
384    _Thread_Executing,
385    buffer,
386    size,
387    id,
388    api_message_queue_mp_support,
389    CORE_MESSAGE_QUEUE_URGENT_REQUEST,
390    wait,     /* sender may block */
391    timeout,  /* timeout interval */
392    lock_context
393 );
394}
395
396RTEMS_INLINE_ROUTINE void _CORE_message_queue_Acquire(
397  CORE_message_queue_Control *the_message_queue,
398  ISR_lock_Context           *lock_context
399)
400{
401  _Thread_queue_Acquire( &the_message_queue->Wait_queue, lock_context );
402}
403
404RTEMS_INLINE_ROUTINE void _CORE_message_queue_Acquire_critical(
405  CORE_message_queue_Control *the_message_queue,
406  ISR_lock_Context           *lock_context
407)
408{
409  _Thread_queue_Acquire_critical( &the_message_queue->Wait_queue, lock_context );
410
411  #if defined(RTEMS_MULTIPROCESSING)
412    /*
413     * In case RTEMS_MULTIPROCESSING is enabled, then we have to prevent
414     * deletion of the executing thread after the thread queue operations.
415     */
416    _Thread_Dispatch_disable();
417  #endif
418}
419
420RTEMS_INLINE_ROUTINE void _CORE_message_queue_Release(
421  CORE_message_queue_Control *the_message_queue,
422  ISR_lock_Context           *lock_context
423)
424{
425  _Thread_queue_Release( &the_message_queue->Wait_queue, lock_context );
426  #if defined(RTEMS_MULTIPROCESSING)
427    _Thread_Dispatch_enable( _Per_CPU_Get() );
428  #endif
429}
430
431/**
432 * This routine copies the contents of the source message buffer
433 * to the destination message buffer.
434 */
435RTEMS_INLINE_ROUTINE void _CORE_message_queue_Copy_buffer (
436  const void *source,
437  void       *destination,
438  size_t      size
439)
440{
441  memcpy(destination, source, size);
442}
443
444/**
445 * This function allocates a message buffer from the inactive
446 * message buffer chain.
447 */
448RTEMS_INLINE_ROUTINE CORE_message_queue_Buffer_control *
449_CORE_message_queue_Allocate_message_buffer (
450    CORE_message_queue_Control *the_message_queue
451)
452{
453   return (CORE_message_queue_Buffer_control *)
454     _Chain_Get_unprotected( &the_message_queue->Inactive_messages );
455}
456
457/**
458 * This routine frees a message buffer to the inactive
459 * message buffer chain.
460 */
461RTEMS_INLINE_ROUTINE void _CORE_message_queue_Free_message_buffer (
462  CORE_message_queue_Control        *the_message_queue,
463  CORE_message_queue_Buffer_control *the_message
464)
465{
466  _Chain_Append_unprotected( &the_message_queue->Inactive_messages, &the_message->Node );
467}
468
469/**
470 * This function returns the priority of @a the_message.
471 *
472 * @note It encapsulates the optional behavior that message priority is
473 *       disabled if no API requires it.
474 */
475RTEMS_INLINE_ROUTINE int _CORE_message_queue_Get_message_priority (
476  const CORE_message_queue_Buffer_control *the_message
477)
478{
479  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
480    return the_message->priority;
481  #else
482    return 0;
483  #endif
484}
485
486/**
487 * This function sets the priority of @a the_message.
488 *
489 * @note It encapsulates the optional behavior that message priority is
490 *       disabled if no API requires it.
491 */
492RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_message_priority (
493  CORE_message_queue_Buffer_control *the_message,
494  int                                priority
495)
496{
497  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
498    the_message->priority = priority;
499  #endif
500}
501
502/**
503 * This function removes the first message from the_message_queue
504 * and returns a pointer to it.
505 */
506RTEMS_INLINE_ROUTINE
507  CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message (
508  CORE_message_queue_Control *the_message_queue
509)
510{
511  return (CORE_message_queue_Buffer_control *)
512    _Chain_Get_unprotected( &the_message_queue->Pending_messages );
513}
514
515#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
516  /**
517   * This function returns true if notification is enabled on this message
518   * queue and false otherwise.
519   */
520  RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_notify_enabled (
521    CORE_message_queue_Control *the_message_queue
522  )
523  {
524    return (the_message_queue->notify_handler != NULL);
525  }
526#endif
527
528/**
529 * This routine initializes the notification information for
530 * @a the_message_queue.
531 */
532#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
533  RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
534    CORE_message_queue_Control        *the_message_queue,
535    CORE_message_queue_Notify_Handler  the_handler,
536    void                              *the_argument
537  )
538  {
539    the_message_queue->notify_handler  = the_handler;
540    the_message_queue->notify_argument = the_argument;
541  }
542#else
543  /* turn it into nothing if not enabled */
544  #define _CORE_message_queue_Set_notify( \
545           the_message_queue, the_handler, the_argument )
546#endif
547
548RTEMS_INLINE_ROUTINE Thread_Control *_CORE_message_queue_Dequeue_receiver(
549  CORE_message_queue_Control      *the_message_queue,
550  const void                      *buffer,
551  size_t                           size,
552  CORE_message_queue_Submit_types  submit_type,
553  ISR_lock_Context                *lock_context
554)
555{
556  Thread_Control *the_thread;
557
558  /*
559   *  If there are pending messages, then there can't be threads
560   *  waiting for us to send them a message.
561   *
562   *  NOTE: This check is critical because threads can block on
563   *        send and receive and this ensures that we are broadcasting
564   *        the message to threads waiting to receive -- not to send.
565   */
566  if ( the_message_queue->number_of_pending_messages != 0 ) {
567    return NULL;
568  }
569
570  /*
571   *  There must be no pending messages if there is a thread waiting to
572   *  receive a message.
573   */
574  the_thread = _Thread_queue_First_locked(
575    &the_message_queue->Wait_queue,
576    the_message_queue->operations
577  );
578  if ( the_thread == NULL ) {
579    return NULL;
580  }
581
582   *(size_t *) the_thread->Wait.return_argument = size;
583   the_thread->Wait.count = (uint32_t) submit_type;
584
585  _CORE_message_queue_Copy_buffer(
586    buffer,
587    the_thread->Wait.return_argument_second.mutable_object,
588    size
589  );
590
591  _Thread_queue_Extract_critical(
592    &the_message_queue->Wait_queue.Queue,
593    the_message_queue->operations,
594    the_thread,
595    lock_context
596  );
597
598  return the_thread;
599}
600
601/** @} */
602
603#ifdef __cplusplus
604}
605#endif
606
607#endif
608/* end of include file */
Note: See TracBrowser for help on using the repository browser.