mq_receive.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /****************************************************************************
  2. * sched/mqueue/mq_receive.c
  3. *
  4. * Copyright (C) 2007, 2009, 2016-2017 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <stdbool.h>
  41. #include <errno.h>
  42. #include <mqueue.h>
  43. #include <debug.h>
  44. #include <nuttx/irq.h>
  45. #include <nuttx/arch.h>
  46. #include <nuttx/mqueue.h>
  47. #include <nuttx/cancelpt.h>
  48. #include "mqueue/mqueue.h"
  49. /****************************************************************************
  50. * Public Functions
  51. ****************************************************************************/
  52. /****************************************************************************
  53. * Name: nxmq_receive
  54. *
  55. * Description:
  56. * This function receives the oldest of the highest priority messages
  57. * from the message queue specified by "mqdes." This is an internal OS
  58. * interface. It is functionally equivalent to mq_receive except that:
  59. *
  60. * - It is not a cancellation point, and
  61. * - It does not modify the errno value.
  62. *
  63. * See comments with mq_receive() for a more complete description of the
  64. * behavior of this function
  65. *
  66. * Input Parameters:
  67. * mqdes - Message Queue Descriptor
  68. * msg - Buffer to receive the message
  69. * msglen - Size of the buffer in bytes
  70. * prio - If not NULL, the location to store message priority.
  71. *
  72. * Returned Value:
  73. * This is an internal OS interface and should not be used by applications.
  74. * It follows the NuttX internal error return policy: Zero (OK) is
  75. * returned on success. A negated errno value is returned on failure.
  76. * (see mq_receive() for the list list valid return values).
  77. *
  78. ****************************************************************************/
  79. ssize_t nxmq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
  80. FAR unsigned int *prio)
  81. {
  82. FAR struct mqueue_msg_s *mqmsg;
  83. irqstate_t flags;
  84. ssize_t ret;
  85. DEBUGASSERT(up_interrupt_context() == false);
  86. /* Verify the input parameters and, in case of an error, set
  87. * errno appropriately.
  88. */
  89. ret = nxmq_verify_receive(mqdes, msg, msglen);
  90. if (ret < 0)
  91. {
  92. return ret;
  93. }
  94. /* Get the next message from the message queue. We will disable
  95. * pre-emption until we have completed the message received. This
  96. * is not too bad because if the receipt takes a long time, it will
  97. * be because we are blocked waiting for a message and pre-emption
  98. * will be re-enabled while we are blocked
  99. */
  100. sched_lock();
  101. /* Furthermore, nxmq_wait_receive() expects to have interrupts disabled
  102. * because messages can be sent from interrupt level.
  103. */
  104. flags = enter_critical_section();
  105. /* Get the message from the message queue */
  106. ret = nxmq_wait_receive(mqdes, &mqmsg);
  107. leave_critical_section(flags);
  108. /* Check if we got a message from the message queue. We might
  109. * not have a message if:
  110. *
  111. * - The message queue is empty and O_NONBLOCK is set in the mqdes
  112. * - The wait was interrupted by a signal
  113. */
  114. if (ret >= 0)
  115. {
  116. DEBUGASSERT(mqmsg != NULL);
  117. ret = nxmq_do_receive(mqdes, mqmsg, msg, prio);
  118. }
  119. sched_unlock();
  120. return ret;
  121. }
  122. /****************************************************************************
  123. * Name: mq_receive
  124. *
  125. * Description:
  126. * This function receives the oldest of the highest priority messages
  127. * from the message queue specified by "mqdes." If the size of the
  128. * buffer in bytes (msglen) is less than the "mq_msgsize" attribute of
  129. * the message queue, mq_receive will return an error. Otherwise, the
  130. * selected message is removed from the queue and copied to "msg."
  131. *
  132. * If the message queue is empty and O_NONBLOCK was not set,
  133. * mq_receive() will block until a message is added to the message
  134. * queue. If more than one task is waiting to receive a message, only
  135. * the task with the highest priority that has waited the longest will
  136. * be unblocked.
  137. *
  138. * If the queue is empty and O_NONBLOCK is set, ERROR will be returned.
  139. *
  140. * Input Parameters:
  141. * mqdes - Message Queue Descriptor
  142. * msg - Buffer to receive the message
  143. * msglen - Size of the buffer in bytes
  144. * prio - If not NULL, the location to store message priority.
  145. *
  146. * Returned Value:
  147. * One success, the length of the selected message in bytes is returned.
  148. * On failure, -1 (ERROR) is returned and the errno is set appropriately:
  149. *
  150. * EAGAIN The queue was empty, and the O_NONBLOCK flag was set
  151. * for the message queue description referred to by 'mqdes'.
  152. * EPERM Message queue opened not opened for reading.
  153. * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the
  154. * message queue.
  155. * EINTR The call was interrupted by a signal handler.
  156. * EINVAL Invalid 'msg' or 'mqdes'
  157. *
  158. ****************************************************************************/
  159. ssize_t mq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
  160. FAR unsigned int *prio)
  161. {
  162. int ret;
  163. /* mq_receive() is a cancellation point */
  164. (void)enter_cancellation_point();
  165. /* Let nxmq_receive do all of the work */
  166. ret = nxmq_receive(mqdes, msg, msglen, prio);
  167. if (ret < 0)
  168. {
  169. set_errno(-ret);
  170. ret = ERROR;
  171. }
  172. leave_cancellation_point();
  173. return ret;
  174. }