1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** ThreadX Component                                                     */
16 /**                                                                       */
17 /**   Queue                                                               */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "tx_api.h"
28 #include "tx_initialize.h"
29 #include "tx_timer.h"
30 #include "tx_thread.h"
31 #include "tx_queue.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _txe_queue_create                                   PORTABLE C      */
39 /*                                                           6.1          */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    William E. Lamie, Microsoft Corporation                             */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function checks for errors in the queue create function call.  */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    queue_ptr                         Pointer to queue control block    */
51 /*    name_ptr                          Pointer to queue name             */
52 /*    message_size                      Size of each queue message        */
53 /*    queue_start                       Starting address of the queue area*/
54 /*    queue_size                        Number of bytes in the queue      */
55 /*    queue_control_block_size          Size of queue control block       */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    TX_QUEUE_ERROR                    Invalid queue pointer             */
60 /*    TX_PTR_ERROR                      Invalid starting address of queue */
61 /*    TX_SIZE_ERROR                     Invalid message queue size        */
62 /*    status                            Actual completion status          */
63 /*                                                                        */
64 /*  CALLS                                                                 */
65 /*                                                                        */
66 /*    _tx_queue_create                  Actual queue create function      */
67 /*    _tx_thread_system_preempt_check   Check for preemption              */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    Application Code                                                    */
72 /*                                                                        */
73 /*  RELEASE HISTORY                                                       */
74 /*                                                                        */
75 /*    DATE              NAME                      DESCRIPTION             */
76 /*                                                                        */
77 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
78 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
79 /*                                            resulting in version 6.1    */
80 /*                                                                        */
81 /**************************************************************************/
_txe_queue_create(TX_QUEUE * queue_ptr,CHAR * name_ptr,UINT message_size,VOID * queue_start,ULONG queue_size,UINT queue_control_block_size)82 UINT  _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
83                         VOID *queue_start, ULONG queue_size, UINT queue_control_block_size)
84 {
85 
86 TX_INTERRUPT_SAVE_AREA
87 
88 UINT            status;
89 ULONG           i;
90 TX_QUEUE        *next_queue;
91 #ifndef TX_TIMER_PROCESS_IN_ISR
92 TX_THREAD       *thread_ptr;
93 #endif
94 
95 
96     /* Default status to success.  */
97     status =  TX_SUCCESS;
98 
99     /* Check for an invalid queue pointer.  */
100     if (queue_ptr == TX_NULL)
101     {
102 
103         /* Queue pointer is invalid, return appropriate error code.  */
104         status =  TX_QUEUE_ERROR;
105     }
106 
107     /* Now check for a valid control block size.  */
108     else if (queue_control_block_size != (sizeof(TX_QUEUE)))
109     {
110 
111         /* Queue pointer is invalid, return appropriate error code.  */
112         status =  TX_QUEUE_ERROR;
113     }
114     else
115     {
116 
117         /* Disable interrupts.  */
118         TX_DISABLE
119 
120         /* Increment the preempt disable flag.  */
121         _tx_thread_preempt_disable++;
122 
123         /* Restore interrupts.  */
124         TX_RESTORE
125 
126         /* Next see if it is already in the created list.  */
127         next_queue =   _tx_queue_created_ptr;
128         for (i = ((ULONG) 0); i < _tx_queue_created_count; i++)
129         {
130 
131             /* Determine if this queue matches the queue in the list.  */
132             if (queue_ptr == next_queue)
133             {
134 
135                 break;
136             }
137             else
138             {
139 
140                 /* Move to the next queue.  */
141                 next_queue =  next_queue -> tx_queue_created_next;
142             }
143         }
144 
145         /* Disable interrupts.  */
146         TX_DISABLE
147 
148         /* Decrement the preempt disable flag.  */
149         _tx_thread_preempt_disable--;
150 
151         /* Restore interrupts.  */
152         TX_RESTORE
153 
154         /* Check for preemption.  */
155         _tx_thread_system_preempt_check();
156 
157         /* At this point, check to see if there is a duplicate queue.  */
158         if (queue_ptr == next_queue)
159         {
160 
161             /* Queue is already created, return appropriate error code.  */
162             status =  TX_QUEUE_ERROR;
163         }
164 
165         /* Check the starting address of the queue.  */
166         else if (queue_start == TX_NULL)
167         {
168 
169             /* Invalid starting address of queue.  */
170             status =  TX_PTR_ERROR;
171         }
172 
173         /* Check for an invalid message size - less than 1.  */
174         else if (message_size < TX_1_ULONG)
175         {
176 
177             /* Invalid message size specified.  */
178             status =  TX_SIZE_ERROR;
179         }
180 
181         /* Check for an invalid message size - greater than 16.  */
182         else if (message_size > TX_16_ULONG)
183         {
184 
185             /* Invalid message size specified.  */
186             status =  TX_SIZE_ERROR;
187         }
188 
189         /* Check on the queue size.  */
190         else if ((queue_size/(sizeof(ULONG))) < message_size)
191         {
192 
193             /* Invalid queue size specified.  */
194             status =  TX_SIZE_ERROR;
195         }
196         else
197         {
198 
199 #ifndef TX_TIMER_PROCESS_IN_ISR
200 
201             /* Pickup thread pointer.  */
202             TX_THREAD_GET_CURRENT(thread_ptr)
203 
204             /* Check for invalid caller of this function.  First check for a calling thread.  */
205             if (thread_ptr == &_tx_timer_thread)
206             {
207 
208                 /* Invalid caller of this function, return appropriate error code.  */
209                 status =  TX_CALLER_ERROR;
210             }
211 #endif
212 
213             /* Check for interrupt call.  */
214             if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
215             {
216 
217                 /* Now, make sure the call is from an interrupt and not initialization.  */
218                 if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
219                 {
220 
221                     /* Invalid caller of this function, return appropriate error code.  */
222                     status =  TX_CALLER_ERROR;
223                 }
224             }
225         }
226     }
227 
228     /* Determine if everything is okay.  */
229     if (status == TX_SUCCESS)
230     {
231 
232         /* Call actual queue create function.  */
233         status =  _tx_queue_create(queue_ptr, name_ptr, message_size, queue_start, queue_size);
234     }
235 
236     /* Return completion status.  */
237     return(status);
238 }
239