source: rtems/cpukit/score/include/rtems/score/coremsgimpl.h @ 5cc6bf4

5
Last change on this file since 5cc6bf4 was 5cc6bf4, checked in by Sebastian Huber <sebastian.huber@…>, on 04/17/16 at 13:47:33

score: Simplify _CORE_message_queue_Close()

Drop status parameter since each caller used
CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED.

Remove superfluous _CORE_message_queue_Flush().

  • Property mode set to 100644
File size: 21.5 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 Initialize a message queue.
105 *
106 *  This package is the implementation of the CORE Message Queue Handler.
107 *  This core object provides task synchronization and communication functions
108 *  via messages passed to queue objects.
109 *
110 *  This routine initializes @a the_message_queue
111 *      based on the parameters passed.
112 *
113 *  @param[in] the_message_queue points to the message queue to initialize
114 *  @param[in] discipline the blocking discipline
115 *  @param[in] maximum_pending_messages is the maximum number of messages
116 *         that will be allowed to pend at any given time
117 *  @param[in] maximum_message_size is the size of largest message that
118 *         may be sent to this message queue instance
119 *
120 *  @retval true if the message queue can be initialized.  In general,
121 *         false will only be returned if memory for the pending
122 *         messages cannot be allocated.
123 */
124bool _CORE_message_queue_Initialize(
125  CORE_message_queue_Control     *the_message_queue,
126  CORE_message_queue_Disciplines  discipline,
127  uint32_t                        maximum_pending_messages,
128  size_t                          maximum_message_size
129);
130
131void _CORE_message_queue_Do_close(
132  CORE_message_queue_Control *the_message_queue
133#if defined(RTEMS_MULTIPROCESSING)
134  ,
135  Thread_queue_MP_callout     mp_callout,
136  Objects_Id                  mp_id
137#endif
138);
139
140/**
141 *  @brief Close a message queue.
142 *
143 *  This package is the implementation of the CORE Message Queue Handler.
144 *  This core object provides task synchronization and communication functions
145 *  via messages passed to queue objects
146 *
147 *  This function closes a message by returning all allocated space and
148 *  flushing @a the_message_queue's task wait queue.
149 *
150 *  @param[in] the_message_queue points to the message queue to close
151 *  @param[in] mp_callout is the routine to call for each thread
152 *         that is extracted from the set of waiting threads
153 *  @param[in] mp_id the object identifier of the message queue object
154 */
155#if defined(RTEMS_MULTIPROCESSING)
156  #define _CORE_message_queue_Close( \
157    the_message_queue, \
158    mp_callout, \
159    mp_id \
160  ) \
161    _CORE_message_queue_Do_close( \
162      the_message_queue, \
163      mp_callout, \
164      mp_id \
165    )
166#else
167  #define _CORE_message_queue_Close( \
168    the_message_queue, \
169    mp_callout, \
170    mp_id \
171  ) \
172    _CORE_message_queue_Do_close( \
173      the_message_queue \
174    )
175#endif
176
177/**
178 *  @brief Flush pending messages.
179 *
180 *  This package is the implementation of the CORE Message Queue Handler.
181 *  This core object provides task synchronization and communication functions
182 *  via messages passed to queue objects.
183 *
184 *  This function flushes @a the_message_queue's pending message queue.  The
185 *  number of messages flushed from the queue is returned.
186 *
187 *  @param[in] the_message_queue points to the message queue to flush
188 *  @param[in] lock_context The lock context of the interrupt disable.
189 *
190 *  @retval This method returns the number of message pending messages flushed.
191 */
192uint32_t   _CORE_message_queue_Flush(
193  CORE_message_queue_Control *the_message_queue,
194  ISR_lock_Context           *lock_context
195);
196
197#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
198/**
199 *  @brief Flush waiting threads.
200 *
201 *  This function flushes the threads which are blocked on
202 *  @a the_message_queue's pending message queue.  They are
203 *  unblocked whether blocked sending or receiving. It returns
204 *  the number of messages flushed from the queue.
205 *
206 *  @param[in] the_message_queue points to the message queue to flush
207 *  @retval number of messages flushed from the queue
208 */
209  void _CORE_message_queue_Flush_waiting_threads(
210    CORE_message_queue_Control *the_message_queue
211  );
212#endif
213
214CORE_message_queue_Status _CORE_message_queue_Do_broadcast(
215  CORE_message_queue_Control *the_message_queue,
216  const void                 *buffer,
217  size_t                      size,
218#if defined(RTEMS_MULTIPROCESSING)
219  Thread_queue_MP_callout     mp_callout,
220  Objects_Id                  mp_id,
221#endif
222  uint32_t                   *count,
223  ISR_lock_Context           *lock_context
224);
225
226/**
227 *  @brief Broadcast a message to the message queue.
228 *
229 *  This package is the implementation of the CORE Message Queue Handler.
230 *  This core object provides task synchronization and communication functions
231 *  via messages passed to queue objects.
232 *
233 *  This function sends a message for every thread waiting on the queue and
234 *  returns the number of threads made ready by the message.
235 *
236 *  @param[in] the_message_queue points to the message queue
237 *  @param[in] buffer is the starting address of the message to broadcast
238 *  @param[in] size is the size of the message being broadcast
239 *  @param[in] mp_callout is the routine to invoke if
240 *         a thread that is unblocked is actually a remote thread.
241 *  @param[in] mp_id is the RTEMS object Id associated with this message queue.
242 *         It is used when unblocking a remote thread.
243 *  @param[out] count points to the variable that will contain the
244 *         number of tasks that are sent this message
245 *  @param[in] lock_context The lock context of the interrupt disable.
246 *  @retval @a *count will contain the number of messages sent
247 *  @retval indication of the successful completion or reason for failure
248 */
249#if defined(RTEMS_MULTIPROCESSING)
250  #define _CORE_message_queue_Broadcast( \
251    the_message_queue, \
252    buffer, \
253    size, \
254    mp_callout, \
255    mp_id, \
256    count, \
257    lock_context \
258  ) \
259    _CORE_message_queue_Do_broadcast( \
260      the_message_queue, \
261      buffer, \
262      size, \
263      mp_callout, \
264      mp_id, \
265      count, \
266      lock_context \
267    )
268#else
269  #define _CORE_message_queue_Broadcast( \
270    the_message_queue, \
271    buffer, \
272    size, \
273    mp_callout, \
274    mp_id, \
275    count, \
276    lock_context \
277  ) \
278    _CORE_message_queue_Do_broadcast( \
279      the_message_queue, \
280      buffer, \
281      size, \
282      count, \
283      lock_context \
284    )
285#endif
286
287CORE_message_queue_Status _CORE_message_queue_Do_submit(
288  CORE_message_queue_Control       *the_message_queue,
289  Thread_Control                   *executing,
290  const void                       *buffer,
291  size_t                            size,
292#if defined(RTEMS_MULTIPROCESSING)
293  Thread_queue_MP_callout           mp_callout,
294  Objects_Id                        mp_id,
295#endif
296  CORE_message_queue_Submit_types   submit_type,
297  bool                              wait,
298  Watchdog_Interval                 timeout,
299  ISR_lock_Context                 *lock_context
300);
301
302/**
303 *  @brief Submit a message to the message queue.
304 *
305 *  This routine implements the send and urgent message functions. It
306 *  processes a message that is to be submitted to the designated
307 *  message queue.  The message will either be processed as a
308 *  send message which it will be inserted at the rear of the queue
309 *  or it will be processed as an urgent message which will be inserted
310 *  at the front of the queue.
311 *
312 *  @param[in] the_message_queue points to the message queue
313 *  @param[in] buffer is the starting address of the message to send
314 *  @param[in] size is the size of the message being send
315 *  @param[in] mp_callout is the routine to invoke if
316 *         a thread that is unblocked is actually a remote thread.
317 *  @param[in] mp_id is the RTEMS object Id associated with this message queue.
318 *         It is used when unblocking a remote thread.
319 *  @param[in] submit_type determines whether the message is prepended,
320 *         appended, or enqueued in priority order.
321 *  @param[in] wait indicates whether the calling thread is willing to block
322 *         if the message queue is full.
323 *  @param[in] timeout is the maximum number of clock ticks that the calling
324 *         thread is willing to block if the message queue is full.
325 *  @param[in] lock_context The lock context of the interrupt disable.
326 *  @retval indication of the successful completion or reason for failure
327 */
328#if defined(RTEMS_MULTIPROCESSING)
329  #define _CORE_message_queue_Submit( \
330    the_message_queue, \
331    executing, \
332    buffer, \
333    size, \
334    mp_callout, \
335    mp_id, \
336    submit_type, \
337    wait, \
338    timeout, \
339    lock_context \
340  ) \
341    _CORE_message_queue_Do_submit( \
342      the_message_queue, \
343      executing, \
344      buffer, \
345      size, \
346      mp_callout, \
347      mp_id, \
348      submit_type, \
349      wait, \
350      timeout, \
351      lock_context \
352    )
353#else
354  #define _CORE_message_queue_Submit( \
355    the_message_queue, \
356    executing, \
357    buffer, \
358    size, \
359    mp_callout, \
360    mp_id, \
361    submit_type, \
362    wait, \
363    timeout, \
364    lock_context \
365  ) \
366    _CORE_message_queue_Do_submit( \
367      the_message_queue, \
368      executing, \
369      buffer, \
370      size, \
371      submit_type, \
372      wait, \
373      timeout, \
374      lock_context \
375    )
376#endif
377
378/**
379 *  @brief Size a message from the message queue.
380 *
381 *  This package is the implementation of the CORE Message Queue Handler.
382 *  This core object provides task synchronization and communication functions
383 *  via messages passed to queue objects.
384 *
385 *  This kernel routine dequeues a message, copies the message buffer to
386 *  a given destination buffer, and frees the message buffer to the
387 *  inactive message pool.  The thread will be blocked if wait is true,
388 *  otherwise an error will be given to the thread if no messages are available.
389 *
390 *  @param[in] the_message_queue points to the message queue
391 *  @param[in] id is the RTEMS object Id associated with this message queue.
392 *         It is used when unblocking a remote thread.
393 *  @param[in] buffer is the starting address of the message buffer to
394 *         to be filled in with a message
395 *  @param[in] size_p is a pointer to the size of the @a buffer and
396 *         indicates the maximum size message that the caller can receive.
397 *  @param[in] wait indicates whether the calling thread is willing to block
398 *         if the message queue is empty.
399 *  @param[in] timeout is the maximum number of clock ticks that the calling
400 *         thread is willing to block if the message queue is empty.
401 *  @param[in] lock_context The lock context of the interrupt disable.
402 *
403 *  @retval indication of the successful completion or reason for failure.
404 *          On success, the location pointed to @a size_p will contain the
405 *          size of the received message.
406 *
407 *  @note Returns message priority via return area in TCB.
408 *
409 *  - INTERRUPT LATENCY:
410 *    + available
411 *    + wait
412 */
413void _CORE_message_queue_Seize(
414  CORE_message_queue_Control      *the_message_queue,
415  Thread_Control                  *executing,
416  Objects_Id                       id,
417  void                            *buffer,
418  size_t                          *size_p,
419  bool                             wait,
420  Watchdog_Interval                timeout,
421  ISR_lock_Context                *lock_context
422);
423
424/**
425 *  @brief Insert a message into the message queue.
426 *
427 *  This kernel routine inserts the specified message into the
428 *  message queue.  It is assumed that the message has been filled
429 *  in before this routine is called.
430 *
431 *  @param[in] the_message_queue points to the message queue
432 *  @param[in] the_message is the message to enqueue
433 *  @param[in] submit_type determines whether the message is prepended,
434 *         appended, or enqueued in priority order.
435 *
436 *  - INTERRUPT LATENCY:
437 *    + insert
438 */
439void _CORE_message_queue_Insert_message(
440  CORE_message_queue_Control        *the_message_queue,
441  CORE_message_queue_Buffer_control *the_message,
442  CORE_message_queue_Submit_types    submit_type
443);
444
445/**
446 * This routine sends a message to the end of the specified message queue.
447 */
448#define _CORE_message_queue_Send( \
449  the_message_queue, \
450  buffer, \
451  size, \
452  mp_callout, \
453  mp_id, \
454  wait, \
455  timeout, \
456  lock_context \
457) \
458  _CORE_message_queue_Submit( \
459    the_message_queue, \
460    _Thread_Executing, \
461    buffer, \
462    size, \
463    mp_callout, \
464    mp_id, \
465    CORE_MESSAGE_QUEUE_SEND_REQUEST, \
466    wait, \
467    timeout, \
468    lock_context \
469  )
470
471/**
472 * This routine sends a message to the front of the specified message queue.
473 */
474#define _CORE_message_queue_Urgent( \
475  the_message_queue, \
476  buffer, \
477  size, \
478  mp_callout, \
479  mp_id, \
480  wait, \
481  timeout, \
482  lock_context \
483) \
484  _CORE_message_queue_Submit( \
485    the_message_queue, \
486    _Thread_Executing, \
487    buffer, \
488    size, \
489    mp_callout, \
490    mp_id, \
491    CORE_MESSAGE_QUEUE_URGENT_REQUEST, \
492    wait,\
493    timeout, \
494    lock_context \
495 )
496
497RTEMS_INLINE_ROUTINE void _CORE_message_queue_Acquire(
498  CORE_message_queue_Control *the_message_queue,
499  ISR_lock_Context           *lock_context
500)
501{
502  _Thread_queue_Acquire( &the_message_queue->Wait_queue, lock_context );
503}
504
505RTEMS_INLINE_ROUTINE void _CORE_message_queue_Acquire_critical(
506  CORE_message_queue_Control *the_message_queue,
507  ISR_lock_Context           *lock_context
508)
509{
510  _Thread_queue_Acquire_critical( &the_message_queue->Wait_queue, lock_context );
511}
512
513RTEMS_INLINE_ROUTINE void _CORE_message_queue_Release(
514  CORE_message_queue_Control *the_message_queue,
515  ISR_lock_Context           *lock_context
516)
517{
518  _Thread_queue_Release( &the_message_queue->Wait_queue, lock_context );
519}
520
521/**
522 * This routine copies the contents of the source message buffer
523 * to the destination message buffer.
524 */
525RTEMS_INLINE_ROUTINE void _CORE_message_queue_Copy_buffer (
526  const void *source,
527  void       *destination,
528  size_t      size
529)
530{
531  memcpy(destination, source, size);
532}
533
534/**
535 * This function allocates a message buffer from the inactive
536 * message buffer chain.
537 */
538RTEMS_INLINE_ROUTINE CORE_message_queue_Buffer_control *
539_CORE_message_queue_Allocate_message_buffer (
540    CORE_message_queue_Control *the_message_queue
541)
542{
543   return (CORE_message_queue_Buffer_control *)
544     _Chain_Get_unprotected( &the_message_queue->Inactive_messages );
545}
546
547/**
548 * This routine frees a message buffer to the inactive
549 * message buffer chain.
550 */
551RTEMS_INLINE_ROUTINE void _CORE_message_queue_Free_message_buffer (
552  CORE_message_queue_Control        *the_message_queue,
553  CORE_message_queue_Buffer_control *the_message
554)
555{
556  _Chain_Append_unprotected( &the_message_queue->Inactive_messages, &the_message->Node );
557}
558
559/**
560 * This function returns the priority of @a the_message.
561 *
562 * @note It encapsulates the optional behavior that message priority is
563 *       disabled if no API requires it.
564 */
565RTEMS_INLINE_ROUTINE int _CORE_message_queue_Get_message_priority (
566  const CORE_message_queue_Buffer_control *the_message
567)
568{
569  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
570    return the_message->priority;
571  #else
572    return 0;
573  #endif
574}
575
576/**
577 * This function sets the priority of @a the_message.
578 *
579 * @note It encapsulates the optional behavior that message priority is
580 *       disabled if no API requires it.
581 */
582RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_message_priority (
583  CORE_message_queue_Buffer_control *the_message,
584  int                                priority
585)
586{
587  #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
588    the_message->priority = priority;
589  #endif
590}
591
592/**
593 * This function removes the first message from the_message_queue
594 * and returns a pointer to it.
595 */
596RTEMS_INLINE_ROUTINE
597  CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message (
598  CORE_message_queue_Control *the_message_queue
599)
600{
601  return (CORE_message_queue_Buffer_control *)
602    _Chain_Get_unprotected( &the_message_queue->Pending_messages );
603}
604
605#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
606  /**
607   * This function returns true if notification is enabled on this message
608   * queue and false otherwise.
609   */
610  RTEMS_INLINE_ROUTINE bool _CORE_message_queue_Is_notify_enabled (
611    CORE_message_queue_Control *the_message_queue
612  )
613  {
614    return (the_message_queue->notify_handler != NULL);
615  }
616#endif
617
618/**
619 * This routine initializes the notification information for
620 * @a the_message_queue.
621 */
622#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
623  RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
624    CORE_message_queue_Control        *the_message_queue,
625    CORE_message_queue_Notify_Handler  the_handler,
626    void                              *the_argument
627  )
628  {
629    the_message_queue->notify_handler  = the_handler;
630    the_message_queue->notify_argument = the_argument;
631  }
632#else
633  /* turn it into nothing if not enabled */
634  #define _CORE_message_queue_Set_notify( \
635           the_message_queue, the_handler, the_argument )
636#endif
637
638RTEMS_INLINE_ROUTINE Thread_Control *_CORE_message_queue_Do_dequeue_receiver(
639  CORE_message_queue_Control      *the_message_queue,
640  const void                      *buffer,
641  size_t                           size,
642#if defined(RTEMS_MULTIPROCESSING)
643  Thread_queue_MP_callout          mp_callout,
644  Objects_Id                       mp_id,
645#endif
646  CORE_message_queue_Submit_types  submit_type,
647  ISR_lock_Context                *lock_context
648)
649{
650  Thread_Control *the_thread;
651
652  /*
653   *  If there are pending messages, then there can't be threads
654   *  waiting for us to send them a message.
655   *
656   *  NOTE: This check is critical because threads can block on
657   *        send and receive and this ensures that we are broadcasting
658   *        the message to threads waiting to receive -- not to send.
659   */
660  if ( the_message_queue->number_of_pending_messages != 0 ) {
661    return NULL;
662  }
663
664  /*
665   *  There must be no pending messages if there is a thread waiting to
666   *  receive a message.
667   */
668  the_thread = _Thread_queue_First_locked(
669    &the_message_queue->Wait_queue,
670    the_message_queue->operations
671  );
672  if ( the_thread == NULL ) {
673    return NULL;
674  }
675
676   *(size_t *) the_thread->Wait.return_argument = size;
677   the_thread->Wait.count = (uint32_t) submit_type;
678
679  _CORE_message_queue_Copy_buffer(
680    buffer,
681    the_thread->Wait.return_argument_second.mutable_object,
682    size
683  );
684
685  _Thread_queue_Extract_critical(
686    &the_message_queue->Wait_queue.Queue,
687    the_message_queue->operations,
688    the_thread,
689    mp_callout,
690    mp_id,
691    lock_context
692  );
693
694  return the_thread;
695}
696
697#if defined(RTEMS_MULTIPROCESSING)
698  #define _CORE_message_queue_Dequeue_receiver( \
699    the_message_queue, \
700    buffer, \
701    size, \
702    mp_callout, \
703    mp_id, \
704    submit_type, \
705    lock_context \
706  ) \
707    _CORE_message_queue_Do_dequeue_receiver( \
708      the_message_queue, \
709      buffer, \
710      size, \
711      mp_callout, \
712      mp_id, \
713      submit_type, \
714      lock_context \
715    )
716#else
717  #define _CORE_message_queue_Dequeue_receiver( \
718    the_message_queue, \
719    buffer, \
720    size, \
721    mp_callout, \
722    mp_id, \
723    submit_type, \
724    lock_context \
725  ) \
726    _CORE_message_queue_Do_dequeue_receiver( \
727      the_message_queue, \
728      buffer, \
729      size, \
730      submit_type, \
731      lock_context \
732    )
733#endif
734
735/** @} */
736
737#ifdef __cplusplus
738}
739#endif
740
741#endif
742/* end of include file */
Note: See TracBrowser for help on using the repository browser.