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 /**   Execution Profile Kit                                               */
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_execution_profile.h"
29 
30 /* Note to developers upgrading from ThreadX version 5: In ThreadX 5, the instruction was to
31    modify TX_THREAD_EXTENSION_3, and to define the symbol TX_ENABLE_EXECUTION_CHANGE_NOTIFY.
32 
33    For ThreadX 6, user no long need to modify TX_THREAD_EXTENSION_3, and shall use the symbol
34    TX_EXECUTION_PROFILE_ENABLE instead of TX_ENABLE_EXECUTION_CHANGE_NOTIFY.
35 
36    For backward compatibiliy reasons, project upgraded from ThreadX 5 may still be able to use
37    Execution Profile without changes to existing project, users are strongly recommended to
38    make the change.  */
39 
40 
41 #if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
42 
43 /* The thread execution profile kit is designed to track thread execution time
44    based on the hardware timer defined by TX_EXECUTION_TIME_SOURCE and
45    TX_EXECUTION_MAX_TIME_SOURCE below. When the thread's total time reaches
46    the maximum value, it remains there until the time is reset to 0 via a call
47    to tx_thread_execution_time_reset. There are several assumptions to the
48    operation of this kit, as follows:
49 
50    1. The TX_EXECUTION_TIME_SOURCE and TX_EXECUTION_MAX_TIME_SOURCE macros are
51       defined to utilize a local hardware time source.
52 
53    2. ThreadX 5.4 (or later) is being used, with the assembly code enabled to
54       call the following routines from assembly code:
55 
56             VOID  _tx_execution_thread_enter(void);
57             VOID  _tx_execution_thread_exit(void);
58             VOID  _tx_execution_isr_enter(void);
59             VOID  _tx_execution_isr_exit(void);
60 
61     3. The ThreadX library assembly code must be rebuilt with TX_EXECUTION_PROFILE_ENABLE so
62        that these macros are expanded in the TX_THREAD structure and so the assembly code macros
63        are enabled to call the execution profile routines.
64 
65     4. Add tx_execution_profile.c to the application build.  */
66 
67 
68 /* Externally reference several internal ThreadX variables.  */
69 
70 extern ULONG                            _tx_thread_system_state;
71 extern UINT                             _tx_thread_preempt_disable;
72 extern TX_THREAD                        *_tx_thread_current_ptr;
73 extern TX_THREAD                        *_tx_thread_execute_ptr;
74 extern TX_THREAD                        *_tx_thread_created_ptr;
75 extern ULONG                            _tx_thread_created_count;
76 
77 
78 /* Define the total time for all threads.  This is accumulated as each thread's total time is accumulated.  */
79 
80 EXECUTION_TIME                          _tx_execution_thread_time_total;
81 
82 
83 /* Define the ISR time gathering information. This is setup to track total ISR time presently, but
84    could easily be expanded to track different ISRs. Also, only ISRs that utilize _tx_thread_context_save
85    and _tx_thread_context_restore are tracked by this utility.  */
86 
87 EXECUTION_TIME                          _tx_execution_isr_time_total;
88 EXECUTION_TIME_SOURCE_TYPE              _tx_execution_isr_time_last_start;
89 
90 
91 /* Define the system idle time gathering information. For idle time that exceeds the range of the timer
92    source, another timer source may be needed. In addition, the total thread execution time added to the
93    total ISR time, less the total system time is also a measure of idle time.  */
94 
95 EXECUTION_TIME                          _tx_execution_idle_time_total;
96 EXECUTION_TIME_SOURCE_TYPE              _tx_execution_idle_time_last_start;
97 UINT                                    _tx_execution_idle_active;
98 
99 /* For Cortex-M targets, we need to keep track of nested interrupts internally.  */
100 #ifdef TX_CORTEX_M_EPK
101 ULONG                                   _tx_execution_isr_nest_counter = 0;
102 #endif
103 
104 
105 /**************************************************************************/
106 /*                                                                        */
107 /*  FUNCTION                                               RELEASE        */
108 /*                                                                        */
109 /*    _tx_execution_initialize                            PORTABLE C      */
110 /*                                                           6.1.11       */
111 /*  AUTHOR                                                                */
112 /*                                                                        */
113 /*    Scott Larson, Microsoft Corporation                                 */
114 /*                                                                        */
115 /*  DESCRIPTION                                                           */
116 /*                                                                        */
117 /*    This function is called at initialization.                          */
118 /*                                                                        */
119 /*  INPUT                                                                 */
120 /*                                                                        */
121 /*    None                                                                */
122 /*                                                                        */
123 /*  OUTPUT                                                                */
124 /*                                                                        */
125 /*    None                                                                */
126 /*                                                                        */
127 /*  CALLS                                                                 */
128 /*                                                                        */
129 /*    None                                                                */
130 /*                                                                        */
131 /*  CALLED BY                                                             */
132 /*                                                                        */
133 /*    xxx                               xxx                               */
134 /*                                                                        */
135 /*  RELEASE HISTORY                                                       */
136 /*                                                                        */
137 /*    DATE              NAME                      DESCRIPTION             */
138 /*                                                                        */
139 /*  04-25-2022      Scott Larson            Initial Version 6.1.11        */
140 /*                                                                        */
141 /**************************************************************************/
_tx_execution_initialize(void)142 VOID  _tx_execution_initialize(void)
143 {
144     /* In idle mode until a thread is scheduled or ISR occurs.  */
145     _tx_execution_idle_active = TX_TRUE;
146 
147     /* Pickup the start of idle time.  */
148     _tx_execution_idle_time_last_start =  TX_EXECUTION_TIME_SOURCE;
149 }
150 
151 
152 /**************************************************************************/
153 /*                                                                        */
154 /*  FUNCTION                                               RELEASE        */
155 /*                                                                        */
156 /*    _tx_execution_thread_enter                          PORTABLE C      */
157 /*                                                           6.1.11       */
158 /*  AUTHOR                                                                */
159 /*                                                                        */
160 /*    William E. Lamie, Microsoft Corporation                             */
161 /*                                                                        */
162 /*  DESCRIPTION                                                           */
163 /*                                                                        */
164 /*    This function is called whenever thread execution starts.           */
165 /*                                                                        */
166 /*  INPUT                                                                 */
167 /*                                                                        */
168 /*    None                                                                */
169 /*                                                                        */
170 /*  OUTPUT                                                                */
171 /*                                                                        */
172 /*    None                                                                */
173 /*                                                                        */
174 /*  CALLS                                                                 */
175 /*                                                                        */
176 /*    None                                                                */
177 /*                                                                        */
178 /*  CALLED BY                                                             */
179 /*                                                                        */
180 /*    _tx_thread_schedule               Thread scheduling                 */
181 /*                                                                        */
182 /*  RELEASE HISTORY                                                       */
183 /*                                                                        */
184 /*    DATE              NAME                      DESCRIPTION             */
185 /*                                                                        */
186 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
187 /*  04-25-2022      Scott Larson            Modified comments and fixed   */
188 /*                                            wrap-around calculation,    */
189 /*                                            resulting in version 6.1.11 */
190 /*                                                                        */
191 /**************************************************************************/
_tx_execution_thread_enter(void)192 VOID  _tx_execution_thread_enter(void)
193 {
194 
195 TX_THREAD                   *thread_ptr;
196 EXECUTION_TIME_SOURCE_TYPE  last_start_time;
197 EXECUTION_TIME_SOURCE_TYPE  current_time;
198 EXECUTION_TIME              delta_time;
199 EXECUTION_TIME              total_time;
200 EXECUTION_TIME              new_total_time;
201 
202 
203     /* Pickup the current time.  */
204     current_time =  TX_EXECUTION_TIME_SOURCE;
205 
206     /* Pickup the current thread control block.  */
207     thread_ptr =  _tx_thread_current_ptr;
208 
209     /* This thread is being scheduled.  Simply setup the last start time in the
210        thread control block.  */
211     thread_ptr -> tx_thread_execution_time_last_start =  current_time;
212 
213     /* Pickup the last idle start time.  */
214     last_start_time =  _tx_execution_idle_time_last_start;
215 
216     /* Determine if idle time is being measured.  */
217     if (_tx_execution_idle_active)
218     {
219 
220         /* Determine how to calculate the difference.  */
221         if (current_time >= last_start_time)
222         {
223 
224             /* Simply subtract.  */
225             delta_time =  (EXECUTION_TIME) (current_time - last_start_time);
226         }
227         else
228         {
229 
230             /* Timer wrapped, compute the delta assuming incrementing time counter.  */
231             delta_time =  (EXECUTION_TIME) (current_time + ((((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) + 1) - last_start_time));
232         }
233 
234         /* Pickup the total time.  */
235         total_time =  _tx_execution_idle_time_total;
236 
237         /* Now compute the new total time.  */
238         new_total_time =  total_time + delta_time;
239 
240         /* Determine if a rollover on the total time is present.  */
241         if (new_total_time < total_time)
242         {
243 
244             /* Rollover. Set the total time to max value.  */
245             new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
246         }
247 
248         /* Now store back the total idle time.  */
249         _tx_execution_idle_time_total =  new_total_time;
250 
251         /* Disable the idle time measurement.  */
252         _tx_execution_idle_active = TX_FALSE;
253     }
254 }
255 
256 
257 /**************************************************************************/
258 /*                                                                        */
259 /*  FUNCTION                                               RELEASE        */
260 /*                                                                        */
261 /*    _tx_execution_thread_exit                           PORTABLE C      */
262 /*                                                           6.1.11       */
263 /*  AUTHOR                                                                */
264 /*                                                                        */
265 /*    William E. Lamie, Microsoft Corporation                             */
266 /*                                                                        */
267 /*  DESCRIPTION                                                           */
268 /*                                                                        */
269 /*    This function is called whenever a thread execution ends.           */
270 /*                                                                        */
271 /*  INPUT                                                                 */
272 /*                                                                        */
273 /*    None                                                                */
274 /*                                                                        */
275 /*  OUTPUT                                                                */
276 /*                                                                        */
277 /*    None                                                                */
278 /*                                                                        */
279 /*  CALLS                                                                 */
280 /*                                                                        */
281 /*    None                                                                */
282 /*                                                                        */
283 /*  CALLED BY                                                             */
284 /*                                                                        */
285 /*    _tx_thread_system_return          Thread exiting                    */
286 /*                                                                        */
287 /*  RELEASE HISTORY                                                       */
288 /*                                                                        */
289 /*    DATE              NAME                      DESCRIPTION             */
290 /*                                                                        */
291 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
292 /*  04-25-2022      Scott Larson            Modified comments and fixed   */
293 /*                                            wrap-around calculation,    */
294 /*                                            resulting in version 6.1.11 */
295 /*                                                                        */
296 /**************************************************************************/
_tx_execution_thread_exit(void)297 VOID  _tx_execution_thread_exit(void)
298 {
299 
300 TX_THREAD                   *thread_ptr;
301 EXECUTION_TIME              total_time;
302 EXECUTION_TIME              new_total_time;
303 EXECUTION_TIME_SOURCE_TYPE  last_start_time;
304 EXECUTION_TIME_SOURCE_TYPE  current_time;
305 EXECUTION_TIME              delta_time;
306 
307 
308     /* Pickup the current thread control block.  */
309     thread_ptr =  _tx_thread_current_ptr;
310 
311     /* Determine if there is a thread.  */
312     if (thread_ptr)
313     {
314 
315         /* Pickup the current time.  */
316         current_time =  TX_EXECUTION_TIME_SOURCE;
317 
318         /* Pickup the last start time.  */
319         last_start_time =  thread_ptr -> tx_thread_execution_time_last_start;
320 
321         /* Determine if there is an actual start time.  */
322         if (last_start_time)
323         {
324 
325             /* Clear the last start time.  */
326             thread_ptr -> tx_thread_execution_time_last_start =  0;
327 
328             /* Determine how to calculate the difference.  */
329             if (current_time >= last_start_time)
330             {
331 
332                 /* Simply subtract.  */
333                 delta_time =  (EXECUTION_TIME) (current_time - last_start_time);
334             }
335             else
336             {
337 
338                 /* Timer wrapped, compute the delta assuming incrementing time counter.  */
339                 delta_time =  (EXECUTION_TIME) (current_time + ((((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) + 1) - last_start_time));
340             }
341 
342             /* Pickup the total time.  */
343             total_time =  thread_ptr -> tx_thread_execution_time_total;
344 
345             /* Now compute the new total time.  */
346             new_total_time =  total_time + delta_time;
347 
348             /* Determine if a rollover on the total time is present.  */
349             if (new_total_time < total_time)
350             {
351 
352                 /* Rollover. Set the total time to max value.  */
353                 new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
354             }
355 
356             /* Store back the new total time.  */
357             thread_ptr -> tx_thread_execution_time_total =  new_total_time;
358 
359             /* Now accumulate this thread's execution time into the total thread execution time.  */
360             new_total_time =  _tx_execution_thread_time_total + delta_time;
361 
362             /* Determine if a rollover on the total time is present.  */
363             if (new_total_time < _tx_execution_thread_time_total)
364             {
365 
366                 /* Rollover. Set the total time to max value.  */
367                 new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
368             }
369 
370             /* Store back the new total time.  */
371             _tx_execution_thread_time_total =  new_total_time;
372         }
373 
374         /* Is the system now idle?  */
375         if (_tx_thread_execute_ptr == TX_NULL)
376         {
377             /* Yes, idle system. Pickup the start of idle time.  */
378             _tx_execution_idle_time_last_start =  TX_EXECUTION_TIME_SOURCE;
379             _tx_execution_idle_active = TX_TRUE;
380         }
381     }
382 }
383 
384 
385 /**************************************************************************/
386 /*                                                                        */
387 /*  FUNCTION                                               RELEASE        */
388 /*                                                                        */
389 /*    _tx_execution_isr_enter                             PORTABLE C      */
390 /*                                                           6.1.11       */
391 /*  AUTHOR                                                                */
392 /*                                                                        */
393 /*    William E. Lamie, Microsoft Corporation                             */
394 /*                                                                        */
395 /*  DESCRIPTION                                                           */
396 /*                                                                        */
397 /*    This function is called whenever ISR processing starts.             */
398 /*                                                                        */
399 /*  INPUT                                                                 */
400 /*                                                                        */
401 /*    None                                                                */
402 /*                                                                        */
403 /*  OUTPUT                                                                */
404 /*                                                                        */
405 /*    None                                                                */
406 /*                                                                        */
407 /*  CALLS                                                                 */
408 /*                                                                        */
409 /*    None                                                                */
410 /*                                                                        */
411 /*  CALLED BY                                                             */
412 /*                                                                        */
413 /*    _tx_thread_context_save           ISR context save                  */
414 /*                                                                        */
415 /*  RELEASE HISTORY                                                       */
416 /*                                                                        */
417 /*    DATE              NAME                      DESCRIPTION             */
418 /*                                                                        */
419 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
420 /*  04-25-2022      Scott Larson            Modified comments and fixed   */
421 /*                                            wrap-around calculation,    */
422 /*                                            resulting in version 6.1.11 */
423 /*                                                                        */
424 /**************************************************************************/
_tx_execution_isr_enter(void)425 VOID  _tx_execution_isr_enter(void)
426 {
427 
428 TX_THREAD                   *thread_ptr;
429 EXECUTION_TIME_SOURCE_TYPE  current_time;
430 EXECUTION_TIME              total_time;
431 EXECUTION_TIME              new_total_time;
432 EXECUTION_TIME_SOURCE_TYPE  last_start_time;
433 EXECUTION_TIME              delta_time;
434 
435 #ifdef TX_CORTEX_M_EPK
436     /* Increment the nested interrupt counter.  */
437     _tx_execution_isr_nest_counter++;
438 #endif
439 
440     /* Determine if this is the first interrupt. Nested interrupts are all treated as
441        general interrupt processing.  */
442 #ifdef TX_CORTEX_M_EPK
443     if ((TX_THREAD_GET_SYSTEM_STATE()) && (_tx_execution_isr_nest_counter == 1))
444 #else
445     if (TX_THREAD_GET_SYSTEM_STATE() == 1)
446 #endif
447     {
448         /* Pickup the current time.  */
449         current_time =  TX_EXECUTION_TIME_SOURCE;
450 
451         /* Pickup the current thread control block.  */
452         thread_ptr =  _tx_thread_current_ptr;
453 
454         /* Determine if a thread was interrupted.  */
455         if (thread_ptr)
456         {
457 
458             /* Pickup the last start time.  */
459             last_start_time =  thread_ptr -> tx_thread_execution_time_last_start;
460 
461             /* Determine if there is an actual start time.  */
462             if (last_start_time)
463             {
464 
465                 /* Clear the last start time.  */
466                 thread_ptr -> tx_thread_execution_time_last_start =  0;
467 
468                 /* Determine how to calculate the difference.  */
469                 if (current_time >= last_start_time)
470                 {
471 
472                     /* Simply subtract.  */
473                     delta_time =  (EXECUTION_TIME) (current_time - last_start_time);
474                 }
475                 else
476                 {
477 
478                     /* Timer wrapped, compute the delta assuming incrementing time counter.  */
479                     delta_time =  (EXECUTION_TIME) (current_time + ((((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) + 1) - last_start_time));
480                 }
481 
482                 /* Pickup the total time.  */
483                 total_time =  thread_ptr -> tx_thread_execution_time_total;
484 
485                 /* Now compute the new total time.  */
486                 new_total_time =  total_time + delta_time;
487 
488                 /* Determine if a rollover on the total time is present.  */
489                 if (new_total_time < total_time)
490                 {
491 
492                     /* Rollover. Set the total time to max value.  */
493                     new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
494                 }
495 
496                 /* Store back the new total time.  */
497                 thread_ptr -> tx_thread_execution_time_total =  new_total_time;
498 
499                 /* Now accumulate this thread's execution time into the total thread execution time.  */
500                 new_total_time =  _tx_execution_thread_time_total + delta_time;
501 
502                 /* Determine if a rollover on the total time is present.  */
503                 if (new_total_time < _tx_execution_thread_time_total)
504                 {
505 
506                     /* Rollover. Set the total time to max value.  */
507                     new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
508                 }
509 
510                 /* Store back the new total time.  */
511                 _tx_execution_thread_time_total =  new_total_time;
512             }
513         }
514 
515         /* Has idle time started?  */
516         else if (_tx_execution_idle_active)
517         {
518 
519             /* Pickup the last idle start time.  */
520             last_start_time =  _tx_execution_idle_time_last_start;
521 
522             /* Determine how to calculate the difference.  */
523             if (current_time >= last_start_time)
524             {
525 
526                 /* Simply subtract.  */
527                 delta_time =  (EXECUTION_TIME) (current_time - last_start_time);
528             }
529             else
530             {
531 
532                 /* Timer wrapped, compute the delta assuming incrementing time counter.  */
533                 delta_time =  (EXECUTION_TIME) (current_time + ((((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) + 1) - last_start_time));
534             }
535 
536             /* Pickup the total time.  */
537             total_time =  _tx_execution_idle_time_total;
538 
539             /* Now compute the new total time.  */
540             new_total_time =  total_time + delta_time;
541 
542             /* Determine if a rollover on the total time is present.  */
543             if (new_total_time < total_time)
544             {
545 
546                 /* Rollover. Set the total time to max value.  */
547                 new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
548             }
549 
550             /* Now store back the total idle time.  */
551             _tx_execution_idle_time_total =  new_total_time;
552 
553             /* Disable the idle time measurement.  */
554             _tx_execution_idle_active = TX_FALSE;
555         }
556 
557         /* Save the ISR start time.  */
558         _tx_execution_isr_time_last_start =  current_time;
559     }
560 }
561 
562 
563 /**************************************************************************/
564 /*                                                                        */
565 /*  FUNCTION                                               RELEASE        */
566 /*                                                                        */
567 /*    _tx_execution_isr_exit                              PORTABLE C      */
568 /*                                                           6.1.11       */
569 /*  AUTHOR                                                                */
570 /*                                                                        */
571 /*    William E. Lamie, Microsoft Corporation                             */
572 /*                                                                        */
573 /*  DESCRIPTION                                                           */
574 /*                                                                        */
575 /*    This function is called whenever ISR processing ends.               */
576 /*                                                                        */
577 /*  INPUT                                                                 */
578 /*                                                                        */
579 /*    None                                                                */
580 /*                                                                        */
581 /*  OUTPUT                                                                */
582 /*                                                                        */
583 /*    None                                                                */
584 /*                                                                        */
585 /*  CALLS                                                                 */
586 /*                                                                        */
587 /*    None                                                                */
588 /*                                                                        */
589 /*  CALLED BY                                                             */
590 /*                                                                        */
591 /*    _tx_thread_context_restore        Thread de-scheduling              */
592 /*                                                                        */
593 /*  RELEASE HISTORY                                                       */
594 /*                                                                        */
595 /*    DATE              NAME                      DESCRIPTION             */
596 /*                                                                        */
597 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
598 /*  04-25-2022      Scott Larson            Modified comments and fixed   */
599 /*                                            wrap-around calculation,    */
600 /*                                            resulting in version 6.1.11 */
601 /*                                                                        */
602 /**************************************************************************/
_tx_execution_isr_exit(void)603 VOID  _tx_execution_isr_exit(void)
604 {
605 
606 TX_THREAD                   *thread_ptr;
607 EXECUTION_TIME              total_time;
608 EXECUTION_TIME              new_total_time;
609 EXECUTION_TIME_SOURCE_TYPE  last_start_time;
610 EXECUTION_TIME_SOURCE_TYPE  current_time;
611 EXECUTION_TIME              delta_time;
612 
613 
614     /* Determine if this is the first interrupt. Nested interrupts are all treated as
615        general interrupt processing.  */
616 #ifdef TX_CORTEX_M_EPK
617     if ((TX_THREAD_GET_SYSTEM_STATE()) && (_tx_execution_isr_nest_counter == 1))
618 #else
619     if (TX_THREAD_GET_SYSTEM_STATE() == 1)
620 #endif
621     {
622 
623         /* Pickup the current time.  */
624         current_time =  TX_EXECUTION_TIME_SOURCE;
625 
626         /* Pickup the last start time.  */
627         last_start_time =  _tx_execution_isr_time_last_start;
628 
629         /* Determine how to calculate the difference.  */
630         if (current_time >= last_start_time)
631         {
632 
633            /* Simply subtract.  */
634            delta_time =  (EXECUTION_TIME) (current_time - last_start_time);
635         }
636         else
637         {
638 
639             /* Timer wrapped, compute the delta assuming incrementing time counter.  */
640             delta_time =  (EXECUTION_TIME) (current_time + (((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) - last_start_time));
641         }
642 
643         /* Pickup the total time.  */
644         total_time =  _tx_execution_isr_time_total;
645 
646         /* Now compute the new total time.  */
647         new_total_time =  total_time + delta_time;
648 
649         /* Determine if a rollover on the total time is present.  */
650         if (new_total_time < total_time)
651         {
652 
653             /* Rollover. Set the total time to max value.  */
654             new_total_time =  (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE;
655         }
656 
657         /* Store back the new total time.  */
658         _tx_execution_isr_time_total =  new_total_time;
659 
660         /* Pickup the current thread control block.  */
661         thread_ptr =  _tx_thread_current_ptr;
662 
663         /* Was a thread interrupted?  */
664         if (thread_ptr)
665         {
666 
667             /* Now determine if the thread will execution is going to occur immediately.  */
668             if ((thread_ptr == _tx_thread_execute_ptr) || (_tx_thread_preempt_disable))
669             {
670 
671                 /* Yes, setup the thread last start time in the thread control block.  */
672                 thread_ptr -> tx_thread_execution_time_last_start =  current_time;
673             }
674         }
675 
676         /* Determine if the system is now idle.  */
677         if (_tx_thread_execute_ptr == TX_NULL)
678         {
679 
680             /* Yes, idle system. Pickup the start of idle time.  */
681             _tx_execution_idle_time_last_start =  TX_EXECUTION_TIME_SOURCE;
682             _tx_execution_idle_active = TX_TRUE;
683         }
684     }
685 
686 #ifdef TX_CORTEX_M_EPK
687     /* Decrement the nested interrupt counter.  */
688     _tx_execution_isr_nest_counter--;
689 #endif
690 }
691 
692 
693 /**************************************************************************/
694 /*                                                                        */
695 /*  FUNCTION                                               RELEASE        */
696 /*                                                                        */
697 /*    _tx_execution_thread_time_reset                     PORTABLE C      */
698 /*                                                           6.1.7        */
699 /*  AUTHOR                                                                */
700 /*                                                                        */
701 /*    William E. Lamie, Microsoft Corporation                             */
702 /*                                                                        */
703 /*  DESCRIPTION                                                           */
704 /*                                                                        */
705 /*    This function resets the execution time of the specified thread.    */
706 /*                                                                        */
707 /*  INPUT                                                                 */
708 /*                                                                        */
709 /*    thread_ptr                        Pointer to thread                 */
710 /*                                                                        */
711 /*  OUTPUT                                                                */
712 /*                                                                        */
713 /*    status                            Completion status                 */
714 /*                                                                        */
715 /*  CALLS                                                                 */
716 /*                                                                        */
717 /*    None                                                                */
718 /*                                                                        */
719 /*  CALLED BY                                                             */
720 /*                                                                        */
721 /*    Application code                                                    */
722 /*                                                                        */
723 /*  RELEASE HISTORY                                                       */
724 /*                                                                        */
725 /*    DATE              NAME                      DESCRIPTION             */
726 /*                                                                        */
727 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
728 /*                                                                        */
729 /**************************************************************************/
_tx_execution_thread_time_reset(TX_THREAD * thread_ptr)730 UINT  _tx_execution_thread_time_reset(TX_THREAD *thread_ptr)
731 {
732 
733     /* Reset the total time to 0.  */
734     thread_ptr -> tx_thread_execution_time_total =  0;
735 
736     /* Return success.  */
737     return(TX_SUCCESS);
738 }
739 
740 
741 /**************************************************************************/
742 /*                                                                        */
743 /*  FUNCTION                                               RELEASE        */
744 /*                                                                        */
745 /*    _tx_execution_thread_total_time_reset               PORTABLE C      */
746 /*                                                           6.1.7        */
747 /*  AUTHOR                                                                */
748 /*                                                                        */
749 /*    William E. Lamie, Microsoft Corporation                             */
750 /*                                                                        */
751 /*  DESCRIPTION                                                           */
752 /*                                                                        */
753 /*    This function resets the total thread execution time.               */
754 /*                                                                        */
755 /*  INPUT                                                                 */
756 /*                                                                        */
757 /*    None                                                                */
758 /*                                                                        */
759 /*  OUTPUT                                                                */
760 /*                                                                        */
761 /*    status                            Completion status                 */
762 /*                                                                        */
763 /*  CALLS                                                                 */
764 /*                                                                        */
765 /*    None                                                                */
766 /*                                                                        */
767 /*  CALLED BY                                                             */
768 /*                                                                        */
769 /*    Application code                                                    */
770 /*                                                                        */
771 /*  RELEASE HISTORY                                                       */
772 /*                                                                        */
773 /*    DATE              NAME                      DESCRIPTION             */
774 /*                                                                        */
775 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
776 /*                                                                        */
777 /**************************************************************************/
_tx_execution_thread_total_time_reset(void)778 UINT  _tx_execution_thread_total_time_reset(void)
779 {
780 
781 TX_INTERRUPT_SAVE_AREA
782 
783 TX_THREAD       *thread_ptr;
784 UINT            total_threads;
785 
786 
787     /* Disable interrupts.  */
788     TX_DISABLE
789 
790     /* Reset the total time to 0.  */
791     _tx_execution_thread_time_total =  0;
792 
793     /* Loop through threads to clear their accumulated time.  */
794     total_threads =      _tx_thread_created_count;
795     thread_ptr =         _tx_thread_created_ptr;
796     while (total_threads--)
797     {
798         thread_ptr -> tx_thread_execution_time_total =  0;
799         thread_ptr =  thread_ptr -> tx_thread_created_next;
800     }
801 
802     /* Restore interrupts.  */
803     TX_RESTORE
804 
805     /* Return success.  */
806     return(TX_SUCCESS);
807 }
808 
809 
810 /**************************************************************************/
811 /*                                                                        */
812 /*  FUNCTION                                               RELEASE        */
813 /*                                                                        */
814 /*    _tx_execution_isr_time_reset                        PORTABLE C      */
815 /*                                                           6.1.7        */
816 /*  AUTHOR                                                                */
817 /*                                                                        */
818 /*    William E. Lamie, Microsoft Corporation                             */
819 /*                                                                        */
820 /*  DESCRIPTION                                                           */
821 /*                                                                        */
822 /*    This function resets the execution time of the ISR calculation.     */
823 /*                                                                        */
824 /*  INPUT                                                                 */
825 /*                                                                        */
826 /*    None                                                                */
827 /*                                                                        */
828 /*  OUTPUT                                                                */
829 /*                                                                        */
830 /*    status                            Completion status                 */
831 /*                                                                        */
832 /*  CALLS                                                                 */
833 /*                                                                        */
834 /*    None                                                                */
835 /*                                                                        */
836 /*  CALLED BY                                                             */
837 /*                                                                        */
838 /*    Application code                                                    */
839 /*                                                                        */
840 /*  RELEASE HISTORY                                                       */
841 /*                                                                        */
842 /*    DATE              NAME                      DESCRIPTION             */
843 /*                                                                        */
844 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
845 /*                                                                        */
846 /**************************************************************************/
_tx_execution_isr_time_reset(void)847 UINT  _tx_execution_isr_time_reset(void)
848 {
849 
850     /* Reset the total time to 0.  */
851     _tx_execution_isr_time_total =  0;
852 
853     /* Return success.  */
854     return(TX_SUCCESS);
855 }
856 
857 
858 /**************************************************************************/
859 /*                                                                        */
860 /*  FUNCTION                                               RELEASE        */
861 /*                                                                        */
862 /*    _tx_execution_idle_time_reset                       PORTABLE C      */
863 /*                                                           6.1.7        */
864 /*  AUTHOR                                                                */
865 /*                                                                        */
866 /*    William E. Lamie, Microsoft Corporation                             */
867 /*                                                                        */
868 /*  DESCRIPTION                                                           */
869 /*                                                                        */
870 /*    This function resets the idle execution time calculation.           */
871 /*                                                                        */
872 /*  INPUT                                                                 */
873 /*                                                                        */
874 /*    None                                                                */
875 /*                                                                        */
876 /*  OUTPUT                                                                */
877 /*                                                                        */
878 /*    status                            Completion status                 */
879 /*                                                                        */
880 /*  CALLS                                                                 */
881 /*                                                                        */
882 /*    None                                                                */
883 /*                                                                        */
884 /*  CALLED BY                                                             */
885 /*                                                                        */
886 /*    Application code                                                    */
887 /*                                                                        */
888 /*  RELEASE HISTORY                                                       */
889 /*                                                                        */
890 /*    DATE              NAME                      DESCRIPTION             */
891 /*                                                                        */
892 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
893 /*                                                                        */
894 /**************************************************************************/
_tx_execution_idle_time_reset(void)895 UINT  _tx_execution_idle_time_reset(void)
896 {
897 
898     /* Reset the total time to 0.  */
899     _tx_execution_idle_time_total =  0;
900 
901     /* Return success.  */
902     return(TX_SUCCESS);
903 }
904 
905 
906 /**************************************************************************/
907 /*                                                                        */
908 /*  FUNCTION                                               RELEASE        */
909 /*                                                                        */
910 /*    _tx_execution_thread_time_get                       PORTABLE C      */
911 /*                                                           6.1.7        */
912 /*  AUTHOR                                                                */
913 /*                                                                        */
914 /*    William E. Lamie, Microsoft Corporation                             */
915 /*                                                                        */
916 /*  DESCRIPTION                                                           */
917 /*                                                                        */
918 /*    This function gets the execution time of the specified thread.      */
919 /*                                                                        */
920 /*  INPUT                                                                 */
921 /*                                                                        */
922 /*    thread_ptr                        Pointer to the thread             */
923 /*    total_time                        Destination for total time        */
924 /*                                                                        */
925 /*  OUTPUT                                                                */
926 /*                                                                        */
927 /*    status                            Completion status                 */
928 /*                                                                        */
929 /*  CALLS                                                                 */
930 /*                                                                        */
931 /*    None                                                                */
932 /*                                                                        */
933 /*  CALLED BY                                                             */
934 /*                                                                        */
935 /*    Application code                                                    */
936 /*                                                                        */
937 /*  RELEASE HISTORY                                                       */
938 /*                                                                        */
939 /*    DATE              NAME                      DESCRIPTION             */
940 /*                                                                        */
941 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
942 /*                                                                        */
943 /**************************************************************************/
_tx_execution_thread_time_get(TX_THREAD * thread_ptr,EXECUTION_TIME * total_time)944 UINT  _tx_execution_thread_time_get(TX_THREAD *thread_ptr, EXECUTION_TIME *total_time)
945 {
946 
947     /* Return the total time.  */
948     *total_time =  thread_ptr -> tx_thread_execution_time_total;
949 
950     /* Return success.  */
951     return(TX_SUCCESS);
952 }
953 
954 
955 /**************************************************************************/
956 /*                                                                        */
957 /*  FUNCTION                                               RELEASE        */
958 /*                                                                        */
959 /*    _tx_execution_thread_total_time_get                 PORTABLE C      */
960 /*                                                           6.1.7        */
961 /*  AUTHOR                                                                */
962 /*                                                                        */
963 /*    William E. Lamie, Microsoft Corporation                             */
964 /*                                                                        */
965 /*  DESCRIPTION                                                           */
966 /*                                                                        */
967 /*    This function gets the execution time of the specified thread.      */
968 /*                                                                        */
969 /*  INPUT                                                                 */
970 /*                                                                        */
971 /*    total_time                        Destination for total time        */
972 /*                                                                        */
973 /*  OUTPUT                                                                */
974 /*                                                                        */
975 /*    status                            Completion status                 */
976 /*                                                                        */
977 /*  CALLS                                                                 */
978 /*                                                                        */
979 /*    None                                                                */
980 /*                                                                        */
981 /*  CALLED BY                                                             */
982 /*                                                                        */
983 /*    Application code                                                    */
984 /*                                                                        */
985 /*  RELEASE HISTORY                                                       */
986 /*                                                                        */
987 /*    DATE              NAME                      DESCRIPTION             */
988 /*                                                                        */
989 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
990 /*                                                                        */
991 /**************************************************************************/
_tx_execution_thread_total_time_get(EXECUTION_TIME * total_time)992 UINT  _tx_execution_thread_total_time_get(EXECUTION_TIME *total_time)
993 {
994 
995     /* Return the total time.  */
996     *total_time =  _tx_execution_thread_time_total;
997 
998     /* Return success.  */
999     return(TX_SUCCESS);
1000 }
1001 
1002 
1003 /**************************************************************************/
1004 /*                                                                        */
1005 /*  FUNCTION                                               RELEASE        */
1006 /*                                                                        */
1007 /*    _tx_execution_isr_time_get                          PORTABLE C      */
1008 /*                                                           6.1.7        */
1009 /*  AUTHOR                                                                */
1010 /*                                                                        */
1011 /*    William E. Lamie, Microsoft Corporation                             */
1012 /*                                                                        */
1013 /*  DESCRIPTION                                                           */
1014 /*                                                                        */
1015 /*    This function gets the execution time of ISRs.                      */
1016 /*                                                                        */
1017 /*  INPUT                                                                 */
1018 /*                                                                        */
1019 /*    total_time                        Destination for total time        */
1020 /*                                                                        */
1021 /*  OUTPUT                                                                */
1022 /*                                                                        */
1023 /*    status                            Completion status                 */
1024 /*                                                                        */
1025 /*  CALLS                                                                 */
1026 /*                                                                        */
1027 /*    None                                                                */
1028 /*                                                                        */
1029 /*  CALLED BY                                                             */
1030 /*                                                                        */
1031 /*    Application code                                                    */
1032 /*                                                                        */
1033 /*  RELEASE HISTORY                                                       */
1034 /*                                                                        */
1035 /*    DATE              NAME                      DESCRIPTION             */
1036 /*                                                                        */
1037 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
1038 /*                                                                        */
1039 /**************************************************************************/
_tx_execution_isr_time_get(EXECUTION_TIME * total_time)1040 UINT  _tx_execution_isr_time_get(EXECUTION_TIME *total_time)
1041 {
1042 
1043     /* Return the total time.  */
1044     *total_time =  _tx_execution_isr_time_total;
1045 
1046     /* Return success.  */
1047     return(TX_SUCCESS);
1048 }
1049 
1050 
1051 /**************************************************************************/
1052 /*                                                                        */
1053 /*  FUNCTION                                               RELEASE        */
1054 /*                                                                        */
1055 /*    _tx_execution_idle_time_get                         PORTABLE C      */
1056 /*                                                           6.1.7        */
1057 /*  AUTHOR                                                                */
1058 /*                                                                        */
1059 /*    William E. Lamie, Microsoft Corporation                             */
1060 /*                                                                        */
1061 /*  DESCRIPTION                                                           */
1062 /*                                                                        */
1063 /*    This function gets the execution time of ISRs.                      */
1064 /*                                                                        */
1065 /*  INPUT                                                                 */
1066 /*                                                                        */
1067 /*    total_time                        Destination for total time        */
1068 /*                                                                        */
1069 /*  OUTPUT                                                                */
1070 /*                                                                        */
1071 /*    status                            Completion status                 */
1072 /*                                                                        */
1073 /*  CALLS                                                                 */
1074 /*                                                                        */
1075 /*    None                                                                */
1076 /*                                                                        */
1077 /*  CALLED BY                                                             */
1078 /*                                                                        */
1079 /*    Application code                                                    */
1080 /*                                                                        */
1081 /*  RELEASE HISTORY                                                       */
1082 /*                                                                        */
1083 /*    DATE              NAME                      DESCRIPTION             */
1084 /*                                                                        */
1085 /*  06-02-2021      William E. Lamie        Initial Version 6.1.7         */
1086 /*                                                                        */
1087 /**************************************************************************/
_tx_execution_idle_time_get(EXECUTION_TIME * total_time)1088 UINT  _tx_execution_idle_time_get(EXECUTION_TIME *total_time)
1089 {
1090 
1091     /* Return the total time.  */
1092     *total_time =  _tx_execution_idle_time_total;
1093 
1094     /* Return success.  */
1095     return(TX_SUCCESS);
1096 }
1097 
1098 
1099 #endif /* #if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) */
1100