==============================
Named Message Queue Interfaces
==============================

NuttX supports POSIX named message queues for inter-task communication.
Any task may send or receive messages on named message queues. Interrupt
handlers may send messages via named message queues.

  - :c:func:`mq_open`
  - :c:func:`mq_close`
  - :c:func:`mq_unlink`
  - :c:func:`mq_send`
  - :c:func:`mq_timedsend`
  - :c:func:`mq_receive`
  - :c:func:`mq_timedreceive`
  - :c:func:`mq_notify`
  - :c:func:`mq_setattr`
  - :c:func:`mq_getattr`

.. c:function:: mqd_t mq_open(const char *mqName, int oflags, ...)

  Establishes a connection between a named message queue and the calling
  task. After a successful call of mq_open(), the task can reference the
  message queue using the address returned by the call. The message queue
  remains usable until it is closed by a successful call to mq_close().

  :param mqName: Name of the queue to open
  :param oflags: Open flags. These may be any combination of:

     -  ``O_RDONLY``. Open for read access.
     -  ``O_WRONLY``. Open for write access.
     -  ``O_RDWR``. Open for both read & write access.
     -  ``O_CREAT``. Create message queue if it does not already exist.
     -  ``O_EXCL``. Name must not exist when opened.
     -  ``O_NONBLOCK``. Don't wait for data.

  :param ``...``: **Optional parameters**. When the O_CREAT flag is specified,
     POSIX requires that a third and fourth parameter be supplied:

     -  ``mode``. The mode parameter is of type mode_t. In the POSIX
        specification, this mode value provides file permission bits for
        the message queue. This parameter is required but not used in the
        present implementation.
     -  ``attr``. A pointer to an mq_attr that is provided to initialize.
        the message queue. If attr is NULL, then the messages queue is
        created with implementation-defined default message queue
        attributes. If attr is non-NULL, then the message queue mq_maxmsg
        attribute is set to the corresponding value when the queue is
        created. The mq_maxmsg attribute determines the maximum number of
        messages that can be queued before addition attempts to send
        messages on the message queue fail or cause the sender to block;
        the mq_msgsize attribute determines the maximum size of a message
        that can be sent or received. Other elements of attr are ignored
        (i.e, set to default message queue attributes).

  :return: A message queue descriptor or -1 (``ERROR``)

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name. Differences from the full POSIX implementation include:

  -  The mq_msgsize attributes determines the maximum size of a message
     that may be sent or received. In the present implementation, this
     maximum message size is limited at 22 bytes.

