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 /** Timer */
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_timer.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _tx_timer_info_get PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function retrieves information from the specified timer. */
46 /* */
47 /* INPUT */
48 /* */
49 /* timer_ptr Pointer to timer control block */
50 /* name Destination for the timer name */
51 /* active Destination for active flag */
52 /* remaining_ticks Destination for remaining ticks */
53 /* before expiration */
54 /* reschedule_ticks Destination for reschedule ticks */
55 /* next_timer Destination for next timer on the */
56 /* created list */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* status Completion status */
61 /* */
62 /* CALLS */
63 /* */
64 /* None */
65 /* */
66 /* CALLED BY */
67 /* */
68 /* Application Code */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
75 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
76 /* resulting in version 6.1 */
77 /* */
78 /**************************************************************************/
_tx_timer_info_get(TX_TIMER * timer_ptr,CHAR ** name,UINT * active,ULONG * remaining_ticks,ULONG * reschedule_ticks,TX_TIMER ** next_timer)79 UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks,
80 ULONG *reschedule_ticks, TX_TIMER **next_timer)
81 {
82
83 TX_INTERRUPT_SAVE_AREA
84
85 TX_TIMER_INTERNAL *internal_ptr;
86 TX_TIMER_INTERNAL **list_head;
87 ULONG ticks_left;
88 UINT timer_active;
89 UINT active_timer_list;
90
91
92 /* Disable interrupts. */
93 TX_DISABLE
94
95 /* If trace is enabled, insert this event into the trace buffer. */
96 TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_INFO_GET, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS)
97
98 /* Log this kernel call. */
99 TX_EL_TIMER_INFO_GET_INSERT
100
101 /* Retrieve the name of the timer. */
102 if (name != TX_NULL)
103 {
104
105 *name = timer_ptr -> tx_timer_name;
106 }
107
108 /* Pickup address of internal timer structure. */
109 internal_ptr = &(timer_ptr -> tx_timer_internal);
110
111 /* Retrieve all the pertinent information and return it in the supplied
112 destinations. */
113
114 /* Default active to false. */
115 timer_active = TX_FALSE;
116
117 /* Default the ticks left to the remaining ticks. */
118 ticks_left = internal_ptr -> tx_timer_internal_remaining_ticks;
119
120 /* Determine if the timer is still active. */
121 if (internal_ptr -> tx_timer_internal_list_head != TX_NULL)
122 {
123
124 /* Indicate this timer is active. */
125 timer_active = TX_TRUE;
126
127 /* Default the active timer list flag to false. */
128 active_timer_list = TX_FALSE;
129
130 /* Determine if the timer is still active. */
131 if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_list_start)
132 {
133
134 /* Determine if the list head is before the end of the list. */
135 if (internal_ptr -> tx_timer_internal_list_head < _tx_timer_list_end)
136 {
137
138 /* This timer is active and has not yet expired. */
139 active_timer_list = TX_TRUE;
140 }
141 }
142
143 /* Determine if the timer is on the active timer list. */
144 if (active_timer_list == TX_TRUE)
145 {
146
147 /* Calculate the amount of time that has elapsed since the timer
148 was activated. */
149
150 /* Setup the list head pointer. */
151 list_head = internal_ptr -> tx_timer_internal_list_head;
152
153 /* Is this timer's entry after the current timer pointer? */
154 if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_current_ptr)
155 {
156
157 /* Calculate ticks left to expiration - just the difference between this
158 timer's entry and the current timer pointer. */
159 ticks_left = ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_current_ptr)) + ((ULONG) 1));
160 }
161 else
162 {
163
164 /* Calculate the ticks left with a wrapped list condition. */
165 ticks_left = ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_list_start)));
166
167 ticks_left = ticks_left + ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1));
168 }
169
170 /* Adjust the remaining ticks accordingly. */
171 if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
172 {
173
174 /* Subtract off the last full pass through the timer list and add the
175 time left. */
176 ticks_left = (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left;
177 }
178
179 }
180 else
181 {
182
183 /* The timer is not on the actual timer list so it must either be being processed
184 or on a temporary list to be processed. */
185
186 /* Check to see if this timer is the timer currently being processed. */
187 if (_tx_timer_expired_timer_ptr == internal_ptr)
188 {
189
190 /* Timer dispatch routine is executing, waiting to execute, or just finishing. No more remaining ticks for this expiration. */
191 ticks_left = ((ULONG) 0);
192 }
193 else
194 {
195
196 /* Timer is not the one being processed, which means it must be on the temporary expiration list
197 waiting to be processed. */
198
199 /* Calculate the remaining ticks for a timer in the process of expiring. */
200 if (ticks_left > TX_TIMER_ENTRIES)
201 {
202
203 /* Calculate the number of ticks remaining. */
204 ticks_left = internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES;
205 }
206 else
207 {
208
209 /* Timer dispatch routine is waiting to execute, no more remaining ticks for this expiration. */
210 ticks_left = ((ULONG) 0);
211 }
212 }
213 }
214 }
215
216 /* Setup return values for an inactive timer. */
217 if (active != TX_NULL)
218 {
219
220 /* Setup the timer active indication. */
221 *active = timer_active;
222 }
223 if (remaining_ticks != TX_NULL)
224 {
225
226 /* Setup the default remaining ticks value. */
227 *remaining_ticks = ticks_left;
228 }
229
230 /* Pickup the reschedule ticks value. */
231 if (reschedule_ticks != TX_NULL)
232 {
233
234 *reschedule_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks;
235 }
236
237 /* Pickup the next created application timer. */
238 if (next_timer != TX_NULL)
239 {
240
241 *next_timer = timer_ptr -> tx_timer_created_next;
242 }
243
244 /* Restore interrupts. */
245 TX_RESTORE
246
247 /* Return completion status. */
248 return(TX_SUCCESS);
249 }
250
251