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