1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** POSIX wrapper for THREADX */
17 /** */
18 /** */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 /* Include necessary system files. */
24
25 #include "tx_api.h" /* Threadx API */
26 #include "pthread.h" /* Posix API */
27 #include "px_int.h" /* Posix helper functions */
28
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* mq_send PORTABLE C */
34 /* 6.1.7 */
35 /* AUTHOR */
36 /* */
37 /* William E. Lamie, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* The mq_send() function puts a message of size msg_len and pointed to*/
42 /* by msg_ptr into the queue indicated by mqdes. The new message has a */
43 /* priority of msg_prio. */
44 /* The queue maintained is in priority order (priorities may range from*/
45 /* 0 to MQ_PRIO_MAX), and in FIFO order within the same priority. */
46 /* */
47 /* INPUT */
48 /* */
49 /* mqdes Queue descriptor */
50 /* msg_ptr Message pointer */
51 /* msg_len length of message */
52 /* msg_prio Priority of the message */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* OK no of bytes received */
57 /* ERROR If error occurs */
58 /* */
59 /* CALLS */
60 /* */
61 /* tx_thread_identify returns currently running thread */
62 /* tx_byte_allocate allocate memory */
63 /* tx_queue_send ThreadX queue send */
64 /* posix_priority_search search message for same priority */
65 /* */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* Application Code */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
76 /* 10-31-2022 Scott Larson Add 64-bit support, */
77 /* resulting in version 6.2.0 */
78 /* */
79 /**************************************************************************/
mq_send(mqd_t mqdes,const CHAR * msg_ptr,size_t msg_len,ULONG msg_prio)80 INT mq_send( mqd_t mqdes, const CHAR * msg_ptr, size_t msg_len,
81 ULONG msg_prio )
82 {
83
84 TX_QUEUE *Queue;
85 UINT temp1;
86 POSIX_MSG_QUEUE *q_ptr;
87 VOID *bp;
88 UCHAR *source;
89 UCHAR *destination;
90 UCHAR *save_ptr;
91 ULONG mycount;
92 ULONG msg[TX_POSIX_MESSAGE_SIZE];
93
94 /* Assign a temporary variable for clarity. */
95 Queue = &(mqdes->f_data->queue);
96 q_ptr = (POSIX_MSG_QUEUE * )mqdes->f_data;
97
98 /* First, check for an invalid queue pointer. */
99 if ( (!q_ptr) || ( (q_ptr -> px_queue_id) != PX_QUEUE_ID))
100 {
101 /* Queue pointer is invalid, return appropriate error code. */
102 posix_errno = EBADF;
103 posix_set_pthread_errno(EBADF);
104
105 /* Return ERROR. */
106 return(ERROR);
107 }
108 /* Make sure if we're calling this routine from a ISR timeout
109 is set to zero. */
110 if (!(tx_thread_identify()))
111 {
112 /* POSIX doesn't have error for this, hence give default. */
113 posix_errno = EINTR ;
114 posix_set_pthread_errno(EINTR);
115
116 /* Return ERROR. */
117 return(ERROR);
118 }
119
120 /* First, check for an invalid queue pointer. */
121 if ( (!q_ptr) || ( (q_ptr->queue.tx_queue_id) != TX_QUEUE_ID))
122 {
123 /* Queue descriptor is invalid, set appropriate error code. */
124 posix_errno = EBADF ;
125 posix_set_pthread_errno(EBADF);
126
127 /* Return ERROR. */
128 return(ERROR);
129 }
130 if(((mqdes->f_flag & O_WRONLY) != O_WRONLY) && ((mqdes->f_flag & O_RDWR) != O_RDWR))
131 {
132 /* Queue pointer is invalid, return appropriate error code. */
133 posix_errno = EBADF;
134 posix_set_pthread_errno(EBADF);
135
136 /* Return ERROR. */
137 return(ERROR);
138 }
139 if( msg_prio > MQ_PRIO_MAX)
140 {
141 /* Return appropriate error. */
142 posix_errno = EINVAL;
143 posix_set_pthread_errno(EINVAL);
144
145 /* Return error. */
146 return(ERROR);
147 }
148 /* Check for an invalid source for message. */
149 if (! msg_ptr)
150 {
151 /* POSIX doesn't have error for this, hence give default. */
152 posix_errno = EINTR ;
153 posix_set_pthread_errno(EINTR);
154
155 /* Return ERROR. */
156 return(ERROR);
157 }
158
159 /* Now check the length of message. */
160 if ( msg_len > (q_ptr->q_attr.mq_msgsize ) )
161 {
162 /* Return message length exceeds max length. */
163 posix_errno = EMSGSIZE ;
164 posix_set_pthread_errno(EMSGSIZE);
165
166 /* Return ERROR. */
167 return(ERROR);
168 }
169
170 /* Now try to allocate memory to save the message from the
171 queue's byte pool. */
172 temp1 = tx_byte_allocate((TX_BYTE_POOL * )&(q_ptr->vq_message_area), &bp,
173 msg_len, TX_NO_WAIT);
174
175 if (temp1 != TX_SUCCESS)
176 {
177 posix_internal_error(9999);
178 }
179 /* Got the memory , Setup source and destination pointers
180 Cast them in UCHAR as message length is in bytes. */
181 source = (UCHAR * ) msg_ptr;
182 destination = (UCHAR * ) bp;
183
184 /* Save start of message storage. */
185 save_ptr = destination;
186
187 /* Copy the message into private buffer. */
188 for ( mycount = 0; mycount < msg_len; mycount++)
189 {
190
191 * destination++ = * source++;
192 }
193 /* Restore the pointer of save message. */
194 source = save_ptr ;
195 /* Create message that holds saved message pointer and message length. */
196 #ifdef TX_64_BIT
197 msg[0] = (ULONG)((ALIGN_TYPE)source >> 32);
198 msg[1] = (ULONG)((ALIGN_TYPE)source);
199 msg[2] = msg_len;
200 msg[3] = msg_prio;
201 msg[4] = posix_priority_search(mqdes, msg_prio);
202 #else
203 msg[0] = (ULONG)source;
204 msg[1] = msg_len;
205 msg[2] = msg_prio;
206 msg[3] = posix_priority_search(mqdes, msg_prio);
207 #endif
208 /* Attempt to post the message to the queue. */
209 temp1 = tx_queue_send(Queue, msg, TX_WAIT_FOREVER);
210 if ( temp1 != TX_SUCCESS)
211 {
212 /* POSIX doesn't have error for this, hence give default. */
213 posix_errno = EINTR ;
214 posix_set_pthread_errno(EINTR);
215
216 /* Return ERROR. */
217 return(ERROR);
218 }
219
220 /* All done. */
221 return(OK);
222 }
223