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 /** ThreadX Component */
17 /** */
18 /** Semaphore */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define TX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "tx_api.h"
29 #include "tx_trace.h"
30 #include "tx_thread.h"
31 #include "tx_semaphore.h"
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _tx_semaphore_ceiling_put PORTABLE C */
39 /* 6.1 */
40 /* AUTHOR */
41 /* */
42 /* William E. Lamie, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function puts an instance into the specified counting */
47 /* semaphore up to the specified semaphore ceiling. */
48 /* */
49 /* INPUT */
50 /* */
51 /* semaphore_ptr Pointer to semaphore */
52 /* ceiling Maximum value of semaphore */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* _tx_thread_system_resume Resume thread service */
61 /* _tx_thread_system_ni_resume Non-interruptable resume */
62 /* thread */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Application Code */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
73 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_tx_semaphore_ceiling_put(TX_SEMAPHORE * semaphore_ptr,ULONG ceiling)77 UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling)
78 {
79
80 TX_INTERRUPT_SAVE_AREA
81
82 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
83 VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr);
84 #endif
85
86 TX_THREAD *thread_ptr;
87 UINT suspended_count;
88 TX_THREAD *next_thread;
89 TX_THREAD *previous_thread;
90 UINT status;
91
92
93 /* Default the status to TX_SUCCESS. */
94 status = TX_SUCCESS;
95
96 /* Disable interrupts to put an instance back to the semaphore. */
97 TX_DISABLE
98
99 #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
100
101 /* Increment the total semaphore put counter. */
102 _tx_semaphore_performance_put_count++;
103
104 /* Increment the number of puts on this semaphore. */
105 semaphore_ptr -> tx_semaphore_performance_put_count++;
106 #endif
107
108 /* If trace is enabled, insert this event into the trace buffer. */
109 TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, ceiling, TX_TRACE_SEMAPHORE_EVENTS)
110
111 /* Log this kernel call. */
112 TX_EL_SEMAPHORE_CEILING_PUT_INSERT
113
114 /* Pickup the number of suspended threads. */
115 suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
116
117 /* Determine if there are any threads suspended on the semaphore. */
118 if (suspended_count == TX_NO_SUSPENSIONS)
119 {
120
121 /* Determine if the ceiling has been exceeded. */
122 if (semaphore_ptr -> tx_semaphore_count >= ceiling)
123 {
124
125 /* Restore interrupts. */
126 TX_RESTORE
127
128 /* Return an error. */
129 status = TX_CEILING_EXCEEDED;
130 }
131 else
132 {
133
134 /* Increment the semaphore count. */
135 semaphore_ptr -> tx_semaphore_count++;
136
137 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
138
139 /* Pickup the application notify function. */
140 semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
141 #endif
142
143 /* Restore interrupts. */
144 TX_RESTORE
145
146 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
147
148 /* Determine if notification is required. */
149 if (semaphore_put_notify != TX_NULL)
150 {
151
152 /* Yes, call the appropriate notify callback function. */
153 (semaphore_put_notify)(semaphore_ptr);
154 }
155 #endif
156
157 /* Return successful completion status. */
158 status = TX_SUCCESS;
159 }
160 }
161 else
162 {
163
164 /* Remove the suspended thread from the list. */
165
166 /* Pickup the pointer to the first suspended thread. */
167 thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
168
169 /* See if this is the only suspended thread on the list. */
170 suspended_count--;
171 if (suspended_count == TX_NO_SUSPENSIONS)
172 {
173
174 /* Yes, the only suspended thread. */
175
176 /* Update the head pointer. */
177 semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
178 }
179 else
180 {
181
182 /* At least one more thread is on the same expiration list. */
183
184 /* Update the list head pointer. */
185 next_thread = thread_ptr -> tx_thread_suspended_next;
186 semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
187
188 /* Update the links of the adjacent threads. */
189 previous_thread = thread_ptr -> tx_thread_suspended_previous;
190 next_thread -> tx_thread_suspended_previous = previous_thread;
191 previous_thread -> tx_thread_suspended_next = next_thread;
192 }
193
194 /* Decrement the suspension count. */
195 semaphore_ptr -> tx_semaphore_suspended_count = suspended_count;
196
197 /* Prepare for resumption of the first thread. */
198
199 /* Clear cleanup routine to avoid timeout. */
200 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
201
202 /* Put return status into the thread control block. */
203 thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
204
205 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
206
207 /* Pickup the application notify function. */
208 semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
209 #endif
210
211 #ifdef TX_NOT_INTERRUPTABLE
212
213 /* Resume the thread! */
214 _tx_thread_system_ni_resume(thread_ptr);
215
216 /* Restore interrupts. */
217 TX_RESTORE
218 #else
219
220 /* Temporarily disable preemption. */
221 _tx_thread_preempt_disable++;
222
223 /* Restore interrupts. */
224 TX_RESTORE
225
226 /* Resume thread. */
227 _tx_thread_system_resume(thread_ptr);
228 #endif
229
230 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
231
232 /* Determine if notification is required. */
233 if (semaphore_put_notify != TX_NULL)
234 {
235
236 /* Yes, call the appropriate notify callback function. */
237 (semaphore_put_notify)(semaphore_ptr);
238 }
239 #endif
240 }
241
242 /* Return successful completion. */
243 return(status);
244 }
245
246