.. c:function:: int mq_close(mqd_t mqdes)

  Used to indicate that the calling task is finished with the specified
  message queued ``mqdes``. The ``mq_close()`` deallocates any system
  resources allocated by the system for use by this task for its message
  queue.

  If the calling task has attached a notification request to the message
  queue via this ``mqdes`` (see ``mq_notify()``), this attachment will be
  removed and the message queue is available for another task to attach
  for notification.

  :param mqdes: Message queue descriptor.

  :return: 0 (``OK``) if the message queue is closed successfully, otherwise, -1
     (``ERROR``).

  **Assumptions/Limitations:**

    -  The behavior of a task that is blocked on either a ``mq_send()`` or
       ``mq_receive()`` is undefined when ``mq_close()`` is called.
    -  The result of using this message queue descriptor after successful
       return from ``mq_close()`` is undefined.

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: int mq_unlink(const char *mqName)

  Removes the message queue named by
  "mqName." If one or more tasks have the message queue open when
  ``mq_unlink()`` is called, removal of the message queue is postponed
  until all references to the message queue have been closed.

  :param mqName: Name of the message queue

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio)

  Adds the specified message, ``msg``, to the message queue, ``mqdes``.
  The ``msglen`` parameter specifies the length of the message in bytes
  pointed to by ``msg``. This length must not exceed the maximum message
  length from the ``mq_getattr()``.

  If the message queue is not full, ``mq_send()`` will place the ``msg``
  in the message queue at the position indicated by the ``prio`` argument.
  Messages with higher priority will be inserted before lower priority
  messages The value of ``prio`` must not exceed ``MQ_PRIO_MAX``.

  If the specified message queue is full and ``O_NONBLOCK`` is not set in
  the message queue, then ``mq_send()`` will block until space becomes
  available to the queue the message.

  If the message queue is full and ``NON_BLOCK`` is set, the message is
  not queued and ``ERROR`` is returned.

  **NOTE**: ``mq_send()`` may be called from an interrupt handler.
  However, it behaves differently when called from the interrupt level:

  -  It does not check the size of the queue. It will always post the
     message, even if there are already too many messages in queue. This is
     because the interrupt handler does not have the option of waiting for
     the message queue to become non-full.
  -  It doesn't allocate new memory (because you cannot allocate memory
     from an interrupt handler). Instead, there is a pool of pre-allocated
     message structures that may be used just for sending messages from
     interrupt handlers. The number of such pre-allocated messages is set
     by the ``PREALLOC_MQ_IRQ_MSGS`` configuration parameter.

  :param mqdes: Message queue descriptor.
  :param msg: Message to send.
  :param msglen: The length of the message in bytes.
  :param prio: The priority of the message.
  :return: On success, ``mq_send()`` returns 0 (``OK``); on
    error, -1 (``ERROR``) is returned, with ```errno`` <#ErrnoAccess>`__ set
    to indicate the error:

    -  ``EAGAIN``. The queue was empty, and the ``O_NONBLOCK`` flag was set
       for the message queue description referred to by ``mqdes``.
    -  ``EINVAL``. Either ``msg`` or ``mqdes`` is ``NULL`` or the value of
       ``prio`` is invalid.
    -  ``EPERM``. Message queue opened not opened for writing.
    -  ``EMSGSIZE``. ``msglen`` was greater than the ``maxmsgsize``
       attribute of the message queue.
    -  ``EINTR``. The call was interrupted by a signal handler.

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, \
                const struct timespec *abstime);

  Adds the specified message, ``msg``, to the message queue, ``mqdes``.
  The ``msglen`` parameter specifies the length of the message in bytes
  pointed to by ``msg``. This length must not exceed the maximum message
  length from the ``mq_getattr()``.

  If the message queue is not full, ``mq_timedsend()`` will place the
  ``msg`` in the message queue at the position indicated by the ``prio``
  argument. Messages with higher priority will be inserted before lower
  priority messages The value of ``prio`` must not exceed ``MQ_PRIO_MAX``.

  If the specified message queue is full and ``O_NONBLOCK`` is not set in
  the message queue, then ``mq_timedsend()`` will block until space becomes
  available to the queue the message or until a timeout occurs.

  ``mq_timedsend()`` behaves just like ``mq_send()``, except that if the
  queue is full and the ``O_NONBLOCK`` flag is not enabled for the message
  queue description, then ``abstime`` points to a structure which
  specifies a ceiling on the time for which the call will block. This
  ceiling is an absolute timeout in seconds and nanoseconds since the
  Epoch (midnight on the morning of 1 January 1970).

  If the message queue is full, and the timeout has already expired by the
  time of the call, ``mq_timedsend()`` returns immediately.

  :param mqdes: Message queue descriptor.
  :param msg: Message to send.
  :param msglen: The length of the message in bytes.
  :param prio: The priority of the message.
  :return: On success, ``mq_send()`` returns 0 (``OK``); on
    error, -1 (``ERROR``) is returned, with ```errno`` <#ErrnoAccess>`__ set
    to indicate the error:

    -  ``EAGAIN``. The queue was full, and the ``O_NONBLOCK`` flag was set
       for the message queue description referred to by ``mqdes``.
    -  ``EINVAL``. Either ``msg`` or ``mqdes`` is ``NULL`` or the value of
       ``prio`` is invalid.
    -  ``EPERM``. Message queue opened not opened for writing.
    -  ``EMSGSIZE``. ``msglen`` was greater than the ``maxmsgsize``
       attribute of the message queue.
    -  ``EINTR``. The call was interrupted by a signal handler.

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio)

  Receives the oldest of the highest priority messages from the message
  queue specified by ``mqdes``. If the size of the buffer in bytes,
  ``msgLen``, is less than the ``mq_msgsize`` attribute of the message
  queue, ``mq_receive()`` will return an error. Otherwise, the selected
  message is removed from the queue and copied to ``msg``.

  If the message queue is empty and ``O_NONBLOCK`` was not set,
  ``mq_receive()`` will block until a message is added to the message
  queue. If more than one task is waiting to receive a message, only the
  task with the highest priority that has waited the longest will be
  unblocked.

  If the queue is empty and ``O_NONBLOCK`` is set, ``ERROR`` will be
  returned.

  :param mqdes: Message Queue Descriptor.
  :param msg: Buffer to receive the message.
  :param msglen: Size of the buffer in bytes.
  :param prio: If not NULL, the location to store message priority.
  :return: On success, the length of the selected message in bytes is
    returned. On failure, -1 (``ERROR``) is returned and the
    ```errno`` <#ErrnoAccess>`__ is set appropriately:

    -  ``EAGAIN`` The queue was empty and the ``O_NONBLOCK`` flag was set
       for the message queue description referred to by ``mqdes``.
    -  ``EPERM`` Message queue opened not opened for reading.
    -  ``EMSGSIZE`` ``msglen`` was less than the ``maxmsgsize`` attribute of
       the message queue.
    -  ``EINTR`` The call was interrupted by a signal handler.
    -  ``EINVAL`` Invalid ``msg`` or ``mqdes``

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, \
                               int *prio, const struct timespec *abstime);

  Receives the oldest of the highest priority messages from the message
  queue specified by ``mqdes``. If the size of the buffer in bytes,
  ``msgLen``, is less than the ``mq_msgsize`` attribute of the message
  queue, ``mq_timedreceive()`` will return an error. Otherwise, the
  selected message is removed from the queue and copied to ``msg``.

  If the message queue is empty and ``O_NONBLOCK`` was not set,
  ``mq_timedreceive()`` will block until a message is added to the message
  queue (or until a timeout occurs). If more than one task is waiting to
  receive a message, only the task with the highest priority that has
  waited the longest will be unblocked.

  ``mq_timedreceive()`` behaves just like ``mq_receive()``, except that if
  the queue is empty and the ``O_NONBLOCK`` flag is not enabled for the
  message queue description, then ``abstime`` points to a structure which
  specifies a ceiling on the time for which the call will block. This
  ceiling is an absolute timeout in seconds and nanoseconds since the
  Epoch (midnight on the morning of 1 January 1970).

  If no message is available, and the timeout has already expired by the
  time of the call, ``mq_timedreceive()`` returns immediately.

  :param mqdes: Message Queue Descriptor.
  :param msg: Buffer to receive the message.
  :param msglen: Size of the buffer in bytes.
  :param prio: If not NULL, the location to store message priority.
  :param abstime: The absolute time to wait until a timeout is declared.

  :return: On success, the length of the selected message in bytes is
    returned. On failure, -1 (``ERROR``) is returned and the
    ```errno`` <#ErrnoAccess>`__ is set appropriately:

    -  ``EAGAIN``: The queue was empty and the ``O_NONBLOCK`` flag was set
       for the message queue description referred to by ``mqdes``.
    -  ``EPERM``: Message queue opened not opened for reading.
    -  ``EMSGSIZE``: ``msglen`` was less than the ``maxmsgsize`` attribute
       of the message queue.
    -  ``EINTR``: The call was interrupted by a signal handler.
    -  ``EINVAL``: Invalid ``msg`` or ``mqdes`` or ``abstime``
    -  ``ETIMEDOUT``: The call timed out before a message could be
       transferred.

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)

  If the ``notification`` input parameter is not ``NULL``, this function
  connects the task with the message queue such that the specified signal
  will be sent to the task whenever the message queue changes from empty
  to non-empty. One notification can be attached to a message queue.

  If ``notification``; is ``NULL``, the attached notification is detached
  (if it was held by the calling task) and the queue is available to
  attach another notification.

  When the notification is sent to the registered task, its registration
  will be removed. The message queue will then be available for
  registration.

  :param mqdes: Message queue descriptor
  :param notification: Real-time signal structure containing:

     -  ``sigev_notify``. Should be SIGEV_SIGNAL (but actually ignored)
     -  ``sigev_signo``. The signo to use for the notification
     -  ``sigev_value``. Value associated with the signal

  :return: On success ``mq_notify()`` returns 0; on error, -1
    is returned, with ``errno`` set to indicate the error:

    -  ``EBADF``. The descriptor specified in ``mqdes`` is invalid.
    -  ``EBUSY``. Another process has already registered to receive
       notification for this message queue.
    -  ``EINVAL``. ``sevp->sigev_notify`` is not one of the permitted
       values; or ``sevp->sigev_notify`` is ``SIGEV_SIGNAL`` and
       ``sevp->sigev_signo`` is not a valid signal number.
    -  ``ENOMEM``. Insufficient memory.

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name. Differences from the full POSIX implementation include:

  -  The notification signal will be sent to the registered task even if
     another task is waiting for the message queue to become non-empty.
     This is inconsistent with the POSIX specification which states, "If a
     process has registered for notification of message arrival at a
     message queue and some process is blocked in ``mq_receive`` waiting
     to receive a message when a message arrives at the queue, the
     arriving message will satisfy the appropriate ``mq_receive()`` ...
     The resulting behavior is as if the message queue remains empty, and
     no notification will be sent."

