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 /* posix_mq_create PORTABLE C */
34 /* 6.2.0 */
35 /* AUTHOR */
36 /* */
37 /* William E. Lamie, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* This subroutine creates and initializes a message queue */
42 /* As the message length is user defined, message pointer and message */
43 /* length is stored in a ThreadX queue(instead of the actual message) */
44 /* The actual message is stored in a dedicated byte pool for the */
45 /* queue */
46 /* */
47 /* */
48 /* INPUT */
49 /* */
50 /* mq_name name of the Queue */
51 /* msgq_attr Pointer to mq_attr structure */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* posix_q If success */
56 /* NULL If failure */
57 /* */
58 /* CALLS */
59 /* */
60 /* posix_in_thread_context Make sure caller is thread */
61 /* tx_queue_create to create a ThreadX Queue */
62 /* posix_internal_error Generic error Handler */
63 /* posix_memory_allocate to create a byte pool */
64 /* tx_queue_delete to delete the queue */
65 /* posix_putback_queue to delete the queue */
66 /* tx_byte_pool_create to create a byte pool */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* POSIX internal Code */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
77 /* 10-31-2022 Scott Larson Add 64-bit support, */
78 /* resulting in version 6.2.0 */
79 /* */
80 /**************************************************************************/
posix_mq_create(const CHAR * mq_name,struct mq_attr * msgq_attr)81 POSIX_MSG_QUEUE * posix_mq_create (const CHAR * mq_name,
82 struct mq_attr * msgq_attr)
83 {
84
85 TX_INTERRUPT_SAVE_AREA
86
87 POSIX_MSG_QUEUE *posix_q;
88 UINT temp1;
89 VOID *bp;
90 INT retval;
91 ULONG size;
92 TX_QUEUE *TheQ;
93
94 /* Make sure we're calling this routine from a thread context. */
95 if (!posix_in_thread_context())
96 {
97 /* return POSIX error. */
98 posix_internal_error(444);
99
100 /* return error. */
101 return ((POSIX_MSG_QUEUE *)ERROR);
102 }
103 /* Disable interrupts.*/
104 TX_DISABLE
105
106 /* Get a new queue from the POSIX queue pool. */
107 /* Make sure we have enough space for the size. */
108
109 posix_q = posix_get_new_queue(msgq_attr->mq_maxmsg);
110
111 /* Make sure we actually got a queue. */
112 if (!posix_q)
113 {
114 /* Restore interrupts. */
115 TX_RESTORE
116
117 /* User configuration error - not enough memory. */
118 posix_errno = EBADF;
119 posix_set_pthread_errno(EBADF);
120
121 /* Return ERROR. */
122 return(TX_NULL);
123 }
124
125 /* Now create a ThreadX message queue.
126 to store only the message pointer and message length. */
127 temp1 = tx_queue_create((&(posix_q->queue)),
128 (CHAR *)mq_name,
129 TX_POSIX_MESSAGE_SIZE,
130 posix_q->storage,
131 (msgq_attr->mq_maxmsg * (sizeof(ULONG) * TX_POSIX_MESSAGE_SIZE)));
132
133 /* Make sure it worked. */
134 if (temp1 != TX_SUCCESS)
135 {
136 /*. Return generic error. */
137 posix_internal_error(188);
138
139 /* Restore interrupts. */
140 TX_RESTORE
141
142 /* Return ERROR. */
143 return(TX_NULL);
144 }
145 /* Restore no. of maximum messages. */
146 posix_q->q_attr.mq_maxmsg = msgq_attr->mq_maxmsg;
147
148 /* Restore maximum message length. */
149 posix_q->q_attr.mq_msgsize = msgq_attr->mq_msgsize;
150
151 /* Flags are stored in que descriptor structure and
152 not in mq_att structure. */
153
154 /* Create a byte pool for the queue.
155 Determine how much memory we need to store all messages in this queue.
156 11 bytes are added to counter overhead as well as alignment problem if any. */
157 size = ( ((msgq_attr->mq_maxmsg) + 1) * (msgq_attr->mq_msgsize + 11) );
158
159 if(size < 100)
160 size = 100;
161
162 /* Now attempt to allocate that much memory for the queue. */
163
164 retval = posix_memory_allocate(size,&bp);
165
166 /* Make sure we obtained the memory we requested. */
167 if (retval)
168 {
169 /* Created queue Control block, got memory to store message pointers
170 and lengths which means that created a fixed length message queue but
171 not enough memory to store actual messages. */
172
173 /* Delete the queue. */
174
175 /* Assign a temporary variable for clarity. */
176 TheQ = (TX_QUEUE * )posix_q;
177 retval = tx_queue_delete(TheQ);
178
179 /* Make sure the queue was deleted. */
180 if (retval != TX_SUCCESS)
181 {
182 /* Return generic error. */
183 posix_internal_error(799);
184
185 /* Restore interrupts. */
186 TX_RESTORE
187
188 /* Return ERROR. */
189 return(TX_NULL);
190 }
191 /* Put the queue back into the POSIX queue pool. */
192 posix_putback_queue(TheQ);
193
194 /* User configuration error - not enough memory. */
195 posix_errno = EBADF;
196 posix_set_pthread_errno(EBADF);
197 TX_RESTORE;
198
199 /* Return ERROR. */
200 return(TX_NULL);
201 }
202 /* Create a ThreadX byte pool that will provide memory needed by the queue. */
203 retval = tx_byte_pool_create((&(posix_q->vq_message_area)), "POSIX Queue",
204 bp, size);
205
206 /* Make sure the byte pool was created successfully. */
207 if (retval)
208 {
209 /* Error creating byte pool. */
210 posix_internal_error(9999);
211
212 /* Restore interrupts. */
213 TX_RESTORE
214
215 /* Return ERROR.*/
216 return(TX_NULL);
217 }
218
219 posix_q->name = (CHAR*) mq_name;
220
221 /* Restore interrupts. */
222 TX_RESTORE
223
224 /* All done. */
225 return(posix_q);
226 }
227