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 /**   ThreadX/GHS Event Log (EL)                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 #define TX_EL_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "tx_api.h"
29 #include "tx_el.h"
30 #include "string.h"
31 
32 
33 /* Define global variables used to manage the event pool.  */
34 
35 UCHAR   *_tx_el_tni_start;
36 UCHAR   **_tx_el_current_event;
37 UCHAR   *_tx_el_event_area_start;
38 UCHAR   *_tx_el_event_area_end;
39 UINT    _tx_el_maximum_events;
40 ULONG   _tx_el_total_events;
41 UINT    _tx_el_event_filter;
42 ULONG   _tx_el_time_base_upper;
43 ULONG   _tx_el_time_base_lower;
44 
45 extern char __ghsbegin_eventlog[];
46 extern char __ghsend_eventlog[];
47 
48 extern  TX_THREAD   *_tx_thread_current_ptr;
49 UINT                _tx_thread_interrupt_control(UINT new_posture);
50 
51 
52 /**************************************************************************/
53 /*                                                                        */
54 /*  FUNCTION                                               RELEASE        */
55 /*                                                                        */
56 /*    _tx_el_initialize                                   PORTABLE C      */
57 /*                                                           6.1          */
58 /*  AUTHOR                                                                */
59 /*                                                                        */
60 /*    William E. Lamie, Microsoft Corporation                             */
61 /*                                                                        */
62 /*  DESCRIPTION                                                           */
63 /*                                                                        */
64 /*    This function creates the Event Log (in the format dictated by the  */
65 /*    GHS Event Analyzer) and sets up various information for subsequent  */
66 /*    operation.  The start and end of the Event Log is determined by the */
67 /*    .eventlog section in the linker control file.                       */
68 /*                                                                        */
69 /*  INPUT                                                                 */
70 /*                                                                        */
71 /*    None                                                                */
72 /*                                                                        */
73 /*  OUTPUT                                                                */
74 /*                                                                        */
75 /*    None                                                                */
76 /*                                                                        */
77 /*  CALLS                                                                 */
78 /*                                                                        */
79 /*    None                                                                */
80 /*                                                                        */
81 /*  CALLED BY                                                             */
82 /*                                                                        */
83 /*    Application Code                                                    */
84 /*                                                                        */
85 /*  RELEASE HISTORY                                                       */
86 /*                                                                        */
87 /*    DATE              NAME                      DESCRIPTION             */
88 /*                                                                        */
89 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
90 /*                                                                        */
91 /**************************************************************************/
_tx_el_initialize(VOID)92 VOID  _tx_el_initialize(VOID)
93 {
94 
95 UCHAR   *work_ptr;
96 UCHAR   *read_ptr;
97 ULONG   event_log_size;
98 UCHAR   *end_ptr;
99 UINT    i;
100 
101 
102     /* Clear total event counter.  */
103     _tx_el_total_events =  0;
104 
105     /* Clear event filter.  */
106     _tx_el_event_filter =  0;
107 
108     /* First, pickup the starting and ending address of the Event Log memory.  */
109     work_ptr =  (unsigned char *) __ghsbegin_eventlog;
110     end_ptr =   (unsigned char *) __ghsend_eventlog;
111 
112     /* Calculate the event log size.  */
113     event_log_size =  end_ptr - work_ptr;
114 
115     /* Subtract off the number of bytes in the header and the TNI area.  */
116     event_log_size =  event_log_size - (TX_EL_HEADER_SIZE +
117                                        (TX_EL_TNI_ENTRY_SIZE * TX_EL_TNIS));
118 
119     /* Make sure the event log is evenly divisible by the event size.  */
120     event_log_size =  (event_log_size/TX_EL_EVENT_SIZE) * TX_EL_EVENT_SIZE;
121 
122     /* Build the Event Log header.  */
123 
124     /* Setup the Event Log Version ID.  */
125     *((unsigned short *) work_ptr) =  (unsigned short) TX_EL_VERSION_ID;
126     work_ptr =  work_ptr + sizeof(unsigned short);
127 
128     /* Setup the TNIS (number of thread names) field.  */
129     *((unsigned short *) work_ptr) =  (unsigned short) TX_EL_TNIS;
130     work_ptr =  work_ptr + sizeof(unsigned short);
131 
132     /* Setup the EVPS (event pool size) field.  */
133     *((ULONG *) work_ptr) =  event_log_size;
134     work_ptr =  work_ptr + sizeof(ULONG);
135 
136     /* Remember the maximum number of events.  */
137     _tx_el_maximum_events =  event_log_size/TX_EL_EVENT_SIZE;
138 
139     /* Setup max_events field.  */
140     *((ULONG *) work_ptr) =  _tx_el_maximum_events;
141     work_ptr =  work_ptr + sizeof(ULONG);
142 
143     /* Setup the evploc (location of event pool).  */
144     *((ULONG *) work_ptr) =  (ULONG) (((ULONG) __ghsbegin_eventlog) + TX_EL_HEADER_SIZE +
145                                         (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
146     work_ptr =  work_ptr + sizeof(ULONG);
147 
148     /* Save the current event pointer.  */
149     _tx_el_current_event =  (UCHAR **) work_ptr;
150 
151     /* Setup event_ptr (pointer to oldest event) field to the start
152        of the event pool.  */
153     *_tx_el_current_event =  (UCHAR *) (((ULONG) __ghsbegin_eventlog) + TX_EL_HEADER_SIZE +
154                                         (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
155     work_ptr =  work_ptr + sizeof(ULONG);
156 
157     /* Setup tbfreq (the number of ticks in a second) field.  */
158     *((ULONG *) work_ptr) =  TX_EL_TICKS_PER_SECOND;
159     work_ptr =  work_ptr + sizeof(ULONG);
160 
161     /* At this point we are pointing at the Thread Name Information (TNI) array.  */
162 
163     /* Remember the start of this for future updates.  */
164     _tx_el_tni_start =  work_ptr;
165 
166     /* Clear the entire TNI array, this is the initial setting.  */
167     end_ptr =  work_ptr + (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE);
168     memset((void *)work_ptr, 0, (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
169     work_ptr = end_ptr;
170 
171     /* At this point, we are pointing at the actual Event Entry area.  */
172 
173     /* Remember the start of the actual event log area.  */
174     _tx_el_event_area_start =  work_ptr;
175 
176     /* Clear the entire Event area.  */
177     end_ptr =  work_ptr + event_log_size;
178     memset((void *)work_ptr, 0, event_log_size);
179     work_ptr = end_ptr;
180 
181     /* Save the end pointer for later use.  */
182     _tx_el_event_area_end =  work_ptr;
183 
184     /* Setup an entry to resolve all activities from initialization and from
185        an idle system.  */
186     work_ptr =  _tx_el_tni_start;
187     read_ptr =  (UCHAR *) "Initialization/System Idle";
188     i =         0;
189     while ((i < TX_EL_TNI_NAME_SIZE) && (*read_ptr))
190     {
191 
192         /* Copy a character of thread's name into TNI area of log.  */
193         *work_ptr++ =  *read_ptr++;
194 
195         /* Increment the character count.  */
196         i++;
197     }
198 
199     /* Determine if a NULL needs to be inserted.  */
200     if (i < TX_EL_TNI_NAME_SIZE)
201     {
202 
203         /* Yes, insert a NULL into the event log string.  */
204         *work_ptr =  (unsigned char) 0;
205     }
206 
207     /* Setup the thread ID to NULL.  */
208     *((ULONG *) (_tx_el_tni_start + TX_EL_TNI_THREAD_ID_OFFSET)) =  (ULONG) TX_NULL;
209 
210     /* Set the valid field to indicate the entry is complete.  */
211     *((UCHAR *) (_tx_el_tni_start + TX_EL_TNI_VALID_OFFSET)) =  (ULONG) TX_EL_VALID_ENTRY;
212 
213     /* Clear the time base global variables.  */
214     _tx_el_time_base_upper =  0;
215     _tx_el_time_base_lower =  0;
216 }
217 
218 
219 /**************************************************************************/
220 /*                                                                        */
221 /*  FUNCTION                                               RELEASE        */
222 /*                                                                        */
223 /*    _tx_el_thread_register                              PORTABLE C      */
224 /*                                                           6.1          */
225 /*  AUTHOR                                                                */
226 /*                                                                        */
227 /*    William E. Lamie, Microsoft Corporation                             */
228 /*                                                                        */
229 /*  DESCRIPTION                                                           */
230 /*                                                                        */
231 /*    This function registers a thread in the event log for future        */
232 /*    display purposes.                                                   */
233 /*                                                                        */
234 /*  INPUT                                                                 */
235 /*                                                                        */
236 /*    thread_ptr                        Pointer to thread control block   */
237 /*                                                                        */
238 /*  OUTPUT                                                                */
239 /*                                                                        */
240 /*    TX_SUCCESS                        Thread was placed in TNI area     */
241 /*    TX_ERROR                          No more room in the TNI area      */
242 /*                                                                        */
243 /*  CALLS                                                                 */
244 /*                                                                        */
245 /*    None                                                                */
246 /*                                                                        */
247 /*  CALLED BY                                                             */
248 /*                                                                        */
249 /*    _tx_thread_create                 ThreadX thread create function    */
250 /*                                                                        */
251 /*  RELEASE HISTORY                                                       */
252 /*                                                                        */
253 /*    DATE              NAME                      DESCRIPTION             */
254 /*                                                                        */
255 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
256 /*                                                                        */
257 /**************************************************************************/
_tx_el_thread_register(TX_THREAD * thread_ptr)258 UINT  _tx_el_thread_register(TX_THREAD *thread_ptr)
259 {
260 
261 UCHAR   *entry_ptr;
262 UCHAR   *work_ptr;
263 UCHAR   *read_ptr;
264 UINT    i;
265 
266 
267     /* First of all, search for a free slot in the TNI area.  */
268     entry_ptr =  _tx_el_tni_start;
269     i =         0;
270     while (i < TX_EL_TNIS)
271     {
272 
273         /* Determine if this entry is available.  */
274         if (*(entry_ptr + TX_EL_TNI_VALID_OFFSET) == TX_EL_INVALID_ENTRY)
275             break;
276 
277         /* Otherwise, increment the associated pointers and indices.  */
278         i++;
279         entry_ptr =  entry_ptr + TX_EL_TNI_ENTRY_SIZE;
280     }
281 
282     /* Check to see if there were no more valid entries.  */
283     if (i >= TX_EL_TNIS)
284         return(TX_EL_NO_MORE_TNI_ROOM);
285 
286     /* Otherwise, we have room in the TNI and a valid record.  */
287 
288     /* Setup the thread's name.  */
289     work_ptr =  entry_ptr;
290     read_ptr =  (UCHAR *) thread_ptr -> tx_thread_name;
291     i =         0;
292     while ((i < TX_EL_TNI_NAME_SIZE) && (*read_ptr))
293     {
294 
295         /* Copy a character of thread's name into TNI area of log.  */
296         *work_ptr++ =  *read_ptr++;
297 
298         /* Increment the character count.  */
299         i++;
300     }
301 
302     /* Determine if a NULL needs to be inserted.  */
303     if (i < TX_EL_TNI_NAME_SIZE)
304     {
305 
306         /* Yes, insert a NULL into the event log string.  */
307         *work_ptr =  (unsigned char) 0;
308     }
309 
310     /* Setup the thread ID.  */
311     *((ULONG *) (entry_ptr + TX_EL_TNI_THREAD_ID_OFFSET)) =  (ULONG) thread_ptr;
312 
313     /* Setup the thread priority.  */
314     *((ULONG *) (entry_ptr + TX_EL_TNI_THREAD_PRIORITY_OFF)) =  (ULONG) thread_ptr -> tx_thread_priority;
315 
316     /* Set the valid field to indicate the entry is complete.  */
317     *((UCHAR *) (entry_ptr + TX_EL_TNI_VALID_OFFSET)) =  (ULONG) TX_EL_VALID_ENTRY;
318 
319     /* Thread name has been registered.  */
320     return(TX_SUCCESS);
321 }
322 
323 
324 /**************************************************************************/
325 /*                                                                        */
326 /*  FUNCTION                                               RELEASE        */
327 /*                                                                        */
328 /*    _tx_el_thread_unregister                            PORTABLE C      */
329 /*                                                           6.1          */
330 /*  AUTHOR                                                                */
331 /*                                                                        */
332 /*    William E. Lamie, Microsoft Corporation                             */
333 /*                                                                        */
334 /*  DESCRIPTION                                                           */
335 /*                                                                        */
336 /*    This function unregisters a thread in the event log for future      */
337 /*    display purposes.                                                   */
338 /*                                                                        */
339 /*  INPUT                                                                 */
340 /*                                                                        */
341 /*    thread_ptr                        Pointer to thread control block   */
342 /*                                                                        */
343 /*  OUTPUT                                                                */
344 /*                                                                        */
345 /*    TX_SUCCESS                        Thread was placed in TNI area     */
346 /*    TX_ERROR                          No more room in the TNI area      */
347 /*                                                                        */
348 /*  CALLS                                                                 */
349 /*                                                                        */
350 /*    None                                                                */
351 /*                                                                        */
352 /*  CALLED BY                                                             */
353 /*                                                                        */
354 /*    _tx_thread_create                 ThreadX thread create function    */
355 /*                                                                        */
356 /*  RELEASE HISTORY                                                       */
357 /*                                                                        */
358 /*    DATE              NAME                      DESCRIPTION             */
359 /*                                                                        */
360 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
361 /*                                                                        */
362 /**************************************************************************/
_tx_el_thread_unregister(TX_THREAD * thread_ptr)363 UINT  _tx_el_thread_unregister(TX_THREAD *thread_ptr)
364 {
365 
366 UCHAR   *entry_ptr;
367 UCHAR   *work_ptr;
368 UCHAR   *read_ptr;
369 UINT    found;
370 UINT    i, j;
371 
372 
373     /* First of all, search for a match in the TNI area.  */
374     entry_ptr =  _tx_el_tni_start;
375     i =         0;
376     while (i < TX_EL_TNIS)
377     {
378 
379         /* Determine if this entry is a match.  */
380         work_ptr =  entry_ptr;
381         read_ptr =  (UCHAR *) thread_ptr -> tx_thread_name;
382         found =     TX_TRUE;
383         j =         0;
384         do
385         {
386 
387             /* Determine if this character is the same.  */
388             if (*work_ptr != *read_ptr)
389             {
390 
391                 /* Set found to false and fall out of the loop.  */
392                 found =  TX_FALSE;
393                 break;
394             }
395             else if (*work_ptr == 0)
396             {
397 
398                 /* Null terminated, just break the loop.  */
399                 break;
400             }
401             else
402             {
403 
404                 /* Copy a character of thread's name into TNI area of log.  */
405                 *work_ptr++ =  *read_ptr++;
406             }
407 
408             /* Increment the character count.  */
409             j++;
410 
411         } while(j < TX_EL_TNIS);
412 
413 
414         /* Was a match found?  */
415         if (found)
416         {
417 
418             /* Yes, mark the entry as available now.  */
419             *(entry_ptr + TX_EL_TNI_VALID_OFFSET) = TX_EL_INVALID_ENTRY;
420 
421             /* Get out of the loop!  */
422             break;
423         }
424 
425         /* Otherwise, increment the associated pointers and indices.  */
426         i++;
427         entry_ptr =  entry_ptr + TX_EL_TNI_ENTRY_SIZE;
428     }
429 
430     /* Determine status to return.  */
431     if (found)
432         return(TX_SUCCESS);
433     else
434         return(TX_EL_NAME_NOT_FOUND);
435 }
436 
437 
438 /**************************************************************************/
439 /*                                                                        */
440 /*  FUNCTION                                               RELEASE        */
441 /*                                                                        */
442 /*    _tx_el_user_event_insert                            PORTABLE C      */
443 /*                                                           6.1          */
444 /*  AUTHOR                                                                */
445 /*                                                                        */
446 /*    William E. Lamie, Microsoft Corporation                             */
447 /*                                                                        */
448 /*  DESCRIPTION                                                           */
449 /*                                                                        */
450 /*    This function inserts a user event into the event log.              */
451 /*    If the event log is full, the oldest event is overwritten.          */
452 /*                                                                        */
453 /*  INPUT                                                                 */
454 /*                                                                        */
455 /*    sub_type                              Event subtype for kernel call */
456 /*    info_1                                First information field       */
457 /*    info_2                                Second information field      */
458 /*    info_3                                Third information field       */
459 /*    info_4                                Fourth information field      */
460 /*                                                                        */
461 /*  OUTPUT                                                                */
462 /*                                                                        */
463 /*    None                                                                */
464 /*                                                                        */
465 /*  CALLS                                                                 */
466 /*                                                                        */
467 /*    None                                                                */
468 /*                                                                        */
469 /*  CALLED BY                                                             */
470 /*                                                                        */
471 /*    ThreadX services                                                    */
472 /*                                                                        */
473 /*  RELEASE HISTORY                                                       */
474 /*                                                                        */
475 /*    DATE              NAME                      DESCRIPTION             */
476 /*                                                                        */
477 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
478 /*                                                                        */
479 /**************************************************************************/
_tx_el_user_event_insert(UINT sub_type,ULONG info_1,ULONG info_2,ULONG info_3,ULONG info_4)480 VOID  _tx_el_user_event_insert(UINT sub_type, ULONG info_1, ULONG info_2,
481                                                     ULONG info_3, ULONG info_4)
482 {
483 
484 TX_INTERRUPT_SAVE_AREA
485 
486 UINT    upper_tb;
487 UCHAR   *entry_ptr;
488 
489     /* Disable interrupts.  */
490     TX_DISABLE
491 
492     /* Increment total event counter.  */
493     _tx_el_total_events++;
494 
495     /* Setup working entry pointer first.  */
496     entry_ptr =  *_tx_el_current_event;
497 
498     /* Store the event type.  */
499     *((unsigned short *) entry_ptr) =  (unsigned short) TX_EL_USER_EVENT;
500 
501     /* Store the event subtype.  */
502     *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
503                                 (unsigned short) sub_type;
504 
505     /* Get time stamp.  */
506     do
507     {
508 
509         /* Pickup the upper tb.  */
510         upper_tb =  (ULONG) read_tbu();
511 
512         /* Store the upper time stamp.  */
513         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
514                                 (ULONG) upper_tb;
515 
516         /* Store the lower time stamp.  */
517         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
518                                 (ULONG) read_tbl();
519     } while (upper_tb != (ULONG) read_tbu());
520 
521     /* Store the current thread.  */
522     *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
523                                 (ULONG) _tx_thread_current_ptr;
524 
525     /* Store the first info field.  */
526     *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
527                                 (ULONG) info_1;
528 
529     /* Store the second info field.  */
530     *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =
531                                 (ULONG) info_2;
532 
533     /* Store the third info field.  */
534     *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =
535                                 (ULONG) info_3;
536 
537     /* Store the fourth info field.  */
538     *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =
539                                 (ULONG) info_4;
540 
541     /* Now move the current event log pointer.  */
542     entry_ptr =  entry_ptr + TX_EL_EVENT_SIZE;
543 
544     /* Check for a wraparound condition.  */
545     if (entry_ptr >= _tx_el_event_area_end)
546     {
547 
548         /* Yes, we have wrapped around to the end of the event area.
549            Start back at the top!  */
550         entry_ptr =  _tx_el_event_area_start;
551     }
552 
553     /* Write the entry pointer back into the header.  */
554     *_tx_el_current_event =  entry_ptr;
555 
556     /* Restore interrupts.  */
557     TX_RESTORE
558 }
559 
560 
561 /**************************************************************************/
562 /*                                                                        */
563 /*  FUNCTION                                               RELEASE        */
564 /*                                                                        */
565 /*    _tx_el_thread_running                               PORTABLE C      */
566 /*                                                           6.1          */
567 /*  AUTHOR                                                                */
568 /*                                                                        */
569 /*    William E. Lamie, Microsoft Corporation                             */
570 /*                                                                        */
571 /*  DESCRIPTION                                                           */
572 /*                                                                        */
573 /*    This function inserts a thread change event into the event          */
574 /*    log, which indicates that a context switch is taking place.         */
575 /*    If the event log is full, the oldest event is overwritten.          */
576 /*                                                                        */
577 /*  INPUT                                                                 */
578 /*                                                                        */
579 /*    thread_ptr                            Pointer to thread being       */
580 /*                                            scheduled                   */
581 /*                                                                        */
582 /*  OUTPUT                                                                */
583 /*                                                                        */
584 /*    None                                                                */
585 /*                                                                        */
586 /*  CALLS                                                                 */
587 /*                                                                        */
588 /*    None                                                                */
589 /*                                                                        */
590 /*  CALLED BY                                                             */
591 /*                                                                        */
592 /*    _tx_thread_schedule                   ThreadX scheduler             */
593 /*                                                                        */
594 /*  RELEASE HISTORY                                                       */
595 /*                                                                        */
596 /*    DATE              NAME                      DESCRIPTION             */
597 /*                                                                        */
598 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
599 /*                                                                        */
600 /**************************************************************************/
_tx_el_thread_running(TX_THREAD * thread_ptr)601 VOID  _tx_el_thread_running(TX_THREAD *thread_ptr)
602 {
603 
604 UINT    upper_tb;
605 UCHAR   *entry_ptr;
606 
607     TX_EL_NO_STATUS_EVENTS
608 
609     /* Increment total event counter.  */
610     _tx_el_total_events++;
611 
612     /* Setup working entry pointer first.  */
613     entry_ptr =  *_tx_el_current_event;
614 
615     /* Store the event type.  */
616     *((unsigned short *) entry_ptr) =  (unsigned short) TX_EL_THREAD_CHANGE;
617 
618     /* Store the event subtype.  */
619     *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
620                                 (unsigned short) 0;
621 
622     /* Get time stamp.  */
623     do
624     {
625 
626         /* Pickup the upper tb.  */
627         upper_tb =  (ULONG) read_tbu();
628 
629         /* Store the upper time stamp.  */
630         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
631                                 (ULONG) upper_tb;
632 
633         /* Store the lower time stamp.  */
634         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
635                                 (ULONG) read_tbl();
636     } while (upper_tb != (ULONG) read_tbu());
637 
638     /* Store the current thread.  */
639     *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
640                                 (ULONG) thread_ptr;
641 
642     /* Now move the current event log pointer.  */
643     entry_ptr =  entry_ptr + TX_EL_EVENT_SIZE;
644 
645     /* Check for a wraparound condition.  */
646     if (entry_ptr >= _tx_el_event_area_end)
647     {
648 
649         /* Yes, we have wrapped around to the end of the event area.
650            Start back at the top!  */
651         entry_ptr =  _tx_el_event_area_start;
652     }
653 
654     /* Write the entry pointer back into the header.  */
655     *_tx_el_current_event =  entry_ptr;
656 
657     TX_EL_END_FILTER
658 }
659 
660 
661 /**************************************************************************/
662 /*                                                                        */
663 /*  FUNCTION                                               RELEASE        */
664 /*                                                                        */
665 /*    _tx_el_thread_preempted                             PORTABLE C      */
666 /*                                                           6.1          */
667 /*  AUTHOR                                                                */
668 /*                                                                        */
669 /*    William E. Lamie, Microsoft Corporation                             */
670 /*                                                                        */
671 /*  DESCRIPTION                                                           */
672 /*                                                                        */
673 /*    This function inserts a thread preempted event into the event       */
674 /*    log, which indicates that an interrupt occurred that made a higher  */
675 /*    priority thread ready for execution.  In this case, the previously  */
676 /*    executing thread has an event entered to indicate it is no longer   */
677 /*    running.                                                            */
678 /*                                                                        */
679 /*  INPUT                                                                 */
680 /*                                                                        */
681 /*    thread_ptr                            Pointer to thread being       */
682 /*                                            scheduled                   */
683 /*                                                                        */
684 /*  OUTPUT                                                                */
685 /*                                                                        */
686 /*    None                                                                */
687 /*                                                                        */
688 /*  CALLS                                                                 */
689 /*                                                                        */
690 /*    None                                                                */
691 /*                                                                        */
692 /*  CALLED BY                                                             */
693 /*                                                                        */
694 /*    _tx_thread_context_restore            ThreadX context restore       */
695 /*                                                                        */
696 /*  RELEASE HISTORY                                                       */
697 /*                                                                        */
698 /*    DATE              NAME                      DESCRIPTION             */
699 /*                                                                        */
700 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
701 /*                                                                        */
702 /**************************************************************************/
_tx_el_thread_preempted(TX_THREAD * thread_ptr)703 VOID  _tx_el_thread_preempted(TX_THREAD *thread_ptr)
704 {
705 
706 UINT    upper_tb;
707 UCHAR   *entry_ptr;
708 
709 
710     TX_EL_NO_STATUS_EVENTS
711 
712     /* Increment total event counter.  */
713     _tx_el_total_events++;
714 
715     /* Setup working entry pointer first.  */
716     entry_ptr =  *_tx_el_current_event;
717 
718     /* Store the event type.  */
719     *((unsigned short *) entry_ptr) =  (unsigned short) TX_EL_THREAD_STATUS_CHANGE;
720 
721     /* Store the event subtype.  */
722     *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
723                                 (unsigned short) TX_READY;
724 
725     /* Get time stamp.  */
726     do
727     {
728 
729         /* Pickup the upper tb.  */
730         upper_tb =  (ULONG) read_tbu();
731 
732         /* Store the upper time stamp.  */
733         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
734                                 (ULONG) upper_tb;
735 
736         /* Store the lower time stamp.  */
737         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
738                                 (ULONG) read_tbl();
739     } while (upper_tb != (ULONG) read_tbu());
740 
741     /* Store the current thread.  */
742     *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
743                                 (ULONG) _tx_thread_current_ptr;
744 
745     /* Now move the current event log pointer.  */
746     entry_ptr =  entry_ptr + TX_EL_EVENT_SIZE;
747 
748     /* Check for a wraparound condition.  */
749     if (entry_ptr >= _tx_el_event_area_end)
750     {
751 
752         /* Yes, we have wrapped around to the end of the event area.
753            Start back at the top!  */
754         entry_ptr =  _tx_el_event_area_start;
755     }
756 
757     /* Write the entry pointer back into the header.  */
758     *_tx_el_current_event =  entry_ptr;
759 
760     TX_EL_END_FILTER
761 }
762 
763 
764 /**************************************************************************/
765 /*                                                                        */
766 /*  FUNCTION                                               RELEASE        */
767 /*                                                                        */
768 /*    _tx_el_interrupt                                    PORTABLE C      */
769 /*                                                           6.1          */
770 /*  AUTHOR                                                                */
771 /*                                                                        */
772 /*    William E. Lamie, Microsoft Corporation                             */
773 /*                                                                        */
774 /*  DESCRIPTION                                                           */
775 /*                                                                        */
776 /*    This function inserts an interrupt event into the log, which        */
777 /*    indicates the start of interrupt processing for the specific        */
778 /*                                                                        */
779 /*  INPUT                                                                 */
780 /*                                                                        */
781 /*    interrupt_number                      Interrupt number supplied by  */
782 /*                                            ISR                         */
783 /*                                                                        */
784 /*  OUTPUT                                                                */
785 /*                                                                        */
786 /*    None                                                                */
787 /*                                                                        */
788 /*  CALLS                                                                 */
789 /*                                                                        */
790 /*    None                                                                */
791 /*                                                                        */
792 /*  CALLED BY                                                             */
793 /*                                                                        */
794 /*    ISR processing                                                      */
795 /*                                                                        */
796 /*  RELEASE HISTORY                                                       */
797 /*                                                                        */
798 /*    DATE              NAME                      DESCRIPTION             */
799 /*                                                                        */
800 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
801 /*                                                                        */
802 /**************************************************************************/
_tx_el_interrupt(UINT interrupt_number)803 VOID  _tx_el_interrupt(UINT interrupt_number)
804 {
805 
806 UINT    upper_tb;
807 UCHAR   *entry_ptr;
808 
809 
810     TX_EL_NO_INTERRUPT_EVENTS
811 
812     /* Increment total event counter.  */
813     _tx_el_total_events++;
814 
815     /* Setup working entry pointer first.  */
816     entry_ptr =  *_tx_el_current_event;
817 
818     /* Store the event type.  */
819     *((unsigned short *) entry_ptr) =  (unsigned short) TX_EL_INTERRUPT;
820 
821     /* Store the event subtype.  */
822     *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
823                                 (unsigned short) TX_EL_INTERRUPT_SUB_TYPE;
824 
825     /* Get time stamp.  */
826     do
827     {
828 
829         /* Pickup the upper tb.  */
830         upper_tb =  (ULONG) read_tbu();
831 
832         /* Store the upper time stamp.  */
833         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
834                                 (ULONG) upper_tb;
835 
836         /* Store the lower time stamp.  */
837         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
838                                 (ULONG) read_tbl();
839     } while (upper_tb != (ULONG) read_tbu());
840 
841     /* Store the current thread.  */
842     *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
843                                 (ULONG) _tx_thread_current_ptr;
844 
845     /* Store the first info word.  */
846     *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
847                                 (ULONG) interrupt_number;
848 
849     /* Now move the current event log pointer.  */
850     entry_ptr =  entry_ptr + TX_EL_EVENT_SIZE;
851 
852     /* Check for a wraparound condition.  */
853     if (entry_ptr >= _tx_el_event_area_end)
854     {
855 
856         /* Yes, we have wrapped around to the end of the event area.
857            Start back at the top!  */
858         entry_ptr =  _tx_el_event_area_start;
859     }
860 
861     /* Write the entry pointer back into the header.  */
862     *_tx_el_current_event =  entry_ptr;
863 
864     TX_EL_END_FILTER
865 }
866 
867 
868 /**************************************************************************/
869 /*                                                                        */
870 /*  FUNCTION                                               RELEASE        */
871 /*                                                                        */
872 /*    _tx_el_interrupt_end                                PORTABLE C      */
873 /*                                                           6.1          */
874 /*  AUTHOR                                                                */
875 /*                                                                        */
876 /*    William E. Lamie, Microsoft Corporation                             */
877 /*                                                                        */
878 /*  DESCRIPTION                                                           */
879 /*                                                                        */
880 /*    This function inserts an interrupt end event into the log, which    */
881 /*    indicates the end of interrupt processing for the specific          */
882 /*                                                                        */
883 /*  INPUT                                                                 */
884 /*                                                                        */
885 /*    interrupt_number                      Interrupt number supplied by  */
886 /*                                            ISR                         */
887 /*                                                                        */
888 /*  OUTPUT                                                                */
889 /*                                                                        */
890 /*    None                                                                */
891 /*                                                                        */
892 /*  CALLS                                                                 */
893 /*                                                                        */
894 /*    None                                                                */
895 /*                                                                        */
896 /*  CALLED BY                                                             */
897 /*                                                                        */
898 /*    ISR processing                                                      */
899 /*                                                                        */
900 /*  RELEASE HISTORY                                                       */
901 /*                                                                        */
902 /*    DATE              NAME                      DESCRIPTION             */
903 /*                                                                        */
904 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
905 /*                                                                        */
906 /**************************************************************************/
_tx_el_interrupt_end(UINT interrupt_number)907 VOID  _tx_el_interrupt_end(UINT interrupt_number)
908 {
909 
910 UINT    upper_tb;
911 UCHAR   *entry_ptr;
912 
913 
914     TX_EL_NO_INTERRUPT_EVENTS
915 
916     /* Increment total event counter.  */
917     _tx_el_total_events++;
918 
919     /* Setup working entry pointer first.  */
920     entry_ptr =  *_tx_el_current_event;
921 
922     /* Store the event type.  */
923     *((unsigned short *) entry_ptr) =  (unsigned short) TX_EL_INTERRUPT;
924 
925     /* Store the event subtype.  */
926     *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
927                                 (unsigned short) TX_EL_END_OF_INTERRUPT;
928 
929     /* Get time stamp.  */
930     do
931     {
932 
933         /* Pickup the upper tb.  */
934         upper_tb =  (ULONG) read_tbu();
935 
936         /* Store the upper time stamp.  */
937         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
938                                 (ULONG) upper_tb;
939 
940         /* Store the lower time stamp.  */
941         *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
942                                 (ULONG) read_tbl();
943     } while (upper_tb != (ULONG) read_tbu());
944 
945     /* Store the current thread.  */
946     *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
947                                 (ULONG) _tx_thread_current_ptr;
948 
949     /* Store the first info word.  */
950     *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
951                                 (ULONG) interrupt_number;
952 
953     /* Now move the current event log pointer.  */
954     entry_ptr =  entry_ptr + TX_EL_EVENT_SIZE;
955 
956     /* Check for a wraparound condition.  */
957     if (entry_ptr >= _tx_el_event_area_end)
958     {
959 
960         /* Yes, we have wrapped around to the end of the event area.
961            Start back at the top!  */
962         entry_ptr =  _tx_el_event_area_start;
963     }
964 
965     /* Write the entry pointer back into the header.  */
966     *_tx_el_current_event =  entry_ptr;
967 
968     TX_EL_END_FILTER
969 }
970 
971 
972 /**************************************************************************/
973 /*                                                                        */
974 /*  FUNCTION                                               RELEASE        */
975 /*                                                                        */
976 /*    _tx_el_interrupt_control                            PORTABLE C      */
977 /*                                                           6.1          */
978 /*  AUTHOR                                                                */
979 /*                                                                        */
980 /*    William E. Lamie, Microsoft Corporation                             */
981 /*                                                                        */
982 /*  DESCRIPTION                                                           */
983 /*                                                                        */
984 /*    This function remaps the tx_interrupt_control service call so that  */
985 /*    it can be tracked in the event log.                                 */
986 /*                                                                        */
987 /*  INPUT                                                                 */
988 /*                                                                        */
989 /*    new_posture                           New interrupt posture         */
990 /*                                                                        */
991 /*  OUTPUT                                                                */
992 /*                                                                        */
993 /*    old_posture                           Old interrupt posture         */
994 /*                                                                        */
995 /*  CALLS                                                                 */
996 /*                                                                        */
997 /*    _tx_thread_interrupt_control          Interrupt control service     */
998 /*                                                                        */
999 /*  CALLED BY                                                             */
1000 /*                                                                        */
1001 /*    ThreadX services                                                    */
1002 /*                                                                        */
1003 /*  RELEASE HISTORY                                                       */
1004 /*                                                                        */
1005 /*    DATE              NAME                      DESCRIPTION             */
1006 /*                                                                        */
1007 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
1008 /*                                                                        */
1009 /**************************************************************************/
_tx_el_interrupt_control(UINT new_posture)1010 UINT  _tx_el_interrupt_control(UINT new_posture)
1011 {
1012 
1013 TX_INTERRUPT_SAVE_AREA
1014 UINT    old_posture;
1015 
1016 
1017     TX_EL_NO_INTERRUPT_EVENTS
1018 
1019     TX_DISABLE
1020     TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_INTERRUPT_CONTROL, _tx_thread_current_ptr, new_posture)
1021     TX_RESTORE
1022 
1023     TX_EL_END_FILTER
1024 
1025     old_posture =  _tx_thread_interrupt_control(new_posture);
1026     return(old_posture);
1027 }
1028 
1029 
1030 /**************************************************************************/
1031 /*                                                                        */
1032 /*  FUNCTION                                               RELEASE        */
1033 /*                                                                        */
1034 /*    _tx_el_event_log_on                                 PORTABLE C      */
1035 /*                                                           6.1          */
1036 /*  AUTHOR                                                                */
1037 /*                                                                        */
1038 /*    William E. Lamie, Microsoft Corporation                             */
1039 /*                                                                        */
1040 /*  DESCRIPTION                                                           */
1041 /*                                                                        */
1042 /*    This function disables all event filters.                           */
1043 /*                                                                        */
1044 /*  INPUT                                                                 */
1045 /*                                                                        */
1046 /*    None                                                                */
1047 /*                                                                        */
1048 /*  OUTPUT                                                                */
1049 /*                                                                        */
1050 /*    None                                                                */
1051 /*                                                                        */
1052 /*  CALLS                                                                 */
1053 /*                                                                        */
1054 /*    None                                                                */
1055 /*                                                                        */
1056 /*  CALLED BY                                                             */
1057 /*                                                                        */
1058 /*    Application code                                                    */
1059 /*                                                                        */
1060 /*  RELEASE HISTORY                                                       */
1061 /*                                                                        */
1062 /*    DATE              NAME                      DESCRIPTION             */
1063 /*                                                                        */
1064 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
1065 /*                                                                        */
1066 /**************************************************************************/
_tx_el_event_log_on(void)1067 VOID  _tx_el_event_log_on(void)
1068 {
1069 
1070     /* Disable all event filters.  */
1071     _tx_el_event_filter =  TX_EL_ENABLE_ALL_EVENTS;
1072 }
1073 
1074 
1075 /**************************************************************************/
1076 /*                                                                        */
1077 /*  FUNCTION                                               RELEASE        */
1078 /*                                                                        */
1079 /*    _tx_el_event_log_off                                PORTABLE C      */
1080 /*                                                           6.1          */
1081 /*  AUTHOR                                                                */
1082 /*                                                                        */
1083 /*    William E. Lamie, Microsoft Corporation                             */
1084 /*                                                                        */
1085 /*  DESCRIPTION                                                           */
1086 /*                                                                        */
1087 /*    This function sets all event filters, thereby turning event         */
1088 /*    logging off.                                                        */
1089 /*                                                                        */
1090 /*  INPUT                                                                 */
1091 /*                                                                        */
1092 /*    None                                                                */
1093 /*                                                                        */
1094 /*  OUTPUT                                                                */
1095 /*                                                                        */
1096 /*    None                                                                */
1097 /*                                                                        */
1098 /*  CALLS                                                                 */
1099 /*                                                                        */
1100 /*    None                                                                */
1101 /*                                                                        */
1102 /*  CALLED BY                                                             */
1103 /*                                                                        */
1104 /*    Application code                                                    */
1105 /*                                                                        */
1106 /*  RELEASE HISTORY                                                       */
1107 /*                                                                        */
1108 /*    DATE              NAME                      DESCRIPTION             */
1109 /*                                                                        */
1110 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
1111 /*                                                                        */
1112 /**************************************************************************/
_tx_el_event_log_off(void)1113 VOID  _tx_el_event_log_off(void)
1114 {
1115 
1116     /* Set all event filters.  */
1117     _tx_el_event_filter =  TX_EL_FILTER_ALL_EVENTS;
1118 }
1119 
1120 
1121 /**************************************************************************/
1122 /*                                                                        */
1123 /*  FUNCTION                                               RELEASE        */
1124 /*                                                                        */
1125 /*    _tx_el_event_log_set                                PORTABLE C      */
1126 /*                                                           6.1          */
1127 /*  AUTHOR                                                                */
1128 /*                                                                        */
1129 /*    William E. Lamie, Microsoft Corporation                             */
1130 /*                                                                        */
1131 /*  DESCRIPTION                                                           */
1132 /*                                                                        */
1133 /*    This function sets the events filters specified by the user.        */
1134 /*                                                                        */
1135 /*  INPUT                                                                 */
1136 /*                                                                        */
1137 /*    filter                            Events to filter                  */
1138 /*                                                                        */
1139 /*  OUTPUT                                                                */
1140 /*                                                                        */
1141 /*    None                                                                */
1142 /*                                                                        */
1143 /*  CALLS                                                                 */
1144 /*                                                                        */
1145 /*    None                                                                */
1146 /*                                                                        */
1147 /*  CALLED BY                                                             */
1148 /*                                                                        */
1149 /*    Application code                                                    */
1150 /*                                                                        */
1151 /*  RELEASE HISTORY                                                       */
1152 /*                                                                        */
1153 /*    DATE              NAME                      DESCRIPTION             */
1154 /*                                                                        */
1155 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
1156 /*                                                                        */
1157 /**************************************************************************/
_tx_el_event_filter_set(UINT filter)1158 VOID  _tx_el_event_filter_set(UINT filter)
1159 {
1160 
1161     /* Apply the user event filter.  */
1162     _tx_el_event_filter =  filter;
1163 }
1164 
1165