.. c:function:: int mq_setattr(mqd_t mqdes, const struct mq_attr *mqStat, \
                      struct mq_attr *oldMqStat);

  Sets the attributes associated with the specified message queue "mqdes."
  Only the "O_NONBLOCK" bit of the "mq_flags" can be changed.

  If ``oldMqStat`` is non-null, mq_setattr() will store the previous message
  queue attributes at that location (just as would have been returned by
  mq_getattr()).

  :param mqdes: Message queue descriptor
  :param mqStat: New attributes
  :param oldMqState: Old attributes

  :return: 0 (``OK``) if attributes are set successfully, otherwise -1
     (``ERROR``).

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.

.. c:function:: int mq_getattr(mqd_t mqdes, struct mq_attr *mqStat)

  Gets status information and attributes associated with the specified
  message queue.

  :param mqdes: Message queue descriptor
  :param mqStat: Buffer in which to return attributes. The returned
     attributes include:

     -  ``mq_maxmsg``. Max number of messages in queue.
     -  ``mq_msgsize``. Max message size.
     -  ``mq_flags``. Queue flags.
     -  ``mq_curmsgs``. Number of messages currently in queue.

  :return: 0 (``OK``) if attributes provided, -1 (``ERROR``) otherwise.

  **POSIX Compatibility:** Comparable to the POSIX interface of the same
  name.
