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 /**   Mutex                                                               */
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_thread.h"
30 #include "tx_timer.h"
31 #include "tx_mutex.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _txe_mutex_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 create mutex function        */
47 /*    call.                                                               */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    mutex_ptr                         Pointer to mutex control block    */
52 /*    name_ptr                          Pointer to mutex name             */
53 /*    inherit                           Initial mutex count               */
54 /*    mutex_control_block_size          Size of mutex control block       */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    TX_MUTEX_ERROR                    Invalid mutex pointer             */
59 /*    TX_CALLER_ERROR                   Invalid caller of this function   */
60 /*    TX_INHERIT_ERROR                  Invalid inherit option            */
61 /*    status                            Actual completion status          */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    _tx_mutex_create                  Actual create mutex function      */
66 /*    _tx_thread_system_preempt_check   Check for preemption              */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    Application Code                                                    */
71 /*                                                                        */
72 /*  RELEASE HISTORY                                                       */
73 /*                                                                        */
74 /*    DATE              NAME                      DESCRIPTION             */
75 /*                                                                        */
76 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
77 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
78 /*                                            resulting in version 6.1    */
79 /*                                                                        */
80 /**************************************************************************/
_txe_mutex_create(TX_MUTEX * mutex_ptr,CHAR * name_ptr,UINT inherit,UINT mutex_control_block_size)81 UINT  _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size)
82 {
83 
84 TX_INTERRUPT_SAVE_AREA
85 
86 UINT            status;
87 ULONG           i;
88 TX_MUTEX        *next_mutex;
89 #ifndef TX_TIMER_PROCESS_IN_ISR
90 TX_THREAD       *thread_ptr;
91 #endif
92 
93 
94     /* Default status to success.  */
95     status =  TX_SUCCESS;
96 
97     /* Check for an invalid mutex pointer.  */
98     if (mutex_ptr == TX_NULL)
99     {
100 
101         /* Mutex pointer is invalid, return appropriate error code.  */
102         status =  TX_MUTEX_ERROR;
103     }
104 
105     /* Now check to make sure the control block is the correct size.  */
106     else if (mutex_control_block_size != (sizeof(TX_MUTEX)))
107     {
108 
109         /* Mutex pointer is invalid, return appropriate error code.  */
110         status =  TX_MUTEX_ERROR;
111     }
112     else
113     {
114 
115         /* Disable interrupts.  */
116         TX_DISABLE
117 
118         /* Increment the preempt disable flag.  */
119         _tx_thread_preempt_disable++;
120 
121         /* Restore interrupts.  */
122         TX_RESTORE
123 
124         /* Next see if it is already in the created list.  */
125         next_mutex =   _tx_mutex_created_ptr;
126         for (i = ((ULONG) 0); i < _tx_mutex_created_count; i++)
127         {
128 
129             /* Determine if this mutex matches the mutex in the list.  */
130             if (mutex_ptr == next_mutex)
131             {
132 
133                 break;
134             }
135             else
136             {
137 
138                 /* Move to the next mutex.  */
139                 next_mutex =  next_mutex -> tx_mutex_created_next;
140             }
141         }
142 
143         /* Disable interrupts.  */
144         TX_DISABLE
145 
146         /* Decrement the preempt disable flag.  */
147         _tx_thread_preempt_disable--;
148 
149         /* Restore interrupts.  */
150         TX_RESTORE
151 
152         /* Check for preemption.  */
153         _tx_thread_system_preempt_check();
154 
155         /* At this point, check to see if there is a duplicate mutex.  */
156         if (mutex_ptr == next_mutex)
157         {
158 
159             /* Mutex is already created, return appropriate error code.  */
160             status =  TX_MUTEX_ERROR;
161         }
162         else
163         {
164 
165             /* Check for a valid inherit option.  */
166             if (inherit != TX_INHERIT)
167             {
168 
169                 if (inherit != TX_NO_INHERIT)
170                 {
171 
172                     /* Inherit option is illegal.  */
173                     status =  TX_INHERIT_ERROR;
174                 }
175             }
176         }
177     }
178 
179     /* Determine if everything is okay.  */
180     if (status == TX_SUCCESS)
181     {
182 
183 #ifndef TX_TIMER_PROCESS_IN_ISR
184 
185         /* Pickup thread pointer.  */
186         TX_THREAD_GET_CURRENT(thread_ptr)
187 
188         /* Check for invalid caller of this function.  First check for a calling thread.  */
189         if (thread_ptr == &_tx_timer_thread)
190         {
191 
192             /* Invalid caller of this function, return appropriate error code.  */
193             status =  TX_CALLER_ERROR;
194         }
195 #endif
196 
197         /* Check for interrupt call.  */
198         if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
199         {
200 
201             /* Now, make sure the call is from an interrupt and not initialization.  */
202             if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
203             {
204 
205                 /* Invalid caller of this function, return appropriate error code.  */
206                 status =  TX_CALLER_ERROR;
207             }
208         }
209     }
210 
211     /* Determine if everything is okay.  */
212     if (status == TX_SUCCESS)
213     {
214 
215         /* Call actual mutex create function.  */
216         status =  _tx_mutex_create(mutex_ptr, name_ptr, inherit);
217     }
218 
219     /* Return completion status.  */
220     return(status);
221 }
222 
223