mirror of
https://github.com/azure-rtos/threadx
synced 2025-02-06 08:08:27 +08:00
223 lines
9.5 KiB
C
223 lines
9.5 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
|
/* */
|
|
/* This software is licensed under the Microsoft Software License */
|
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
|
/* and in the root directory of this software. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/** */
|
|
/** POSIX wrapper for THREADX */
|
|
/** */
|
|
/** */
|
|
/** */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
/* Include necessary system files. */
|
|
|
|
#include "tx_api.h" /* Threadx API */
|
|
#include "pthread.h" /* Posix API */
|
|
#include "px_int.h" /* Posix helper functions */
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* mq_send PORTABLE C */
|
|
/* 6.1.7 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* William E. Lamie, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* The mq_send() function puts a message of size msg_len and pointed to*/
|
|
/* by msg_ptr into the queue indicated by mqdes. The new message has a */
|
|
/* priority of msg_prio. */
|
|
/* The queue maintained is in priority order (priorities may range from*/
|
|
/* 0 to MQ_PRIO_MAX), and in FIFO order within the same priority. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* mqdes Queue descriptor */
|
|
/* msg_ptr Message pointer */
|
|
/* msg_len length of message */
|
|
/* msg_prio Priority of the message */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* OK no of bytes received */
|
|
/* ERROR If error occurs */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* tx_thread_identify returns currently running thread */
|
|
/* tx_byte_allocate allocate memory */
|
|
/* tx_queue_send ThreadX queue send */
|
|
/* posix_priority_search search message for same priority */
|
|
/* */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
|
|
/* 10-31-2022 Scott Larson Add 64-bit support, */
|
|
/* resulting in version 6.2.0 */
|
|
/* */
|
|
/**************************************************************************/
|
|
INT mq_send( mqd_t mqdes, const CHAR * msg_ptr, size_t msg_len,
|
|
ULONG msg_prio )
|
|
{
|
|
|
|
TX_QUEUE *Queue;
|
|
UINT temp1;
|
|
POSIX_MSG_QUEUE *q_ptr;
|
|
VOID *bp;
|
|
UCHAR *source;
|
|
UCHAR *destination;
|
|
UCHAR *save_ptr;
|
|
ULONG mycount;
|
|
ULONG msg[TX_POSIX_MESSAGE_SIZE];
|
|
|
|
/* Assign a temporary variable for clarity. */
|
|
Queue = &(mqdes->f_data->queue);
|
|
q_ptr = (POSIX_MSG_QUEUE * )mqdes->f_data;
|
|
|
|
/* First, check for an invalid queue pointer. */
|
|
if ( (!q_ptr) || ( (q_ptr -> px_queue_id) != PX_QUEUE_ID))
|
|
{
|
|
/* Queue pointer is invalid, return appropriate error code. */
|
|
posix_errno = EBADF;
|
|
posix_set_pthread_errno(EBADF);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
/* Make sure if we're calling this routine from a ISR timeout
|
|
is set to zero. */
|
|
if (!(tx_thread_identify()))
|
|
{
|
|
/* POSIX doesn't have error for this, hence give default. */
|
|
posix_errno = EINTR ;
|
|
posix_set_pthread_errno(EINTR);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
|
|
/* First, check for an invalid queue pointer. */
|
|
if ( (!q_ptr) || ( (q_ptr->queue.tx_queue_id) != TX_QUEUE_ID))
|
|
{
|
|
/* Queue descriptor is invalid, set appropriate error code. */
|
|
posix_errno = EBADF ;
|
|
posix_set_pthread_errno(EBADF);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
if(((mqdes->f_flag & O_WRONLY) != O_WRONLY) && ((mqdes->f_flag & O_RDWR) != O_RDWR))
|
|
{
|
|
/* Queue pointer is invalid, return appropriate error code. */
|
|
posix_errno = EBADF;
|
|
posix_set_pthread_errno(EBADF);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
if( msg_prio > MQ_PRIO_MAX)
|
|
{
|
|
/* Return appropriate error. */
|
|
posix_errno = EINVAL;
|
|
posix_set_pthread_errno(EINVAL);
|
|
|
|
/* Return error. */
|
|
return(ERROR);
|
|
}
|
|
/* Check for an invalid source for message. */
|
|
if (! msg_ptr)
|
|
{
|
|
/* POSIX doesn't have error for this, hence give default. */
|
|
posix_errno = EINTR ;
|
|
posix_set_pthread_errno(EINTR);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Now check the length of message. */
|
|
if ( msg_len > (q_ptr->q_attr.mq_msgsize ) )
|
|
{
|
|
/* Return message length exceeds max length. */
|
|
posix_errno = EMSGSIZE ;
|
|
posix_set_pthread_errno(EMSGSIZE);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Now try to allocate memory to save the message from the
|
|
queue's byte pool. */
|
|
temp1 = tx_byte_allocate((TX_BYTE_POOL * )&(q_ptr->vq_message_area), &bp,
|
|
msg_len, TX_NO_WAIT);
|
|
|
|
if (temp1 != TX_SUCCESS)
|
|
{
|
|
posix_internal_error(9999);
|
|
}
|
|
/* Got the memory , Setup source and destination pointers
|
|
Cast them in UCHAR as message length is in bytes. */
|
|
source = (UCHAR * ) msg_ptr;
|
|
destination = (UCHAR * ) bp;
|
|
|
|
/* Save start of message storage. */
|
|
save_ptr = destination;
|
|
|
|
/* Copy the message into private buffer. */
|
|
for ( mycount = 0; mycount < msg_len; mycount++)
|
|
{
|
|
|
|
* destination++ = * source++;
|
|
}
|
|
/* Restore the pointer of save message. */
|
|
source = save_ptr ;
|
|
/* Create message that holds saved message pointer and message length. */
|
|
#ifdef TX_64_BIT
|
|
msg[0] = (ULONG)((ALIGN_TYPE)source >> 32);
|
|
msg[1] = (ULONG)((ALIGN_TYPE)source);
|
|
msg[2] = msg_len;
|
|
msg[3] = msg_prio;
|
|
msg[4] = posix_priority_search(mqdes, msg_prio);
|
|
#else
|
|
msg[0] = (ULONG)source;
|
|
msg[1] = msg_len;
|
|
msg[2] = msg_prio;
|
|
msg[3] = posix_priority_search(mqdes, msg_prio);
|
|
#endif
|
|
/* Attempt to post the message to the queue. */
|
|
temp1 = tx_queue_send(Queue, msg, TX_WAIT_FOREVER);
|
|
if ( temp1 != TX_SUCCESS)
|
|
{
|
|
/* POSIX doesn't have error for this, hence give default. */
|
|
posix_errno = EINTR ;
|
|
posix_set_pthread_errno(EINTR);
|
|
|
|
/* Return ERROR. */
|
|
return(ERROR);
|
|
}
|
|
|
|
/* All done. */
|
|
return(OK);
|
|
}
|